使用ASP.NET路由来提供静态文件
ASP.Net路由(而不是MVC)可用于提供静态文件吗?使用ASP.NET路由来提供静态文件
说我想航线
http://domain.tld/static/picture.jpg
到
http://domain.tld/a/b/c/picture.jpg
,我要动态地做它在这个意义上,重写URL计算的飞行。我无法一劳永逸地设置一条静态路由。
反正,我可以创造这样的路线:
routes.Add(
"StaticRoute", new Route("static/{file}", new FileRouteHandler())
);
在FileRouteHandler.ProcessRequest
方法我可以重写从/static/picture.jpg
到/a/b/c/picture.jpg
的路径。然后我想为静态文件创建一个处理程序。 ASP.NET为此使用StaticFileHandler
。不幸的是,这门课是内部的。我试图创建使用反射处理程序,它实际上工作:
Assembly assembly = Assembly.GetAssembly(typeof(IHttpHandler));
Type staticFileHandlerType = assembly.GetType("System.Web.StaticFileHandler");
ConstructorInfo constructorInfo = staticFileHandlerType.GetConstructor(BindingFlags.NonPublic | BindingFlags.Instance, null, Type.EmptyTypes, null);
return (IHttpHandler) constructorInfo.Invoke(null);
但使用内部类型似乎不是正确的解决方案。另一个选择是实现我自己的StaticFileHandler
,但是正确执行(支持范围和etags之类的HTTP内容)并不重要。
我应该如何处理ASP.NET中静态文件的路由?
在仔细研究了这个问题几个小时之后,我发现只需添加忽略规则就可以获得静态文件。
在的RegisterRoutes(RouteCollection路线),添加以下忽略的规则:
routes.IgnoreRoute("{file}.js");
routes.IgnoreRoute("{file}.html");
为什么不使用IIS来做到这一点?您可以创建重定向规则,将请求从第一条路径指向第二条路径,然后再将请求发送到您的应用程序。因此,这将是一个更快速的重定向请求的方法。
假设你有IIS7 +,你这样做......
<rule name="Redirect Static Images" stopProcessing="true">
<match url="^static/?(.*)$" />
<action type="Redirect" url="https://stackoverflow.com/a/b/c/{R:1}" redirectType="Permanent" />
</rule>
或者,如果你不需要重定向,如@ ni5ni6建议:
<rule name="Rewrite Static Images" stopProcessing="true">
<match url="^static/?(.*)$" />
<action type="Rewrite" url="https://stackoverflow.com/a/b/c/{R:1}" />
</rule>
编辑2015-06-17 for @RyanDawkins:
如果您想知道重写规则在哪里出现,这里是它在web.config
文件中的位置的地图。
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<system.webServer>
<rewrite>
<rules>
<!-- rules go below -->
<rule name="Redirect Static Images" stopProcessing="true">
<match url="^static/?(.*)$" />
<action type="Redirect" url="https://stackoverflow.com/a/b/c/{R:1}" redirectType="Permanent" />
</rule>
</rules>
</rewrite>
</system.webServer>
</configuration>
我想出了一个替代使用内部StaticFileHandler
。在IRouteHandler
我打电话HttpServerUtility.Transfer
:
public class FileRouteHandler : IRouteHandler {
public IHttpHandler GetHttpHandler(RequestContext requestContext) {
String fileName = (String) requestContext.RouteData.Values["file"];
// Contrived example of mapping.
String routedPath = String.Format("https://stackoverflow.com/a/b/c/{0}", fileName);
HttpContext.Current.Server.Transfer(routedPath);
return null; // Never reached.
}
}
这是一个黑客。 IRouteHandler
应该返回IHttpHandler
而不是中止并传输当前请求。但是,它确实实现了我想要的。
使用内部StaticFileHandler
也有点破解,因为我需要反思才能访问它,但至少有一些documentation on StaticFileHandler
on MSDN使它成为一个稍微更“官方”的类。不幸的是,我不认为有可能在部分信任环境中反思内部类。
我会坚持使用StaticFileHandler
,因为我不认为它会在可预见的将来从ASP.NET中删除。
我宁愿这种做法,也是如此。将它移出到管道,并让IIS工作进程处理重定向比通过运行时实际处理路径的循环更有效,我假设。即使服务器上的流失量大致相同,我也会选择不使用路由的路由(双关语),并将重定向保留在应用程序之外。 – 2009-07-26 19:00:22
从我的问题的最初版本中不清楚的是,重写的URL是即时计算的(我不担心这里的性能)。我已经更新了这个问题来澄清这一点。无论如何,谢谢你的回复。 – 2009-07-26 20:52:47
(删除我以前的评论,并重新添加一个非缩短的网址)。除了性能问题之外,为什么要在应用程序中处理这个URL,在外部处理时会更好?我想你可以创建一个处理这个的控制器动作,但这里有一些你可以看看的东西: - http://geekswithblogs.net/sankarsan/archive/2009/01/18/developing-custom-routehandler.aspx – 2011-07-20 11:52:36