ASP.NET MVC 4 Routes - controller/id vs controller/action/id

Arman Bimatov picture Arman Bimatov · Aug 4, 2013 · Viewed 32.5k times · Source

I'm trying to add a route to the default one, so that I have both urls working:

  1. http://www.mywebsite.com/users/create
  2. http://www.mywebsite.com/users/1

This will make the first route work:

routes.MapRoute(
     name: "Default",
     url: "{controller}/{action}/{id}",
     defaults: new { controller = "users", action = "Index", id = UrlParameter.Optional }
);

However, the second route won't work obviously.

This will make the second route work, but will break the first one:

routes.MapRoute(
     name: "Book",
     url: "books/{id}",
     defaults: new { controller = "users", action = "Details" }
);

How to combine the two route configurations so that both URLs work? I apologize if there is already a question like this on SO, I wasn't able to find anything.

Answer

McGarnagle picture McGarnagle · Aug 4, 2013

The key is to put more specific routes first. So put the "Book" route first. Edit I guess you also need a constraint to only allow numbers to match the "id" part of this route. End edit

routes.MapRoute(
    name: "Book",
    url: "books/{id}",
    defaults: new { controller = "users", action = "Details" },
    constraints: new { id = @"\d+" }
);

routes.MapRoute(
    name: "Default",
    url: "{controller}/{action}/{id}",
    defaults: new { controller = "users", action = "Index", id = UrlParameter.Optional }
);

And ensure that the "id" parameter in your "Details" action is an int:

// "users" controller
public ActionResult books(int id)
{
    // ...
}

This way, the "Books" route will not catch a URL like /users/create (since the second parameter is reqiured to be a number), and so will fall through to the next ("Default") route.