Make Routing Ignore Requests For A File Extension

asp.net mvc, asp.net 0 comments suggest edit

By default, ASP.NET Routing ignores requests for files that do not exist on disk. I explained the reason for this in a previous post on upcoming routing changes.

Long story short, we didn’t want routing to attempt to route requests for static files such as images. Unfortunately, this caused us a headache when we remembered that many features of ASP.NET make requests for .axd files which do not exist on disk.

To fix this, we included a new extension method on RouteCollection, IgnoreRoute, that creates a Route mapped to the StopRoutingHandler route handler (class that implements IRouteHandler). Effectively, any request that matches an “ignore route” will be ignored by routing and normal ASP.NET handling will occur based on existing http handler mappings.

Hence in our default template, you’ll notice we have the following route defined.

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

This handles the standard .axd requests.

However, there are other cases where you might have requests for files that don’t exist on disk. For example, if you register an HTTP Handler directly to a type that implements IHttpHandler. Not to mention requests for favicon.ico that the browser makes automatically. ASP.NET Routing attempts to route these requests to a controller.

One solution to this is to add an appropriate ignore route to indicate that routing should ignore these requests. Unfortunately, we can’t do something like this: {*path}.aspx/{*pathinfo}

We only allow one catch-all route and it must happen at the end of the URL. However, you can take the following approach. In this example, I added the following two routes.

routes.IgnoreRoute("{*allaspx}", new {allaspx=@".*\.aspx(/.*)?"});
routes.IgnoreRoute("{*favicon}", new {favicon=@"(.*/)?favicon.ico(/.*)?"});

What I’m doing here is a technique Eilon showed me which is to map all URLs to these routes, but then restrict which routes to ignore via the constraints dictionary. So in this case, these routes will match (and thus ignore) all requests for favicon.ico (no matter which directory) as well as requests for a .aspx file. Since we told routing to ignore these requests, normal ASP.NET processing of these requests will occur.

Technorati Tags: aspnetmvc,routing

Found a typo or error? Suggest an edit! If accepted, your contribution is listed automatically here.

Comments

avatar

