13

In my web application I have a route which looks like this:

routeCollection.MapRoute(
    "AdfsMetadata",                                                // name
    "FederationMetadata/2007-06/FederationMetadata.xml",           // url
    new { controller = "AdfsController", action = "MetaData" });   // defaults

The idea behind this route was to work better with Microsoft AD FS server (2.0+) which looks for AD FS metadata at this point when you just specify a host name. With MVC3 all worked fine. But we upgraded the project to MVC4 recently and now the call for this URL results in a 404, the handler mentioned on the error page is StaticFile and the physical path is D:\path\to\my\project\FederationMetadata\2007-06\FederationMetadata.xml. I assume that MVC or ASP.NET "thinks" it must be a request for a static file and looks for the file, but it isn't a file. The data is generated dynamically - that's why I routed the URL to a controller action. The problem is that even the Route Debugger by Phil Haack doesn't work. It's just a 404 with no further information besides that IIS tried to access a physical file which isn't there.

Does anyone have a solution for this? I just want this URL to be routed to a controller action.

P.S.: I'm not 100% sure that the cause was the upgrade to MVC4, it was just a guess because the error occurred at about the same time as the upgrade, and the same route works in another project which is still using MVC3.

Edit:

I have a custom ControllerFactory which needs the full class name (AdfsController instead of Adfs), so the suffix Controller is correct in this case.

fero
  • 6,050
  • 1
  • 33
  • 56

2 Answers2

17

Add the following to the <handlers> section of the <system.webServer> node:

<add 
    name="AdfsMetadata" 
    path="/FederationMetadata/2007-06/FederationMetadata.xml" 
    verb="GET" 
    type="System.Web.Handlers.TransferRequestHandler" 
    preCondition="integratedMode,runtimeVersionv4.0" />

This instructs IIS that GET requests to the specified url should be handled by the managed pipeline and not considered as static files and served by IIS directly.

I have a custom ControllerFactory which needs the full class name (AdfsController instead of Adfs), so the suffix Controller is correct in this case.

Double check this please. Try with and without the Controller suffix in the route definition.

Darin Dimitrov
  • 1,023,142
  • 271
  • 3,287
  • 2,928
  • You saved my life. Although I would love to see a solution without having to modify my `Web.config` (can I add this handler by code?), your solution works perfectly. Thank you. – fero Jan 14 '13 at 22:40
  • 1
    No, there is no way to configure this by code. The very root of your problem was that IIS intercepts and hijacks the request thinking that this is a static file. So there's no *code* - at least no code in your application that is ever run. By putting this in the config file you are telling IIS to actually pass the request through your application. It's only then that it will hit your actual code and go through the routing process. – Darin Dimitrov Jan 14 '13 at 22:55
  • OK, thanks. Now that you say it, it's actually pretty obvious. The 404 error message is generated by IIS after all, and not by ASP.NET. – fero Jan 15 '13 at 07:39
2

IIS by default is serving that file as static withouth going into ASP pipeline, can you change the route to not have a .xml extension (which is not necessary at least you have a specific requirement about that)

You can specifiy the route like this:

routeCollection.MapRoute(
"AdfsMetadata",                                                // name
"FederationMetadata/2007-06/FederationMetadata",               // url
new { controller = "AdfsController", action = "MetaData" });   // defaults

Other solution would be to add to your web.config

<modules runAllManagedModulesForAllRequests="true">

but I recommend you to avoid this as possible since what it does is to stop IIS from serving all static files

EDIT Last try... a custom http handler for that specific path would work. This post is similar to your problem only that with images (look for "Better: Custom HttpHandlers" section)

jorgehmv
  • 3,633
  • 3
  • 25
  • 39
  • No, I can't remove the `.xml` extension because the URL is defined by Microsoft AD FS server. The AD FS server just requests this URL on my server and I have to serve the correct data. – fero Jan 14 '13 at 22:08
  • 2
    got it, let me know if runAllManagedModulesForAllRequests option worked – jorgehmv Jan 14 '13 at 22:09
  • I added the snippet to my `Web.config` in the `system.webServer` section, but it didn't help. But stopping the server from serving static files isn't an option anyway. – fero Jan 14 '13 at 22:13
  • 1
    `runAllManagedModulesForAllRequests` doesn't prevent IIS from serving static files. It first passes them through the managed pipeline and then it might serve them as static files if all the routes have failed to match the request. This could have an additional overhead. I wouldn't activate this option at all and only selectively enable it for routes that I know. – Darin Dimitrov Jan 14 '13 at 22:30
  • The runAllManagedModulesforAllRequests is brilliant for when using i.e. AD FS since in that case you DO want all requests to go through the managed pipeline and thus get authenticated. – Koen Zomers Nov 21 '14 at 08:16