ASP.NET MVC 路由:绕过路径的静态文件处理程序

Posted

技术标签:

【中文标题】ASP.NET MVC 路由:绕过路径的静态文件处理程序【英文标题】:ASP.NET MVC Route: bypass staticfile handler for path 【发布时间】:2012-06-30 17:57:05 【问题描述】:

我已经在谷歌上搜索和修补了几个小时,并没有真正取得太大进展,所以希望这里有人可以提供帮助。

我正在尝试让某个路径的所有请求都由第 3 方组件处理。

编辑我需要对所有其他路径的所有请求才能正常运行。

我正在使用带有通配符映射的路由处理程序,如下所示:

routes.Add(new Route("pathiwant/*EverythingElse", new MyRouteHandler()));

所有传统路由都正确转发到处理程序,该处理程序很好地转发到第 3 方组件。当我点击静态文件(.html、.txt 等)时,它们会被 StaticFile 处理程序而不是我的处理程序拾取,所以我试图像这样(简化)关闭 StaticFile 处理程序:

<system.webServer>
  <handlers>
    <remove name="StaticFile"/>
  </handlers>
</system.webServer>

这会关闭 StaticFile 处理程序,但 MVC 仍然不会选择路由。

我不希望依赖于创建自己的处理程序并注入 ASP 请求堆栈,因为似乎应该有一种 MVC 快乐的方式来做到这一点。

有什么想法吗?谢谢。

【问题讨论】:

【参考方案1】:

这里有几个选项。

http://www.hanselman.com/blog/BackToBasicsDynamicImageGenerationASPNETControllersRoutingIHttpHandlersAndRunAllManagedModulesForAllRequests.aspx

如果您真的希望所有请求都通过 asp.net 管道运行,那么您需要。

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

更新

另一种选择,特别是如果您需要绕过静态处理程序被限制在您的网站的一个子集,是使用以下

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

考虑到在 mvc 站点上,大多数静态文件是从几个众所周知的目录中处理的,这是一个更好的选择。

【讨论】:

谢谢。这绝对是我尝试过的,但我确实希望所有其他路径都能正常处理。真的开始似乎没有 MVC 方法可以做到这一点,我应该分解并在 MVC 之前添加处理程序。 不确定你想要和不想处理的具体细节,但是是的,为了在 mvc 中处理事情,asp.net 管道需要接收所有适当的请求。 重要提示:&lt;system.webServer&gt; 仅适用于运行集成模式管道的应用程序池。这不适用于在经典模式下运行的应用程序池。 请注意:不建议使用 runAllManagedModulesForAllRequests="true" - 有关详细信息,请参阅 Hanselman 文章。这可能会对性能产生负面影响。 不仅仅是性能。由于模块针对所有请求运行,因此通过管道推送 PDF 和 XML 以及其他文件的 URL 可以产生有趣的结果。警告购买者。【参考方案2】:

对此的最佳解决方案可能是使用 URL Rewriter 将来自原始 URL 的请求代理到 MVC 友好的替代方案。

例如,假设您需要能够自动加载从数据库提供的内容中的相对 URL。

RewriteRule ^/load/(\d+)/rel(\?.*)? -   [L]
RewriteRule ^/load/(\d+)/(.*)$  /load/$1/rel?path=$2    [P,QSA,L,NC]

这些规则将允许您设置两条 MVC 路由:

routes.MapRoute(
    "Load Item",
    "load/itemId",
    new  controller = "Load", action = "Index" 
    );

routes.MapRoute(
    "Load Relative Item",
    "load/itemId/rel",   //?path=
    new  controller = "Load", action = "Relative" 
    );

然后你的操作方法很简单:

 public ActionResult Index(int itemId)  ... 

 public FileStreamResult Relative(int itemId, string path)  ... 

第一个重写规则是为了防止包含 /rel 的路径被重写;它们已经处于最终形式。第二个重写规则代理(而不是重定向)请求。

例如

/load/1234/file.xml

变成

/load/1234/rel?path=file.xml

代理请求而不是执行客户端重定向可以使嵌套的相对路径也能正常工作(并隐藏最终用户的秘密。)

【讨论】:

以上是关于ASP.NET MVC 路由:绕过路径的静态文件处理程序的主要内容,如果未能解决你的问题,请参考以下文章

找不到静态图像的控制器路径? asp.net mvc 路由问题?

使用 ASP.NET 路由来提供静态文件

如何在 ASP.NET MVC 的 ~/Views 文件夹下请求静态 .html 文件?

ASP.NET MVC学习之路由篇

Asp.Net MVC 无法获取 .html 文件或 .xml 文件 404 错误?

Web API系列教程2.1 — ASP.NET Web API中的路由机制