I have seen this question a couple of times here in SO but none of them with any acceptable answer:
ASP.NET MVC @Url.Action includes current route data
ASP.NET MVC implicitly adds route values
Basically I have Controller with an action method called Group, it has an overload that receives no parameters and displays a list of elements and another one that receives an id and displays details for that group.
If I do something like this:
Url.Action("Group", "Groups");
From the main page of the site (/) it returns an url like this:
"mysite.com/Groups/Group"
which is alright Now, if the current address of the site is /Groups/Group/1 And I call the same method
Url.Action("Group", "Groups");
the returned url is this:
"mysite.com/Groups/Group/1"
It automatically adds the value of the route for the current page when generating the URL. Even if I generate the URL this way:
Url.Action("Group", "Groups", null);
Thus explicitly specifying that I don't want any route values, the generated URL is the same. To get the address I want I have to explicitly set the route value to an empty string, like so:
Url.Action("Group", "Groups", new {id=""});
This will generate the following url:
"mysite.com/Groups/Group"
My question is, why does this happen? If I don't set any route values it shouldn't add them to the generated URL.
A simple workaround would be first to call
and then rename dummy in the resulting string to the correct action name.
Simple example:
Edit view contains only this:
So when you run your site e.g.
localhost:randomPort/Product/Edit/123
you get next response:/Product/Detail/123
Why? Because
Route
attribute has required parameterid
. Id parameter is read from url, although we wrote onlyUrl.Action(methodName, controller)
- without specifying parameter. Also it doesn't make sense to have a method detail without id.In order for attributes to work next line must be added to
RouteConfig.cs
:Url.Action will reuse the current request parameters, if you do not explicitly set them. It is by design in outbound url-matching algorithm. When looking for the route data parameters in a process of generating url, parameters are taken from:
1) explicitly provided values
2) values from the current request
3) defaults
In the order I specified above.
Outbound matching algorithm for routes is complicated, so it is good practice to explicitly set all parameters for request, as you did in your example
So when I read objectbox's answer I thought I would have to modify several links in my code. I then tried adding a default route omitting the default parameters which solved the problem:
A silly workaround I found that works to handle the current page routing data, including changing the page parameter upon your preferences
My application explicitly sets route values and does not want a magical value from the current request. I want to be in full control.
I have made an extension which coexists with my route library collection. Hence the single RouteValueDictionary param. (See my Route library comment at the bottom)
Here I remove any routevalues from the request prior to generating a url.
(note: for the array.contains ignorecase part, see: How can I make Array.Contains case-insensitive on a string array?)
I have Form and ActionLink extension methods that uses the RemoveRoutes method. No helper in my mvc library uses a method that is not an extension method i have created. Thereby, all routedata is cleaned up before generating urls.
For reference I use AttributeRouting. Here is an example of one route from my route library.