Steve Smith's Blog

Musings on Software and the Developer Community

IgnoreRoute in ASP.NET Routing is Order Dependent

I’m wiring up the IoCControllerFactory from MVCContrib into an MVC application and I kept running into an issue where a request was coming in looking for a ContentController.  The reason for this is that in my CSS file I have a property like this:

background: transparent url(images/logo.gif) no-repeat scroll left top;

which is in the Content folder.  The resulting request for “/Content/images/logo.gif” was matching the default routing rule:

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

and the result was that it excpeted to find a controller by the name of Content.  I searched and found this post that had some useful ideas that I tried.  At first, adding this had no effect:

routes.IgnoreRoute("{Content}/{*pathInfo}");

However, once I realized that the order mattered, and moved this to the top of my RegisterRoutes() method, it worked as expected.

I can understand that the ordering of the routes is important, for matching purposes, but it’s not intuitive to me that ignored routes should be order-dependent.  I would think that there would be two lists in the RouteCollection, one for actual routes, and a separate one for ignored route patterns.  The ignored routes would be checked every time, and anything that matched ignored (duh), while the actual routes would be checked in order, with the first matching route determining the appropriate controller to use.  However, this doesn’t appear to be the case.

The following will ignore the Content folder for routing purposes:

   1: public static void RegisterRoutes(RouteCollection routes)
   2: {
   3:     routes.IgnoreRoute("{Content}/{*pathInfo}"); 
   4:  
   5:     routes.MapRoute(
   6:         "Default",                                              // Route name
   7:         "{controller}/{action}/{id}",                           // URL with parameters
   8:         new { controller = "Home", action = "Index", id = "" }  // Parameter defaults
   9:     );
  10: } 

The following will not ignore the Content folder:

   1: public static void RegisterRoutes(RouteCollection routes)
   2: {
   3:     routes.MapRoute(
   4:         "Default",                                              // Route name
   5:         "{controller}/{action}/{id}",                           // URL with parameters
   6:         new { controller = "Home", action = "Index", id = "" }  // Parameter defaults
   7:     );
   8:  
   9:     routes.IgnoreRoute("{Content}/{*pathInfo}");
  10: }

It seems the actual implementation of IgnoreRoute is more of an actual MapRoute that simply maps to nothing.  Thus, it follows all the same ordering logic that MapRoute follows.  Once you make this realization, it makes sense, and of course you’ll want to put your IgnoreRoutes first (assuming you really want them to always be ignored) – otherwise they won’t be ignored.

    kick it on DotNetKicks.com

Tuesday, 12 May 2009

Comments

 avatar

Haacked said on 13 May 2009 at 3:00 AM

By default, routing ignores requests for files that actually exist on disk. Did you change this default or are you missing the logo.gif in the proper directory?


 avatar

Steve said on 13 May 2009 at 6:01 PM

Hi Phil, thanks for the response. In this case the files didn't exist.


 avatar

ben said on 16 Dec 2009 at 5:50 PM

Shouldn't everything be ignored by default? And only mapped if you explicitly map it?