31 responses

  1. Avatar for Kyle Banashek
    Kyle Banashek July 14th, 2008

    I do not understand what we are supposed to see upon completing this step:
    "Remove the first route above, recompile, and try again and you’ll see an error message."
    The only time I see the 'It worked!' message is when I request for errors.aspx.
    Please clarify.
    Thanks
    Kyle

  2. Avatar for Kyle Banashek
    Kyle Banashek July 14th, 2008

    ahh...nevermind I figured it out....at least i believe i did.
    I see now that by modifying the web.config to the following:
    <add verb="*" path="*.aspx" type="IgnoreRouteWeb.ErrorHttpHandler"/>
    We can 'catch' all .aspx page requests and handle as we desire.
    Nice work!
    Thanks
    Kyle

  3. Avatar for haacked
    haacked July 14th, 2008

    I meant remove the route: routes.IgnoreRoute("{*allaspx}", new {allaspx=@".*\.aspx(/.*)?"}); and then try to hit /Errors.aspx. You should see an error.

  4. Avatar for Steve Smith
    Steve Smith July 14th, 2008

    Hey Phil,
    I know previously routes didn't involve regular expressions, though many people get that impression upon first seeing them. I have to say that your IgnoreRoute syntax looks an awful lot like a regex. When did the use of regular expressions combine with routes (or has it, in any holistic fashion)? Perhaps you could comment on where regular expressions are supported and where not, to clear up any confusion (or at least mine). Thanks!

  5. Avatar for Sean Lynch
    Sean Lynch July 14th, 2008

    The regex in this case isn't so much defining the route as it is limiting which routes are valid for a specific URL.
    So while it has generally the same effect, you do not get the catch all parsed nicely into the route values collection, or passed in as parameters to the action, just the single catchall.
    Though I could be wrong.

  6. Avatar for haacked
    haacked July 14th, 2008

    @Steve What Sean said is exactly correct. The route URL in the ignor routes happen to be "catch-all" routes, meaning they match everything. They are not regexes.
    The part *after* the route URL is the Constraints dictionary used to constrain what URLs the route will match. That part does use regex by default for fine grained control over matching.

  7. Avatar for Steve Sanderson
    Steve Sanderson July 14th, 2008

    Minor (but consequential!) typo:
    > By default, ASP.NET Routing ignores requests for files
    > that do not exist on disk.
    I think you mean it ignores requests for files that *do* appear on disk :)

  8. Avatar for mark
    mark July 14th, 2008

    Hi, whats the difference from adding and not adding:
    routes.IgnoreRoute("{*allaspx}", new {allaspx=@".*\.aspx(/.*)?"});
    when i didn't have that, my .aspx pages still works.

  9. Avatar for haacked
    haacked July 15th, 2008

    @Steve Doh! Thanks for catching that. Fixed.
    @Mark That's for the case where you map a .aspx URL to an HttpHandler. For example, when using ELMAH, you can map /Errors.aspx to the ELMAH handler. In that case, /Errors.aspx doesn't actually exist on disk, in which case Routing attempts to route the request for /Errors.aspx.
    Take a look at the example project linked to in this post and you'll see what I mean.

  10. Avatar for evan
    evan July 15th, 2008

    Maybe it's just me but I am finding the usage of all these anonymous type parameters in the MVC framework really resistant to exploration and understanding. To me they are non obvious and not self explanatory.
    On another note . . . is there going to be a pure regex route handler pushed out by the MVC team? Many people who are very accustomed to using regexes would greatly prefer them over the tokenized routes. Well at least I know I would :)

  11. Avatar for haacked
    haacked July 16th, 2008

    @evan each of those methods contain overloads for passing in a proper RouteValueDictionary. So you can take the approach that you think is best.
    We don't have any current plans on releasing a pure regex handler. If you want to use regex to simply match routes, then you can use catch-all routes + constraints (since constraints are regex by default). But URL generation won't work too well with that (which is the benefit of the tokenization).
    Or write a custom implementation of RouteBase that uses regex. Just keep in mind, that an implementation of RouteBase should also implement URL generation, not just route matching.

  12. Avatar for Mr Latty
    Mr Latty July 20th, 2008

    Not anything to add but wanted to give you praise for the find!

  13. Avatar for Tim Hardy
    Tim Hardy July 23rd, 2008

    I'm having a lot of problems with Application_BeginRequest getting called many times on a single request. I'm using Preview 4, IIS7, and I've even added your route ignores from above. From watching in Fiddler or Firebug, it seems like every js, css, and even some gif files are triggering BeginRequest. No one else seems to be seeing this behavior, except a co-worker, who is just as stuck as I am. Any insight into how we can stop ASP.NET from handling static files would be much appreciated.

  14. Avatar for Kyle Banashek
    Kyle Banashek July 23rd, 2008

    Has anyone ran across an exception handling solution for an invalid controller name specified in a request?

    Thanks
    Kyle

  15. Avatar for Tim Hardy
    Tim Hardy July 23rd, 2008

    After looking into this further. It seems like the behavior of all files being managed is expected, and due to the runAllManagedModulesForAllRequests="true" setting in web.config. While the UrlRoutingModule might do nothing once it figures out the request is a static file, it's still problematic to have all static files be managed. Here's a specific troublesome example: Forms auth with a redirect to a login page - all static files requested by said login page will be redirected as well. That's right, the css file and images used by the login page will themselves be redirected to the login page, making for a very crappy looking login page. How can we work around this? The only solution I've found is to make certain that your static content is in a folder/app that is not managed by .NET. That means all static files go in a separate website, or by creating an app within your web app that uses a different AppPool. Is there a better solution for this? It doesn't seem like it would be too hard to never send static files through the .NET runtime to begin with. Perhaps a little more granularity than runAllManagedModulesForAllRequests="true".

  16. Avatar for haacked
    haacked July 23rd, 2008

    @Tim I'll dig into this some more.



    As you pointed out, having a separate web app or site for static images would work. In fact, this is how many of the large high performance sites do it. Flickr, for example, hosts the actual images on something like farm4.static.flickr.com.

    At the very least, put your static content in the "content" folder and make sure you don't authenticate requests for that folder. I think our default configuration does that. If not, we'll make sure it does.


    Another approach for best performance is to use a file extension for your MVC URLs and set runAllManagedModulesForAllRequests to false. You'll have to map your extension (perhaps ".mvc").

  17. Avatar for Tim Hardy
    Tim Hardy July 23rd, 2008

    Thanks for the response. I think the reason why few people have posted problems with this is because they probably have used the "out of the box" MVC app. We're having these problems because we're trying to integrate some new MVC pages into an existing webforms app. Turning off auth for the content folder is a brilliant idea :) Don't know why I didn't think of that earlier. I think I was assuming having all files go through the runtime was the root problem for so long I forgot to shift my thinking.

  18. Avatar for James Dunne
    James Dunne September 3rd, 2008

    This is especially annoying when you have to conceive of an IgnoreRoute line for every possible URL that is NOT an MVC route when using virtual path providers for example.

  19. Avatar for Mohan
    Mohan September 23rd, 2008

    I implemented URL Routing without using MVC and Dynamic Data, still certain routes interfere with the /WebResource.axd and /ScriptResource.axd handlers. Causig failue of Ajax framework. Please provide me the suggestions.

  20. Avatar for Mohan
    Mohan September 25th, 2008

    Mistake from my side, forgot to put IgnoreRoute on top before adding routes.

  21. Avatar for pablo
    pablo June 10th, 2010

    I've tried to download the sample code but it seems that the download link is broken. Do you mind fixing it please?

  22. Avatar for pan
    pan August 17th, 2010

    hello

    what about this message
    The controller for path '/Services/Category.asmx/SubcategoryList' was not found or does not implement IController.
    Can you help me please ...?

  23. Avatar for Afeef
    Afeef May 8th, 2011

    how to do this in asp.net 3.5 SP1?

  24. Avatar for Plasico D.
    Plasico D. July 2nd, 2011

    @Mohan, I've made the same mistake the first time : )

  25. Avatar for abhi
    abhi September 12th, 2011

    how do we give link for a web-form(report) in a mvc2 page as link; which is located in folder called Reports in Views folder. when i try to give a link for that page in Report, I finding it hard since the request is by default going to the controller. I tried to use href and actionlink but i guess I am missing something.

  26. Avatar for rekha
    rekha September 7th, 2012

    Hi,If the given url like errors.aspx is not present in the disk then how rouer will work .... since as there is an extension of .aspx so it will come under ignore route it can't go for defaukt route so will it give an exception that page not found?

  27. Avatar for Urim
    Urim November 11th, 2012

    I used the Ignore function (.net 4 - routes.IgnoreRoute("{resource}.axd/{*pathInfo}") and ajax controls (modalpopextender, watermark, etc) still don't work ,
    please any ideas on how to fix this issue
    thanks in advence

  28. Avatar for Jatin
    Jatin December 11th, 2012

    I have implemented the URL Routing using asp.net 4.0, so its working fine, but whatever images having into that page is not displaying.
    I have written below code to ignore .jpg files,but It never work
    ---
    routes.RouteExistingFiles = false;
    routes.Add(new Route("*.jpg", new StopRoutingHandler()));
    ---
    Can anyone help me out to resolve this issue asap.

    Thanks in advance.

  29. Avatar for haacked
    haacked December 11th, 2012

    @Jatin routing doesn't work with wildcards in the way you did it. That should be something like:

    routes.IgnoreRoute("{*alljpg}", new {alljpg=@".*\.jpe?g"});

  30. Avatar for abc
    abc December 26th, 2013

    abc comment

  31. Avatar for ShieldOfSalvation
    ShieldOfSalvation May 2nd, 2017

    I'm having trouble getting the IgnoreRoutes selections I've made to work. If you have a moment and can assist me, please reply to my StackOverflow question at http://stackoverflow.com/qu.... Thanks.