2009-07-19 82 views
61

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中静态文件的路由?

回答

37

在仔细研究了这个问题几个小时之后,我发现只需添加忽略规则就可以获得静态文件。

在的RegisterRoutes(RouteCollection路线),添加以下忽略的规则:

routes.IgnoreRoute("{file}.js"); 
routes.IgnoreRoute("{file}.html"); 
48

为什么不使用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> 
+0

我宁愿这种做法,也是如此。将它移出到管道,并让IIS工作进程处理重定向比通过运行时实际处理路径的循环更有效,我假设。即使服务器上的流失量大致相同,我也会选择不使用路由的路由(双关语),并将重定向保留在应用程序之外。 – 2009-07-26 19:00:22

+0

从我的问题的最初版本中不清楚的是,重写的URL是即时计算的(我不担心这里的性能)。我已经更新了这个问题来澄清这一点。无论如何,谢谢你的回复。 – 2009-07-26 20:52:47

+0

(删除我以前的评论,并重新添加一个非缩短的网址)。除了性能问题之外,为什么要在应用程序中处理这个URL,在外部处理时会更好?我想你可以创建一个处理这个的控制器动作,但这里有一些你可以看看的东西: - http://geekswithblogs.net/sankarsan/archive/2009/01/18/developing-custom-routehandler.aspx – 2011-07-20 11:52:36

5

我想出了一个替代使用内部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中删除。