Reputation: 1193
I'm trying to achieve this goal of changing my apps routes to look like this:
hxxp://host/MyController/Widgets/3/AddWhatsit
The view for this route would help a user add a Whatsit to Widget 3.
Similarly, I would expect the route to create a new Widget to be:
hxxp://host/MyController/Widgets/Create
I've created separate routes to try and facilitate this. They are:
routes.MapRoute("DefaultAction",
"{controller}/{action}",
new {controller = "Home", action = "Index"});
routes.MapRoute("Default",
"{controller}/{id}/{action}",
new {controller = "Home", action = "Index", id = UrlParameter.Optional});
The problem I'm having is that when I browse to the Index page for Widgets (/MyController/Widgets, matching the "DefaultAction" route) Any ActionLinks that would introduce a new url parameter that's not part of that route gets turned into a querystring value. So, for example, the edit link for Widget 3 would render as:
Widget/Edit?id=3
instead of (what I would prefer):
Widget/3/Edit
I guess I understand that I'm messing things up by not putting my (optional) id param at the end of the route.
Should I suck it up and just leave id at the end of the route?
Upvotes: 2
Views: 613
Reputation: 39807
I believe you need to change the order of your routes. Remember, that MVC looks down the route list and picks the First matching route. Your second route with the ID parameter is more specific and as such, should come first in your routing table.
Even though you have specified an ID parameter in your ActionLink, you have also specified a controller and an action. Therefore, the first route is being chosen by the RoutingEngine.
Lastly, remove the optional parameter for the ID attribute. Since you want that route to be chosen when you have an Id, then you do not want that to be an optional parameter, you want it to be required to match that route.
routes.MapRoute("Default","{controller}/{id}/{action}",
new {controller = "Home", action = "Index"});
routes.MapRoute("DefaultAction", "{controller}/{action}",
new {controller = "Home", action = "Index"});
Upvotes: 1
Reputation: 26687
It is possible to achieve this. To get anchor link looking like /Home/1/Index, set routes like:
public static void RegisterRoutes(RouteCollection routes)
{
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.MapRoute(
name: "Custom",
url: "{controller}/{id}/{action}"
);
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
);
}
And then, in the View:
@Html.ActionLink("Here", "Index", "Home", new { id = 5 }, null)
And you get link rendered like this:
<a href="/Home/5/Index">Here</a>
Quirk is to constrain custom route. I removed defaults in this case, they do not make sense. And order of routes, of course.
Upvotes: 2