Andrei
Andrei

Reputation: 56688

Route with optional parameter is not resolved correctly

Here is necessary code to reproduce a very strange problem with ASP.NET MVC 3.0 routing:

Route registration in Global.asax.cs:

routes.MapRoute("History", "Customer/History", new {controller = "User", action = "History", someParam = UrlParameter.Optional});
routes.MapRoute("Default", "{controller}/{action}/{id}", new { controller = "Home", action = "Index", id = UrlParameter.Optional });

Here we declare a route to the user's history. But in the URL we want "Customer" instead of "User". Also please note parameter someParam. Controller User does really exist and has action History.

Now usage in view:

<a href="<%= Url.Action("History", "User") %>">History</a>
<a href="<%= Url.Action("History", "User", new { someParam="qqq" }) %>">History with param</a>

I am using here Url.Action() instead of Html.ActionLink() only for clarity.

And here is the result - how this part of the view was rendered:

<a href="/Customer/History">History</a>
<a href="/User/History?someParam=qqq">History with param</a>

Now the problem is clear - URL without parameters was resolved correctly, while the URL with parameter starts with "/User" instead of "/Customer".

Questions:

  1. Is it a normal behavior? If yes, why does routing work that way?
  2. Is there any workaround for this? I mean is there any way to get the final result as:

    <a href="/Customer/History">History</a>
    <a href="/Customer/History?someParam=qqq">History with param</a>
    

Upvotes: 0

Views: 1249

Answers (1)

Tridus
Tridus

Reputation: 5081

I suspect it's getting confused because your route for Customer doesn't list that extra value, but the default one does. Try this:

routes.MapRoute("History", "Customer/History/{someParam}", new {controller = "User", action = "History", someParam = UrlParameter.Optional});

Or to preserive the query string link syntax, this:

routes.MapRoute("History", "Customer/History/{id}", new {controller = "User", action = "History", id = UrlParameter.Optional});

In the second case you don't supply a value for id when creating the link (your call to Url.Action shouldn't have to change).

Upvotes: 1

Related Questions