Lets say we have this route:
routes.MapRoute(
"Library",
"Lib/{id}/{lang}",
New With {.controller = "MyLibrary", .action = "ShowItem", .id= 0, .lang = "en"}
)
And lets say we request this url:
http://localhost/Lib/10/de
so now we have this route values: id = 10 & lang = de
Here is the problem:
This code:
<%= Url.Action("ShowItem", New With {.id = 45})%>
returns:
http://localhost/Lib/45/de
It changes id but preserves lang.
But this code:
<%= Url.RouteUrl("Library", New With {.id = 45})%>
returns:
http://localhost/Lib/45
It changes id but removes lang!
Is this a bug or what? I know how to fix this, but this different behavior is very confusing. Am I right? Or just imagining this?
One quick fix would be:
<%= Url.RouteUrl("Library", New With {.id = 45},.lang = RouteData.Values("lang"))%>
Ok so the theoretically correct expected mvc behaviour here is that it shouldn’t reuse variables from the current request if they occur in a later segment than one you specify. So I’m wondering if you have some other routes defined as what you are describing isn’t quite right so could it be matching something else. If not it may be a bug.
Regardless because this above behaviour (when its working!) is pretty confusing, best practice is to supply all the segment variables when creating links, using UrlParameter.Optional as described above. Then you don’t have to worry about this ambiguity.
For what it is worth, the second result you are seeing (i.e. RouteUrl) is the correct behaviour. The Action should be behaving the same.