问题 防止静态文件处理程序拦截类似文件名的URL


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

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也行不通。除了IIS试图访问不存在的物理文件之外,它只是404而没有进一步的信息。

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

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

编辑:


11927
2018-01-14 21:56


起源



答案:


将以下内容添加到 <handlers> 部分 <system.webServer> 节点:

<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 路径定义中的后缀。


14
2018-01-14 22:25



你救了我的命。虽然我很乐意看到一个解决方案,而不必修改我的 Web.config (我可以通过代码添加此处理程序吗?),您的解决方案完美无缺。谢谢。 - fero
不,没有办法通过代码配置它。问题的根源在于,IIS拦截并劫持了认为这是静态文件的请求。所以没有 码  - 至少在您的应用程序中没有运行的代码。通过将其放在配置文件中,您告诉IIS实际通过您的应用程序传递请求。只有这样,它才会触及您的实际代码并完成路由过程。 - Darin Dimitrov
好,谢谢。现在你说了,实际上很明显。毕竟,IIS生成404错误消息,而不是由ASP.NET生成。 - fero


答案:


将以下内容添加到 <handlers> 部分 <system.webServer> 节点:

<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 路径定义中的后缀。


14
2018-01-14 22:25



你救了我的命。虽然我很乐意看到一个解决方案,而不必修改我的 Web.config (我可以通过代码添加此处理程序吗?),您的解决方案完美无缺。谢谢。 - fero
不,没有办法通过代码配置它。问题的根源在于,IIS拦截并劫持了认为这是静态文件的请求。所以没有 码  - 至少在您的应用程序中没有运行的代码。通过将其放在配置文件中,您告诉IIS实际通过您的应用程序传递请求。只有这样,它才会触及您的实际代码并完成路由过程。 - Darin Dimitrov
好,谢谢。现在你说了,实际上很明显。毕竟,IIS生成404错误消息,而不是由ASP.NET生成。 - fero


默认情况下,IIS将该文件作为静态服务而不进入ASP管道,您是否可以将路由更改为不具有.xml扩展名(至少您没有必要具有该特定要求)

您可以指定这样的路线:

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

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

<modules runAllManagedModulesForAllRequests="true">

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

编辑 最后一次尝试...该特定路径的自定义http处理程序将起作用。这个 岗位 类似于你的问题只有图像(寻找“更好:自定义HttpHandlers”部分)


1
2018-01-14 22:05



不,我无法删除 .xml 扩展名,因为URL是由Microsoft AD FS服务器定义的。 AD FS服务器只在我的服务器上请求此URL,我必须提供正确的数据。 - fero
得到它,让我知道runAllManagedModulesForAllRequests选项是否有效 - jorgehmv
我把片段添加到了我的脑袋里 Web.config 在里面 system.webServer 部分,但它没有帮助。但无论如何,停止服务器提供静态文件都不是一种选择。 - fero
runAllManagedModulesForAllRequests 不会阻止IIS提供静态文件。它首先将它们传递给托管管道,然后如果所有路由都无法匹配请求,它可以将它们作为静态文件提供。这可能会产生额外的开销。我根本不会激活此选项,只能为我知道的路由选择性地启用它。 - Darin Dimitrov
runAllManagedModulesforAllRequests在使用AD FS时非常出色,因为在这种情况下,您希望所有请求都通过托管管道,从而获得身份验证。 - Koen Zomers