Custom MapRoute

Chris picture Chris · May 23, 2012 · Viewed 16.9k times · Source

I am attempting to create some custom map routes but can't get it working quite right.

My ultimate aim is to be able to specify something like the following. Where by I essentially have my URL constructed with value pairs of "id" and "name". The name is irrelevant and solely for user pleasantries, I will require the ID in my controller though.

/dashboards/5-My-Estate-name/89-My-subgroup-name/133-Maybe-even-another-subgroup

For starters I'm working on the first section and having troubles.

Browsing to "http://localhost:53933/dashboards/109-building-xyz" whilst using the following route generates the error A public action method '109-building-xyz' was not found on controller 'MyInterfaceInterface.Controllers.DashboardsController'.

routes.MapRoute(
  "Dashboard",
  "dashboards/{id}-{name}", // URL pattern
   new { controller = "Dashboards", action = "Index" },
   new { id = @"\d+", name = UrlParameter.Optional }
);

Obviously I wanted this to be routed to the Index function with parameters.

What am I doing wrong? Am I even structuring this correctly? I come from a web-PHP background and using htaccess to achieve such things.

Thanks

Answer

danludwig picture danludwig · May 23, 2012

The order of routes matter. MVC will match the first declared route with a pattern that matches the URL pattern.

So if you have this:

routes.MapRoute(
  "Default",
  "{controller}/{action}/{id}", // URL pattern
   new { controller = "Home", action = "Index" },
   new { id = UrlParameter.Optional }
);
routes.MapRoute(
  "Dashboard",
  "dashboards/{id}-{name}", // URL pattern
   new { controller = "Dashboards", action = "Index" },
   new { id = @"\d+", name = UrlParameter.Optional }
);

Then what will happen with the URL http://localhost:53933/dashboards/109-building-xyz is that MVC will match "dashboards" to the controller and "109-building-xyz" to the action.

You need to always declare your most specific routes first, and more general routes afterward, like so:

routes.MapRoute(
  "Dashboard",
  "dashboards/{id}-{name}", // URL pattern
   new { controller = "Dashboards", action = "Index" },
   new { id = @"\d+", name = UrlParameter.Optional }
);
routes.MapRoute(
  "Default",
  "{controller}/{action}/{id}", // URL pattern
   new { controller = "Home", action = "Index" },
   new { id = UrlParameter.Optional }
);

However, Morten Mertner is right in his comment -- I don't think you can have 2 route parameters that are not separated by a forward slash. You would need to change your URL pattern to something like this in order to use it with the default routing engine:

"dashboards/{id}/{name}"