37

I'm trying to get the following (and similar) urls to work in my ASP.net MVC4/WebApi project:

http://127.0.0.1:81/api/nav/SpotiFire/SpotiFire.dll

The route responsible for this url looks like this:

        config.Routes.MapHttpRoute(
            name: "Nav",
            routeTemplate: "api/nav/{project}/{assembly}/{namespace}/{type}/{member}",
            defaults: new { controller = "Nav", assembly = RouteParameter.Optional, @namespace = RouteParameter.Optional, type = RouteParameter.Optional, member = RouteParameter.Optional }
        );

It works just fine if I remove the . in the file-name, or if I add a slash behind the URL, but that also means I can't use the Url.Route-methods etc. The error I get is a generic 404-error (image below).

enter image description here

I've tried adding <httpRuntime targetFramework="4.5" relaxedUrlToFileSystemMapping="true" /> to my web.config, and I've also tried adding

<compilation debug="true" targetFramework="4.5">
  <buildProviders>
    <remove extension=".dll"/>
    <remove extension=".exe"/>
  </buildProviders>
</compilation>

And none of it seems to work. So my question is basically, how can I get this URL to work, and map correctly?

Alxandr
  • 12,345
  • 10
  • 59
  • 95
  • Only the last portion of a route can be optional. In the example you have shown you have made all the route parameters except project optional which obviously is not possible. Also in the url you have shown you are missing `namespace` and `type` portions of the url. Only the `member` portion can be optional because it is defined at the end of the route. – Darin Dimitrov Feb 02 '13 at 17:46
  • This is not true, and it's proven to work without problems. You can have as many parts optional as you want to. For instance, even before the change I just made in my answer, the url `/api/nav/SpotiFire` worked as a charm. – Alxandr Feb 02 '13 at 17:48
  • This also works for ASP.NET Web API 2. – SoItBegins Dec 22 '22 at 19:46

3 Answers3

52

You could add the following handler to the <handlers> section of your <system.webServer>:

<add 
    name="ManagedDllExtension" 
    path="api/nav/*/*.dll" 
    verb="GET" 
    type="System.Web.Handlers.TransferRequestHandler" 
    preCondition="integratedMode,runtimeVersionv4.0" 
/>

This will make all requests containing .dll be served through the managed pipeline. Also notice how I have limited them only to the GET verb to limit the performance impact.

Darin Dimitrov
  • 1,023,142
  • 271
  • 3,287
  • 2,928
  • Brilliant, thought shouldn't this `` cover that already? I'm not sure what's covered by "*.". – Alxandr Feb 02 '13 at 18:00
  • 2
    No, it's not covering it. You need to specify the extension. If there's an extension in the url, IIS will take over thinking that it is a static file. – Darin Dimitrov Feb 02 '13 at 18:00
  • 1
    This is such a fantastic answer. – bonh Jun 01 '15 at 14:44
  • @DarinDimitrov, what if we use this: `path="*.*"`? It works, for any kind of file, but I'm wondering if it can create side problems. Kind regards. – bluish Nov 06 '19 at 09:28
13

Found it. What's needed is this (and maybe some of the things I've added above in the original post):

<system.webServer>
  <modules runAllManagedModulesForAllRequests="true" />
</system.webServer>
Alxandr
  • 12,345
  • 10
  • 59
  • 95
  • 3
    I wouldn't recommend you adding this because it will have a bad side effect => all requests will now go through the managed pipeline which will have a negative impact on the performance of your application. – Darin Dimitrov Feb 02 '13 at 17:48
  • True, I might find a better solution in time, however, already more than 90% of requests are managed requests, so I don't think the performance-hit will be too big at all... The only thing that isn't loaded through the managed pipeline are images, and I have about 2 of them on my entire page... – Alxandr Feb 02 '13 at 17:50
  • 2
    Checkout my answer for the correct way to make this without activating the `runAllManagedModulesForAllRequests="true"`. – Darin Dimitrov Feb 02 '13 at 17:53
5

My trade off was to append /end to the end of route. .'s are ignored before the last /.

The equivalent URL would be http://127.0.0.1:81/api/nav/SpotiFire/SpotiFire.dll/end.

The benefit being that you don't get a performance hit on your assets.

kim3er
  • 6,306
  • 4
  • 41
  • 69