【问题标题】:Prevent static file handler from intercepting filename-like URL防止静态文件处理程序拦截类似文件名的 URL
【发布时间】:2012-12-28 22:42:15
【问题描述】:

在我的网络应用程序中,我有一个如下所示的路由:

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

此路由背后的想法是更好地与 Microsoft AD FS 服务器 (2.0+) 配合使用,此时您只需指定主机名即可查找 AD FS 元数据。使用 MVC3 一切正常。但是我们最近将项目升级到了 MVC4,现在对该 URL 的调用导致 404,错误页面上提到的处理程序是StaticFile,物理路径是D:\path\to\my\project\FederationMetadata\2007-06\FederationMetadata.xml。我假设 MVC 或 ASP.NET “认为”它必须是对静态文件的请求并查找文件,但它不是文件。数据是动态生成的——这就是我将 URL 路由到控制器操作的原因。问题是即使是 Phil Haack 的 Route Debugger 也不起作用。它只是一个 404,除了 IIS 试图访问一个不存在的物理文件之外没有其他信息。

有人对此有解决方案吗?我只想将此 URL 路由到控制器操作。

PS:我不是 100% 确定原因是升级到 MVC4,这只是一个猜测,因为错误发生在升级的大约同一时间,并且路线相同在另一个仍在使用 MVC3 的项目中工作。

编辑:

我有一个自定义的ControllerFactory,它需要完整的类名(AdfsController 而不是Adfs),所以在这种情况下后缀Controller 是正确的。

【问题讨论】:

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


    【解决方案1】:

    默认情况下,IIS 将该文件作为静态文件提供,而无需进入 ASP 管道,您可以将路由更改为没有 .xml 扩展名(这不是必需的,至少您对此有特定要求)

    您可以像这样指定路线:

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

    其他解决方案是添加到您的 web.config

    <modules runAllManagedModulesForAllRequests="true">
    

    但我建议您尽可能避免这种情况,因为它的作用是阻止 IIS 提供所有静态文件

    EDIT 最后一次尝试...为该特定路径定制一个 http 处理程序会起作用。这个post 与您的问题类似,只是图像问题(查找“更好:自定义 HttpHandlers”部分)

    【讨论】:

    • 不,我无法删除 .xml 扩展名,因为 URL 是由 Microsoft AD FS 服务器定义的。 AD FS 服务器只在我的服务器上请求此 URL,我必须提供正确的数据。
    • 知道了,让我知道 runAllManagedModulesForAllRequests 选项是否有效
    • 我在system.webServer 部分的Web.config 中添加了sn-p,但它没有帮助。但无论如何都不能阻止服务器提供静态文件。
    • runAllManagedModulesForAllRequests 不会阻止 IIS 提供静态文件。它首先通过托管管道传递它们,然后如果所有路由都未能匹配请求,它可能会将它们作为静态文件提供。这可能会产生额外的开销。我根本不会激活这个选项,只会有选择地为我知道的路线启用它。
    • runAllManagedModulesforAllRequests 非常适合使用即 AD FS,因为在这种情况下,您确实希望所有请求都通过托管管道并因此获得身份验证。
    【解决方案2】:

    将以下内容添加到&lt;system.webServer&gt; 节点的&lt;handlers&gt; 部分:

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

    这指示 IIS 对指定 url 的 GET 请求应由托管管道处理,而不是视为静态文件并由 IIS 直接提供服务。

    我有一个需要完整类名的自定义 ControllerFactory (AdfsController而不是Adfs),所以后缀Controller是正确的 在这种情况下。

    请仔细检查。尝试在路由定义中使用和不使用 Controller 后缀。

    【讨论】:

    • 你救了我的命。虽然我很想看到一个解决方案而不必修改我的Web.config(我可以通过代码添加这个处理程序吗?),你的解决方案工作得很好。谢谢。
    • 不,没有办法通过代码来配置这个。您的问题的根源是 IIS 拦截并劫持了认为这是一个静态文件的请求。所以没有代码——至少你的应用程序中没有运行过的代码。通过将它放在配置文件中,您是在告诉 IIS 实际通过您的应用程序传递请求。只有这样它才会访问您的实际代码并完成路由过程。
    • 好的,谢谢。既然你这么说,其实很明显了。 404 错误消息毕竟是由 IIS 生成的,而不是由 ASP.NET 生成的。
    猜你喜欢
    • 1970-01-01
    • 2011-12-19
    • 1970-01-01
    • 1970-01-01
    • 2018-01-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-09-30
    相关资源
    最近更新 更多