20

I have the following routes defined:

public static void RegisterRoutes(RouteCollection routes)
{
    routes.IgnoreRoute("{resource}.axd/{*pathInfo}");

    routes.MapRoute(name: "Homepage", url: "", defaults: new { controller = "Restaurants", action = "Search" });
    routes.MapRoute(name: "About", url: "about", defaults: new { controller = "Home", action = "About" });
    routes.MapRoute(name: "Disclaimer", url: "disclaimer", defaults: new { controller = "Home", action = "Disclaimer" });
    routes.MapRoute(name: "Contact", url: "contact", defaults: new { controller = "Home", action = "Contact" });
    routes.MapRoute(name: "RestaurantDetails", url: "{id}/{slug}", defaults: new { controller = "Restaurant", action = "Details" });
    routes.MapRoute(name: "RestaurantLocationDetails", url: "{id}/{restaurantSlug}/{locationSlug}", defaults: new { controller = "Restaurant", action = "LocationDetails" });
    routes.MapRoute(name: "Api", url: "api/{action}", defaults: new { controller = "Api" });
}

I found some routes to give a 404, so I installed the RouteDebugger NuGet package.

It shows what I expect for the first 4 routs, but on the last 3 routes I still get a 404 and alas Route Debugger doesn't appear at the bottom of the page - I was hoping it would show me which bits got mapped, but I get nothing. All the views exist.

So I'm assuming I'm making a mistake with the route definitions - can anyone shed any light on this? Also, how can I get Route Debugger to show me how the URL gets mapped into the route dictionary for those pages that return a 404?

skaffman
  • 398,947
  • 96
  • 818
  • 769
Saqib
  • 7,242
  • 7
  • 41
  • 55
  • 2
    I think you need to reverse your RestaurantDetails and RestaurantLocationDetails definitions but I'm not sober so I could be wrong. And I don't know anything about routes. – Joe Phillips May 07 '11 at 00:39
  • 1
    +1 @Joe Phillips for admitting you're not sober :) – Buildstarted May 07 '11 at 00:46
  • 1
    if you're blind (which I find amazing) you should definitely bring your issues up on http://meta.stackoverflow.com/ and your problems in accessing this site. – Buildstarted May 07 '11 at 02:22

1 Answers1

22

You need to change the order of the routes.

routes.MapRoute(name: "Homepage", url: "", defaults: new { controller = "Restaurants", action = "Search" });
routes.MapRoute(name: "About", url: "about", defaults: new { controller = "Home", action = "About" });
routes.MapRoute(name: "Disclaimer", url: "disclaimer", defaults: new { controller = "Home", action = "Disclaimer" });
routes.MapRoute(name: "Contact", url: "contact", defaults: new { controller = "Home", action = "Contact" });
routes.MapRoute(name: "Api", url: "api/{action}", defaults: new { controller = "Api" });
routes.MapRoute(name: "RestaurantLocationDetails", url: "{id}/{restaurantSlug}/{locationSlug}", defaults: new { controller = "Restaurant", action = "LocationDetails" });
routes.MapRoute(name: "RestaurantDetails", url: "{id}/{slug}", defaults: new { controller = "Restaurant", action = "Details" });

The routes are processed in the order in which they're added to the route list.

For example: api/action also matches the RestaurantDetails route since there are only two parameters in the route url parameters.

So it needs to go from specific to general. In general if you have the same number of parameters in two route definitions then the first route added will be the one chosen.

Buildstarted
  • 26,529
  • 10
  • 84
  • 95
  • 1
    Although I think the "api" part of the URL will not match the RestaurantDetails URL will it? – Joe Phillips May 07 '11 at 00:53
  • 1
    It will if `RestaurantDetails` is before the `Api` one because the url segment `api/action` also matches `{id}/{slug}` so if `RestaurantDetails` is before `Api` it will match first. – Buildstarted May 07 '11 at 00:56
  • Thanks very much for the detailed explanation. Makes sense. Putting Api above RestaurantDetails makes that work now. But I can't get restaurantDetails or restaurantLocationDetails to work - I've tried different orderings, and also specifying "" as the defaults for id/slug/etc. I also double checked that the controller/action/parameters matched the method. – Saqib May 07 '11 at 01:35
  • Could you post your example urls (without domain). I tested them with `someid/somerestaurantslug/somelocationslug` and it matches `RestaurantLocationDetails` and `detailid/detailslug` matches the `RestaurantDetails` route – Buildstarted May 07 '11 at 01:37
  • I'm wondering if you're expecting the `restaurantSlug` to be a wildcard match so that you could match `restid/restaurantslugpart1/restaurantslugpart2/locationslugpart1/locationslugpart2` – Buildstarted May 07 '11 at 01:40
  • Got this working now - in addition to the order, there was another one-character typo. . @BuildStarted I really appreciate your explanation/help :-) – Saqib May 07 '11 at 01:53
  • @Saqib, Glad to be of help :) – Buildstarted May 07 '11 at 02:02