MVC 4 HomeController constructor and action always fired - c#

I've been looking for a solution for 2 days now. Maybe I'm mind blocked so I have to ask for help.
I have a project in MVC 4 which has many controllers, models and views. I kept the HomeController and used the Index action as the default entry for the site. There I have a grid, something like this:
<div class="ui-grid-b home-icon-grid">
<div class="ui-block-a"><div class="home-icon" style="background-color:#b13a3a"><i class="fa fa-3x fa-shopping-cart"></div><div class="icon-title">#Mobile.Resources.Resources.resCart</div></div>
<div class="ui-block-c"><div class="home-icon" style="background-color:#1c70ef"><i class="fa fa-3x fa-tags"></i></div><div class="icon-title">#Mobile.Resources.Resources.resItems</div></div>
<div class="ui-block-c"><div class="home-icon" style="background-color:#6b6b6b"><i class="fa fa-3x fa-gear"></i></div><div class="icon-title">#Mobile.Resources.Resources.resSettings</div></div>
</div>
As expected, every time I start debugging, I can see the method
public ActionResult Index() {code}
in HomeController.cs is fired.
Also, in Fiddler I see the following at the beggining:
Host: localhost:55883
URL: /
(Sorry I don't post images, I don't have enough reputation yet)
So far so good. Now, when I click on one of the links in the grid, let's say "Items". I expect to see the Products list, and I do, but if I'm debugging, I see that the Index method in the HomeController is fired as well. An then the Category method in ProductsController is called.
And not only that. Let's say I'm seeing the Products list, and I click in some other link (which go to other view, I've tested many cases) the HomeController Index() is called too.
In Fiddler, when I click the Items link, I see first "/" in the URL column, and then the "Products/Category/ROOT" one.
Following the example, in that view, I clicked over a link which go to "Search/Result", in Fiddler I see "/" and then "Search/Result?productCategory=..."
This happens in all over the site. Every time I click on an anchor, Home/Index is called first, and then the selected path.
I even tried using a simple anchor:
Google
And again, first the Home/Index, and then it redirected to Google.
I suppose it could be related to Route Configuration, or maybe there's something with POSTs being made. Maybe is the normal flow in the mvc life cycle and I'm freaking out over nothing, hehe.
Any ideas? Thanks in advance. I hope I was clear enough.

Many modern browsers "preload" linked pages. So when you load a page, it may also load pages that are linked to those pages. So if you have links back to your home page, then those pages might be loaded by the browser to improve performance.

Related

blazor not changing the page when clicking on a link

I am migrating my personal blog to Blazor, and I have a problem. I was developing the "next post" functionality and blazor (or the browser) is not redirecting the user when a link is clicked. the post are "the same page" under the next route #page "/post/{Url}
For example the user is in domain.com/post/foo and in that site there is a link to domain.com/post/bar.
It is a simple link, like the next:
<a href="post/bar" title="#Post.Title">
#Post.Title
</a>
When the user clicks on the link the url for the browser changes, and the location of the page moves to the top, but the page content is not changing.
I noticed that this behaviour is happening when I click from a post page into another, but is not happening from the "index" of the site (/) or when I click the tags on the post, which links to domain.com/tags/{tag}.
one thing to notice is that if I select the url in the browser and click enter or refresh the page it actually goes to the page i clicked on, in this case domain.com/post/bar
My question is, is this actually expected behavior or is it a bug? if it is expected behaviour, is there any way of making the url to actually go to the clicked url and not stay in the same page.
I am using net5.0 if that matters.
Thanks.
As an add on to #enet's answer, you're probably fetching the post referenced by the Url property in OnInitialized/OnInitializedAsync. See the last long paragraph in #enet's answer.
One way to address this is:
place the code to load data in a separate method say LoadDataAsync
in SetParameters/SetParametersAsync detect if the data reference - in your case Url - has changed in , and if so call LoadDataAsync.
The key here is understand component lifecycle and getting the code in the right place.
Put breakpoints in on OnInitialized and SetParameters and watch when they get hit when you load and do navigation.
when I click from a post page into another
post in domain.com/post/foo and domain.com/post/bar is definitely not a page but a literal path segment.
I've created a routable component named Foo:
Foo.razor
#page "/post/foo"
#code {
}
Foo is a routable component; that is, it is a page, and can be accessed by typing the url in the address bar of your browser, using an anchor element or the NavigationManager. You may embed it in a parent component as well.
post is, as I've said above, a literal path segment
But if you insist that post is actually a component page, then I guess it may look something like this:
Post.razor
#page "/post"
#page "/post/{Param}"
<a href="post/bar" title="Title">
Title
</a>
<div>#Param</div>
#code {
[Parameter]
public string Param {get;set;}
}
Now, when you type in the address bar a url like this:
https://localhost:<port-number>/post
You'll be navigated to the post routable component (page)
If you click on the anchor element, the url in the address bar will change to https://localhost:<port-number>/post/bar
bar is not a component; it is a parameter. The address bar changes, but you seem to be in the same post component, the data or content, however, do changes...
Note that when you click on the anchor element, you are being navigated to
a new Url ("post/bar"), but rendering engine does not create a new instance of the Post component in order to render the page, but instead it treats it as the same page with changed parameters. Thus it looks like no navigation has taken place, and nothing has changed, except the url in the address bar. I'm not claiming that your issue is the same, but it may stem from similar code usage.
Note that since Blazor does not create a new component instance, but uses the existing one, the OnInitialized(Async) pairs can only run once... So you'll have to use the SetParametersAsync method (" on initializedAsync is getting the "nextPost" information from the backend, but its just a plain http cal")
All the above was intended to ask you to do the simplest thing and provide the route templates........
Is bar a component?
Is foo a component?
Answer withdrawn as it breaks some component parameter recommendations by ASPNetCore Team - see https://github.com/dotnet/aspnetcore/issues/24599

