I have a question that has pretty much been asked here:
asp.net mvc Html.ActionLink() keeping route value I don't want
However, the final solution is a kludge, pure and simple and I really would like to understand why this happens, if someone can please explain it to me?
For completeness, it is possible to recreate the scenario very easily:
- Create a new MVC web app.
- Run it up.
- Visit the About tab Modify the URL to read /Home/About/Flib - This obviously takes you to the action with an id of 'Flib' which we don't care about.
Notice that the top menu link to About now actually links to /Home/About/Flib - this is wrong as far as I can see, as I now have absolutely no way of using site links to get back to /Home/About
I really don't understand why I should be forced to modify all of my Html.ActionLinks to include new { id = string.Empty }
for the routevalues and null for the htmlAttribs. This seems especially out of whack because I already specify id = 0
as part of the route itself.
Hopefully I'm missing a trick here.
If you either don't know what values need to be explicitly overridden or you just want to avoid the extra list of parameters you can use an extension method like the below.
The implementation details are in this blog post
When you look into the source code for the action link you find that
will match
Now so far this looks good since it is creating a new route value dictionary so it is not passing along the values in your current context to be added to the new link, which is what will happen.
However, further down in the code where the url is being generated:
you can see the requestContext being referenced which has access to the routeData and routeCollections, which will contain the id data. When creating the VirtualPathForArea, the following line is where the id value appears in your url:
The line:
takes the virtual path (which is just the route) and returns it. So the virtual path would be
/Home/About/Flib
Then when that virtual path is returned the following line uses it to set the client url for the action link:
So pretty much it looks like the actionlink is set using the virtual path for the area, which is just the route that was matched, which happens to be the default route in this case.
If I understand correctly, it sounds like you need to register a second "Action Only" route and use Html.RouteLink. First register a route like this in you application start up:
Then instead of ActionLink to create those links use: