Using ASP.NET routing to serve static files

Why not use IIS to do this? You could create a redirect rule to point any requests from the first route to the second one before it even gets to your application. Because of this, it would be a quicker method for redirecting requests.

Assuming you have IIS7+, you would do something like...

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

Or, if you don't need to redirect, as suggested by @ni5ni6:

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

Edit 2015-06-17 for @RyanDawkins:

And if you're wondering where the rewrite rule goes, here is a map of its location in the web.config file.

<?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>

After digging through this problem for a few hours, I found that simply adding ignore rules will get your static files served.

In RegisterRoutes(RouteCollection routes), add the following ignore rules:

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

I've had a similar problem. I ended up using 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));
        }
    }
}

I came up with an alternative to using the internal StaticFileHandler. In the IRouteHandler I call 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.
  }

}

This is a hack. The IRouteHandler is supposed to return an IHttpHandler and not abort and transfer the current request. However, it does actually achieve what I want.

Using the internal StaticFileHandler is also somewhat a hack since I need reflection to get access to it, but at least there is some documentation on StaticFileHandler on MSDN making it a slightly more "official" class. Unfortunately I don't think it is possible to reflect on internal classes in a partial trust environment.

I will stick to using StaticFileHandler as I don't think it will get removed from ASP.NET in the foreseeable future.


You need to add TransferRequestHandler for handling your static files.Please see following answer https://stackoverflow.com/a/21724783/22858