Controller's action is getting called twice while loading a view

I am working on an asp.net core application where I am loading a view on click of a hyperlink. The view loads fine but what strange thing happening here is whenever I click on the hyperlink, call to controller's action goes twice. I accidently found this issue when I put debug point on the action method and it got hit twice. Then I also checked the network traffic tab in the browser, there also I noticed 2 calls to controller action got recorded twice.
Markup of hyperlink in layout page:
<li><a asp-action="ApplyLeave" asp-controller="Home">Apply Leave</a></li>
Controller's action method:
[HttpGet]
public IActionResult ApplyLeave()
{
.......
.......
.......
return View();
}
ApplyLeave.cshtml
#{
ViewData["Title"] = "Apply Leave";
}
<header class="page-header">
<div class="container-fluid">
<div class="row">
<div class="col-12">
<h2 class="no-margin-bottom">
Apply Leave
</h2>
</div>
</div>
</div>
</header>
Screenshot of network traffic captured in browser:
Kindly help me in resolving this issue, thanks in advance!
If you see your request in console window on network tab, there is two kind of request:-
1: Doc Type
2: XmlHttpRequest
Doc type request is coming from the View which is action link where action method name is mention, but if you see another request then, this request comes from Javascript environment.
Please see the official definition of XMLHttpRequest:-
XMLHttpRequest (XHR) is an API in the form of an object whose methods transfer data between a web browser and a web server. The object is provided by the browser's JavaScript environment.
Please validate once your JS part.
Thanks you all for your kind attention on this.
I have site.js where I am keeping all the script code and code for ajax calls.
There was an ajax call which was intended to be called on a particular page, but due to improper code, that ajax call was triggering after every other page load.
So I corrected the code for that ajax call and now I am not seeing any duplicate call to controller, everything is working fine.
Thanks everyone.

Sending data to header of _Layout.cshtml regardless of what page the user is on

