Url.Action generates wrong url

Hi,

I am trying to call @Url.Action(…) from myView like below:
<a href="@Url.Action("Index", "Customer")">Link</a>

The url that is generated is: {mylocaladdress}/site.axd/Customer which doesn’t work. And if I try to go to that link I get a NullReferenceException in Litium.Accelerator.Mvc\Routing\SearchQueryMapper.cs
where _routeRequestInfoAccessor.RouteRequestInfo seems to be null.

@Url.Action(…) is used exactly in the same way I am trying to do in the partialView _AlreadyLoggedIn.cshtml in the accelerator as below:
<a href="@Url.Action("Logout", "Login")" class="form__button"><i class="fa fa-sign-out"></i>@Html.WebSiteString("login.logout")</a>
and the generated url for this is: {mylocaladdress}/inloggning.Logout

But I can’t figure it out why my call doesn’t work.
What am I missing?

Litium version: 7.2.0

It exists a similar post for Litium 6 but the concept is the same, will Html.ActionLink in Litium 6 MVC help you?

Not really. I want to know why the one that is used in the standard accelerator works but not mine, despite of they are implemented exactly in the same way (At least what I can see)?

I looked some other posts that I thought that they could be relevant to my problem, but still nothing :confused:

When you do regular MVC @Url.Action("Index", "Customer") the action-helper will find the CustomerController that is registered. This is registered in App_Start\RouteConfig.cs file in the web-project and looks as below and the url will be generated as /site.axd/customer. If you executing the LoginController and it is that one that is generating the link, the mvc-action extensions probably see that it is the same controller that is requested and using the same url that the user have requested.

            routes.MapRoute(
                "ControllerDirect", // Route name
                "site.axd/{controller}/{action}/{id}", // URL with parameters
                new { action = "Index", id = UrlParameter.Optional } // Parameter defaults
                );

When the user will click on the link, the url it will bypassing Litium’s url routing and passing the request down to the CustomerController directly without setting the RouteRequestInfoAccessor.RouteRequestInfo (that is part of Litium’s url routing) and for the controller the RouteRequestInfoAccessor.RouteRequestInfo is needed so the usage will throw the NullReferenceException.

If you check Views\Mypages\index.cshtml you can find the below code that will generate the correct url because it using the Litium-extension method for LinkFor.

@Html.LinkFor(x => x.LogoutLink, "login.logout".AsWebSiteString())

In the NuGet package Litium.Web.Mvc.Abstractions it exits extensions methods that will help you to create links or write images from our model objects (only some example).

Thank you Patric for this explanation.

In my CustomView if I call @Url.Action(“Index”, “Customer”), this will cause the nullException and so on. But if change @Url.Action(“Index”, “Customer”) to @Url.Action(“Logout”, “Login”) in the same view then it works fine. This is what I don’t understand why? Why is RouteRequestInfoAccessor.RouteRequestInfo not needed for LoginController but it is needed for my CustomerController, and is it possible to solve this, if it is, then how?

I know that I can solve this in some other ways, e.g. like your example, by getting the link through the model but I want to understand the problem.

I cant answer for why @Url.Action(“Index”, “Customer”) is throwing an NRE, it is a custom added controller so I cant test in my installation. When you do the @Url.Action(“Logout”, “Login”) will that generate a link to the /site.axd/login/logout? The Logout action in the default LoginController from accelerator is not using any services that are dependent on the RouteRequestInfoAccessor.RouteRequestInfo, that will mean that this controller can be executed by the default mvc handler without a need of the request information that litium can parse from the url.

If you wan’t us to understand your code and why that behave as it do you can always open a support ticket and we can try to help out and understand this specific case.

Yes it does.

Is it possible to identify what services are using RouteRequestInfoAccessor.RouteRequestInfo?

Yes, in your solution, do a test-search for RouteRequestInfoAccessor or use the Find All References in the context menu of the item.


In this specific case I think you can find the where the NRE is throwing if you debug your solution.

On Line 57: var productPageData = _routeRequestInfoAccessor.RouteRequestInfo.Data as ProductPageData;

However, this is now solved by adding a pointer to the page and pass the link to the view.
I will follow up this with litium support.

Thanks for your replies! :slight_smile:

If you want to render a controller that need information from Litium, you need to get the url that is for that page, either with passing the page into the extension method or building the url manually. It is not possible to use standard Mvc actions that need information from Litium when you bypass Litium url-handling.