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

ASP.Net路由(而不是MVC)可以用来提供静态文件吗?

说我想要路线

http://domain.tld/static/picture.jpg 

 http://domain.tld/a/b/c/picture.jpg 

而且我想dynamic地执行,因为重写的URL是即时计算的。 我无法一劳永逸地设置一条静态路由。

无论如何,我可以创build一个这样的路线:

 routes.Add( "StaticRoute", new Route("static/{file}", new FileRouteHandler()) ); 

FileRouteHandler.ProcessRequest方法中,我可以重写从/static/picture.jpg/a/b/c/picture.jpg的path。 然后我想为静态文件创build一个处理程序。 ASP.NET为此使用StaticFileHandler 。 不幸的是,这个class是内部的。 我试图创build使用reflection处理程序,它实际上工作:

 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); 

但是使用内部types似乎不是合适的解决scheme。 另一个select是实现我自己的StaticFileHandler ,但是正确地执行(支持范围和etags之类的HTTP内容)并不重要。

我应该如何处理ASP.NET中的静态文件的路由?

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

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

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

为什么不使用IIS来做到这一点? 您可以创buildredirect规则,以便在请求甚至到达您的应用程序之前将来自第一条path的请求指向第二条path。 因此,这将是一个更快的redirect请求的方法。

假设你有IIS7 +,你可以做类似…

 <rule name="Redirect Static Images" stopProcessing="true"> <match url="^static/?(.*)$" /> <action type="Redirect" url="/a/b/c/{R:1}" redirectType="Permanent" /> </rule> 

或者 ,如果你不需要redirect,就像@ ni5ni6build议的那样:

 <rule name="Rewrite Static Images" stopProcessing="true"> <match url="^static/?(.*)$" /> <action type="Rewrite" url="/a/b/c/{R:1}" /> </rule> 

@RyanDawkins编辑2015-06-17

如果您想知道重写规则的位置,请在web.config文件中find它的位置。

 <?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="/a/b/c/{R:1}" redirectType="Permanent" /> </rule> </rules> </rewrite> </system.webServer> </configuration> 

我有类似的问题。 我结束了使用HttpContext.RewritePath :

 public class MyApplication : HttpApplication { private readonly Regex r = new Regex("^/static/(.*)$", RegexOptions.IgnoreCase); public override void Init() { BeginRequest += OnBeginRequest; } protected void OnBeginRequest(object sender, EventArgs e) { var match = r.Match(Request.Url.AbsolutePath); if (match.Success) { var fileName = match.Groups[1].Value; Context.RewritePath(string.Format("/a/b/c/{0}", fileName)); } } } 

我想出了一个使用内部StaticFileHandler的替代scheme。 在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("/a/b/c/{0}", fileName); HttpContext.Current.Server.Transfer(routedPath); return null; // Never reached. } } 

这是一个黑客。 IRouteHandler应该返回一个IHttpHandler而不是中止并传输当前的请求。 但是,它确实实现了我想要的。

使用内部的StaticFileHandler也是一个黑客,因为我需要reflection来访问它,但是至less在MSDN上有一些关于StaticFileHandler文档,使它成为一个稍微更“官方”的类。 不幸的是,我不认为有可能在部分信任环境中反思内部类。

我将坚持使用StaticFileHandler因为我不认为它会在可预见的将来从ASP.NET中删除。

你需要添加TransferRequestHandler来处理你的静态文件。请看下面的回答https://stackoverflow.com/a/21724783/22858