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

Mar*_*age 71 asp.net url-routing

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

说我想路线

http://domain.tld/static/picture.jpg
Run Code Online (Sandbox Code Playgroud)

http://domain.tld/a/b/c/picture.jpg
Run Code Online (Sandbox Code Playgroud)

我想动态地做这件事,因为重写的URL是动态计算的.我无法一劳永逸地建立静态路线.

无论如何,我可以创建这样的路线:

routes.Add(
  "StaticRoute", new Route("static/{file}", new FileRouteHandler())
);
Run Code Online (Sandbox Code Playgroud)

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);
Run Code Online (Sandbox Code Playgroud)

但使用内部类型似乎不是正确的解决方案.另一个选择是实现我自己的StaticFileHandler,但正确地这样做(支持范围和etags等HTTP的东西)是非常重要的.

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

Dan*_*son 56

为什么不使用IIS来做到这一点?您可以创建重定向规则,以便在请求进入您的应用程序之前将任何请求从第一个路由指向第二个路由.因此,这将是一种更快速的重定向请求的方法.

假设您有IIS7 +,您可以执行以下操作...

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

或者,如果您不需要重定向,如@ ni5ni6所示:

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

编辑2015-06-17 @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="/a/b/c/{R:1}" redirectType="Permanent" />
        </rule>
      </rules>
    </rewrite>
  </system.webServer>
</configuration>
Run Code Online (Sandbox Code Playgroud)


Rob*_*Mao 41

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

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

routes.IgnoreRoute("{file}.js");
routes.IgnoreRoute("{file}.html");
Run Code Online (Sandbox Code Playgroud)

  • 不知怎的,我似乎错过了拼图中的一块...如何忽略到静态文件的路径有助于从`/ static`到`/ a/b/c`(OP要求)的路由?你能不能对你的答案有所了解,我真的很想了解这个解决方案. (24认同)
  • 同意Oliver的说法,这不会回答OP,也不应该被接受作为解决方案. (18认同)

she*_*mar 12

我有类似的问题.我最终使用了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));
        }
    }
}
Run Code Online (Sandbox Code Playgroud)


Mar*_*age 7

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

}
Run Code Online (Sandbox Code Playgroud)

这是一个黑客.本IRouteHandler应该返回的IHttpHandler,而不是放弃和转移当前请求.但是,它实际上实现了我想要的.

使用内部StaticFileHandler也有点黑客,因为我需要反射来访问它,但至少在MSDN StaticFileHandler有一些文档使它成为一个稍微"官方"的类.不幸的是,我认为不可能在部分信任环境中反映内部类.

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