ASP.NET MVC URL Routing with Multiple Route Values

asp.netasp.net MvcUrl Routing

asp.net Problem Overview


I am having trouble with Html.ActionLink when I have a route that takes more than one parameter. For example, given the following routes defined in my Global.asax file:

routes.MapRoute(
    "Default",                                              // Route name
    "{controller}.mvc/{action}/{id}",                           // URL with parameters
    new { controller = "Home", action = "Index", id = "" }  // Parameter defaults
);

routes.MapRoute(
    "Tagging",
    "{controller}.mvc/{action}/{tags}",
    new { controller = "Products", action = "Index", tags = "" }
);

routes.MapRoute(
    "SlugsAfterId",
    "{controller}.mvc/{action}/{id}/{slug}",
    new { controller = "Products", action = "Browse", id = "", slug = "" }
);

The first two routes work without a problem, but when I try to create an action link to the third route using:

<%= Html.ActionLink(Html.Encode(product.Name), "Details", new { id = product.ProductId, slug = Html.Encode(product.Name) }) %>

I end up with a URL like [site-root]/Details/1?slug=url-slug whereas I would like the URL to be more like [site-root]/Details/1/url-slug

Can anyone see where I am going wrong?

asp.net Solutions


Solution 1 - asp.net

It is using the first route that is fully satisfied. Try putting your SlugsAfterId route above the Default one.

It's basically going: "Check Default. Got an action? Yes. Got an id? Yes. Use this one and chuck any other parameters in the querystring."

As a side note, doing that will make your Default route redundant as you provide a default value for the slug parameter.

Solution 2 - asp.net

Garry (above) is correct. You can use Mr. Haack's route debugger for MVC. It can help resolve routing issues by showing you which routes are hit and when.

Here is the Blog Post. And here is the Zip File.

Solution 3 - asp.net

You could add a Constraint to your Routes that contain "id" since it's presumably only to accept a number. This way the first route will only match when the "id" is numeric, then it would make the second route for all other values. Then place the one that includes the {slug} at the top and everything should work correctly.

routes.MapRoute(
    "SlugsAfterId",
    "{controller}.mvc/{action}/{id}/{slug}",
    new { controller = "Products", action = "Browse", id = "", slug = "" },
    new { id = @"\d+" }
);

routes.MapRoute(
    "Default",                                              // Route name
    "{controller}.mvc/{action}/{id}",                           // URL with parameters
    new { controller = "Home", action = "Index", id = "" },  // Parameter defaults
    new { id = @"\d+" }
);

routes.MapRoute(
    "Tagging",
    "{controller}.mvc/{action}/{tags}",
    new { controller = "Products", action = "Index", tags = "" }
);

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionIan OxleyView Question on Stackoverflow
Solution 1 - asp.netGarry ShutlerView Answer on Stackoverflow
Solution 2 - asp.netMunkiPhDView Answer on Stackoverflow
Solution 3 - asp.netChris PietschmannView Answer on Stackoverflow