ASP.net MVC4 WebApi带有文件名的路由

37

我正试图让以下(和类似的)网址在我的ASP.net MVC4/WebApi项目中起作用:

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

负责此URL的路由如下:

        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 }
        );

如果我删除文件名中的“.”或在URL后面添加斜杠,它就能正常工作,但这也意味着我不能使用 Url.Route 等方法。 我得到的错误是通用的404错误(如下图所示)。

enter image description here

我尝试过将<httpRuntime targetFramework =“4.5” relaxedUrlToFileSystemMapping =“true” />添加到我的web.config中,也尝试过添加

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

但似乎所有的方法都不起作用。因此,我的问题基本上是,如何使这个URL正常工作并正确映射?


只有路由的最后一部分可以是可选的。在你展示的例子中,除了项目参数之外,你已经使所有的路由参数都变成可选的,这显然是不可能的。此外,在你展示的URL中,你缺少了URL的namespacetype部分。只有member部分可以是可选的,因为它被定义在路由的末尾。 - Darin Dimitrov
这是不正确的说法,而且已经证明可以无问题地运行。您可以将许多部分设置为可选项。例如,在我刚刚回答中所做的更改之前,url“/api/nav/SpotiFire”就像魅力一样工作。 - Alxandr
这也适用于 ASP.NET Web API 2。 - SoItBegins
3个回答

52
你可以将以下处理程序添加到你的 <system.webServer><handlers> 部分:
<add 
    name="ManagedDllExtension" 
    path="api/nav/*/*.dll" 
    verb="GET" 
    type="System.Web.Handlers.TransferRequestHandler" 
    preCondition="integratedMode,runtimeVersionv4.0" 
/>

这将使所有包含.dll的请求通过托管管道进行服务。还请注意,我仅将它们限制为GET动词,以限制性能影响。


太棒了,但是这个<add name="ExtensionlessUrlHandler-Integrated-4.0" path="*." verb="GET,HEAD,POST,DEBUG,PUT,DELETE,PATCH,OPTIONS" type="System.Web.Handlers.TransferRequestHandler" preCondition="integratedMode,runtimeVersionv4.0" />不应该已经覆盖了吗?我不确定“*.”覆盖了什么。 - Alxandr
2
不,它并没有涵盖它。您需要指定扩展名。如果url中有扩展名,IIS将接管认为它是静态文件。 - Darin Dimitrov
1
这是一个非常棒的答案。 - bonh
@DarinDimitrov,如果我们使用 path="*.*" 怎么样?它可以处理任何类型的文件,但是我想知道是否会引发其他问题。谢谢! - bluish

13

找到了。需要的是这个(也许还有我在原始帖子中添加的一些内容):

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

3
我不建议你添加这个,因为会产生负面影响,即所有请求现在都会经过托管管道,这会对应用程序性能产生负面影响。 - Darin Dimitrov
是的,也许我会在未来找到更好的解决方案,但已经有超过90%的请求是托管请求,所以我不认为性能影响会太大...唯一没有通过托管管道加载的是图像,而且我整个页面只有大约2个图像... - Alxandr
2
请查看我的答案,正确的方法可以在不启用runAllManagedModulesForAllRequests="true"的情况下完成。 - Darin Dimitrov

5
我的权衡是在路由的末尾添加/end。最后一个/之前的.会被忽略。
相应的URL将是http://127.0.0.1:81/api/nav/SpotiFire/SpotiFire.dll/end
好处是您不会因为资产而受到性能影响。

这对我很有效,也是最简单的解决方案,尽管我只是在末尾添加了一个“/”。 - Jason Jong

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接