I have a notifications badge in the header of my _Layout.cshtml file. This is so I can constantly show the user their notifications regardless of what page they are on.
Notifications <span class="badge">#ViewData["NotificationCount"]</span><br>
However, I am wondering if there are better ways to do this. It seems like I need to do the following at the top of every single one of my views:
#{
ViewData["ReminderCount"] = Model.Notifications.Count();
}
This also means I need to have a list of notifications as part of every single page ViewModel throughout my application.
Am I missing something here? I feel like there has to be a better way to handle things like this in ASP.NET MVC.
The ideal thing would be to load the user's notifications one time as soon as they login and go to their dashboard and then continue to show that number across all pages unless they check the notifications, then the number clears.
What you can do is create an action and against that action create a partial view and in the _Layout.cshtml call it, this will save you from code duplication and ViewData :
You action code will look like:
public ActionResult Notifications()
{
var model = Model.Notifications.Count();
return View("_NotificationsPartial",model);
}
your partial view _NotificationsPartial.cshtml would be like:
#model System.Int32
<a href="#">Notifications
<span class="badge">#Model</span>
Now you just need to call it in your _Layout.csthml:
#Html.Action("Notifications","SomeController")

Trouble loading a partial view from a different controller with model data

Quite new to MVC so please bear with me. I'm trying to load a partial view in a modal from a different controller and everytime I try to view it I get just an empty modal. I believe it is because I haven't been able to instantiate my model in the view.
E.g. I have a Controller 'Home' with a method 'Details' that returns a partialview from a different View folder. The native model to the controller is 'model', whereas the model belonging to my other controller is 'model2'.
public ActionResult Details() {
model2.User = user; //this is a global variable
model2.GetDetails();
return PartialView("~/Views/...Details", model2);
}
I'm sure the reason is because i'm missing the model data in the view. I tried adding another #model... to the view but clearly this doesn't work.
Is there a way of doing what I am trying to accomplish? It can even be a relatively dirty solution as this is a stopgap solution for the time being.
Reading back over this post it reads a little convoluted so if any clarification is needed please let me know.
Thanks
I faced this problem once before and i think it's a lot of work to reproduce it to provide an exact solution, but I can offer my 2 cents. The thing with browser Modals is that you need to provide a url when you are opening it. The URL will have to be the Controller/Action url and this is the tricky part which causes the problem. If you can figure that out, you should be able to solve the problem. If you can't, you can do one of the following:
1. Set the HTML content of Modal dialog from your main window's JS code after the Modal is opened.
2. Use one of the 3rd party HTML/CSS modal implementation, and set the HTML content from the JS code. In this case there is no browser modal and everything is on the same page.
To verify if the view is returning correctly from XHR, put the actionRoute URL in the browser address bar and you will see the content getting returned. It will help with troubleshooting.

Closing C# ASP.Net MVC4 Application with a Close Button

I am going to ask the dumnest question ever. I am creating a C# ASP.Net MVC4 application. I want a button on the index page that will shut the application down and close the browser. How do I do it? I currently have the following code snippet in my Index.cshtml to give a button:
#using (Html.BeginForm("CloseApplication", "Home", FormMethod.Post))
{
<input id="close" name="closeButton" type="submit" style="width:170px" value="Close Application" />
}
I am going to a CloseApplication ActionResult method in my HomeController.cs which currently looks like:
public ViewResult CloseApplication()
{
// Something to do here I think
return null;
}
What do I do here?
Am I over complicating things?
Many thanks to all of you who contribute regularly and help us out.
Honestly think you are over-complicating things for yourself.
HTTP is stateless so by the time you have rendered a page onto the client's browser, your connections, etc, should have already been Dispose'd and the instance of the controller that returned the view the client is now looking at should no longer exist. The next request the client makes will spin up a whole other controller instance.
So the user can already "close" their "instance" (from their perspective) of the application by closing their browser - adding a button to do this is kind of pointless IMHO!

Categories