【问题标题】:Serving static files and falling back to MVC routing提供静态文件并回退到 MVC 路由
【发布时间】:2014-01-24 13:14:12
【问题描述】:

我有一个在 IIS 8.5 下运行的 ASP.NET MVC 4 应用程序。我之前在 MVC 中对这些场景的理解/经验是,如果存在静态文件,则会对其进行服务。如果它存在,路径将通过MVC路由发送。这是期望的行为,但似乎没有发生。

默认情况下,如果我在 /blah.htmlno 对应的静态文件创建一个包罗万象的路由,IIS 会提供 404(由 StaticFile 处理程序提供)。 MVC 路由永远不会被命中。如果文件存在,则提供。

所以,我做了一些谷歌搜索并与同事聊天,并想出了这里发布的答案:

https://*.com/a/14327897/1043198

进入处理程序:

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

太棒了!该请求现在到达 MVC 应用程序,并且我的动态内容按预期提供。除了现在,当我放置一个物理文件时,我再次收到错误。带有以下信息(仅此而已)的无意义的 500 错误:

模块: ManagedPipelineHandler

通知: ExecuteRequestHandler

处理程序: ApiURIs-ISAPI-Integrated-4.0

错误代码: 0x800703e9

发生了什么事?为什么当静态文件不存在时 IIS 不回退到我的 MVC 应用程序,当我修复它时,为什么会发生相反的情况并且不再正确提供静态文件?我很确定这在过去一直是默认行为。

应用程序池以集成模式运行,CLR v4.0。

【问题讨论】:

    标签: asp.net-mvc-4 iis-8


    【解决方案1】:

    在找到建议启用runAllManagedModulesForAllRequests 的各种答案和博客文章后,这似乎不是正确的方法——虽然它有效。

    RAMMFAR 完全按照它在 tin 上说的做,并通过所有托管模块运行所有请求(包括那些对“非托管”静态资源的请求),这会产生性能开销,并且还可能导致异常的副作用,具体取决于启用的模块和请求通过它们运行。

    原来解决这个问题所需的唯一模块是UrlRoutingModule,当去除前置条件时,会导致所有静态资源通过MVC路由运行(当不存在静态文件时):

    <remove name="UrlRoutingModule" />
    <add name="UrlRoutingModule-4.0" type="System.Web.Routing.UrlRoutingModule"   
        preCondition="" />
    

    【讨论】:

    • @JotaBe 我会的,两天后。
    • 这修复了它,但它不是正确的答案。因为使用 satic 路径告诉 IIS 将路径视为路由,忽略任何 mime 类型。这个答案告诉 ISS 将所有内容传递给应用程序,无论 mime 类型如何,如果失败则回退到 IIS。如果分配对静态文件的非托管调用,这可能会降低性能。
    • @ppumkin 你是对的 - 一直想更新这个答案。
    • 是的,那太好了......但我发现这是因为愚蠢的 500 错误。在本地它工作正常,但在实时服务器上它只显示 IIS 500,而不是应用程序 500。它不会被记录或显示任何错误原因。所以我可能不得不使用 RAMMFAR ......或者如果你知道为什么?我会尝试 UrlRouting 一个:)
    • 投反对票,因为 cmets 不清楚这是否是一个好的答案。