20

I've been googling and tinkering for a couple hours and haven't really made much progress, so hopefully someone here can help.

I'm trying to get all requests to a certain path to be handled by a 3rd party component.

EDIT And I need all requests to all other paths to behave normally.

I'm using a route handler with a wildcard mapping like this:

routes.Add(new Route("pathiwant/{*EverythingElse}", new MyRouteHandler()));

All traditional routes forward correctly to the handler, which forwards nicely to the 3rd party component. When I hit static files (.html, .txt, etc.), they get picked up by the StaticFile handler instead of my handler, so I'm attempting to turn off the StaticFile handler like so (simplified):

<system.webServer>
  <handlers>
    <remove name="StaticFile"/>
  </handlers>
</system.webServer>

This turns off the StaticFile handler, but MVC still doesn't pick up the route.

I'd prefer not to fall back on creating my own handler and injecting into the ASP request stack since it seems like there should be an MVC-happy way to do this.

Any thoughts? And thanks.

jmoss
  • 203
  • 1
  • 2
  • 5

2 Answers2

17

There are a couple options here.

http://www.hanselman.com/blog/BackToBasicsDynamicImageGenerationASPNETControllersRoutingIHttpHandlersAndRunAllManagedModulesForAllRequests.aspx

If you really want all requests running through the asp.net pipe then you need.

<system.webServer>
  <modules runAllManagedModulesForAllRequests="true" />
</system.webServer>

Update

Another option, especially if your need to bypass the static handler is constrained to a subset of your site, is to use the following

  <add name="ApiURIs-ISAPI-Integrated-4.0"
     path="/subdirectory/*"
     verb="GET,HEAD,POST,DEBUG,PUT,DELETE,PATCH,OPTIONS"
     type="System.Web.Handlers.TransferRequestHandler"
     preCondition="integratedMode,runtimeVersionv4.0" />

Considering how on mvc sites, most static files are handled from a couple well known directories, this is a better option.

Kenneth Ito
  • 5,201
  • 2
  • 25
  • 44
  • Thanks. It's definitely something I tried, but I do want all other paths to be handled normally. It's really beginning to seem like there isn't an MVC way to do this, and I should just break down and add the handler before MVC. – jmoss Jun 29 '12 at 16:09
  • Not sure about the specifics of exactly what you want and don't want to handle, but yes, in order to handle things in mvc the asp.net pipe needs to receive all the appropriate requests. – Kenneth Ito Jun 29 '12 at 22:55
  • 1
    IMPORTANT NOTE: `` only applies for application pools running an Integrated Mode Pipeline. This won't work for app pools running under Classic mode. – BenSwayne Aug 09 '12 at 02:47
  • 4
    Please note: it is NOT RECOMMENDED to use runAllManagedModulesForAllRequests="true" - see the Hanselman article for details. This can have a negative performance impact. – Quango Jan 07 '13 at 09:24
  • 3
    Not just performance. As the modules are ran for ALL requests, pushing URLs for PDF and XML and other files through the pipeline can yield interesting results. Caveat emptor. – Cornelius Feb 25 '13 at 13:38
3

The best solution for this is probably to use a URL Rewriter to proxy the requests from the original URL to an MVC friendly alternative.

For example, say you need to be able to automatically load relative URLs in content served from a database.

RewriteRule ^/load/(\d+)/rel(\?.*)? -   [L]
RewriteRule ^/load/(\d+)/(.*)$  /load/$1/rel?path=$2    [P,QSA,L,NC]

Those rules will let you set up two MVC routes:

routes.MapRoute(
    "Load Item",
    "load/{itemId}",
    new { controller = "Load", action = "Index" }
    );

routes.MapRoute(
    "Load Relative Item",
    "load/{itemId}/rel",   //?path=
    new { controller = "Load", action = "Relative" }
    );

And then your action methods are straightforward:

 public ActionResult Index(int itemId) { ... }

 public FileStreamResult Relative(int itemId, string path) { ... }

The first rewrite rule is there to prevent paths containing /rel from being rewritten; they're already in their final form. The second rewrite rule proxies (instead of redirecting) the request.

e.g.

/load/1234/file.xml

becomes

/load/1234/rel?path=file.xml

Proxying the request instead of doing a client redirect enables nested relative paths to work as well (and hides the secret sauce from the end user.)

hemp
  • 5,602
  • 29
  • 43