Search code examples
c#asp.net-mvcrazorasp.net-mvc-routingmaproute

Custom MapRoute


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


Solution

  • 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}"