Использование маршрутизации ASP.NET для обслуживания статических файлов. - PullRequest
68 голосов
/ 19 июля 2009

Можно ли использовать маршрутизацию ASP.Net (не MVC) для обслуживания статических файлов?

Скажите, что я хочу направить

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, но сделать это правильно (поддерживая такие вещи HTTP, как диапазоны и тэги) нетривиально.

Как мне подойти к маршрутизации статических файлов в ASP.NET?

Ответы [ 5 ]

51 голосов
/ 26 июля 2009

Почему бы не использовать IIS для этого? Вы можете просто создать правило перенаправления, чтобы указать любые запросы от первого маршрута ко второму, прежде чем запрос попадет в ваше приложение. Из-за этого это будет более быстрый способ перенаправления запросов.

Если у вас есть IIS7 +, вы делаете что-то вроде ...

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

или , если вам не нужно перенаправлять, как предлагает @ ni5ni6:

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

Изменить 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>
41 голосов
/ 24 июня 2010

Пройдя несколько часов, разобравшись с этой проблемой, я обнаружил, что простое добавление правил игнорирования приведет к обработке ваших статических файлов.

В RegisterRoutes (маршруты RouteCollection) добавьте следующие правила игнорирования:

routes.IgnoreRoute("{file}.js");
routes.IgnoreRoute("{file}.html");
10 голосов
/ 17 октября 2010

У меня была похожая проблема. В итоге я использовал 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));
        }
    }
}
6 голосов
/ 24 августа 2009

Я придумал альтернативу использованию внутреннего 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.
  }

}

Это хак. IRouteHandler должен возвращать IHttpHandler, а не прерывать и передавать текущий запрос. Тем не менее, он действительно достигает того, чего я хочу.

Использование внутреннего StaticFileHandler также является своего рода хаком, так как мне нужно размышление, чтобы получить к нему доступ, но по крайней мере есть некоторая документация по StaticFileHandler в MSDN , что делает его немного более "официальным " учебный класс. К сожалению, я не думаю, что можно подумать о внутренних классах в среде частичного доверия.

Я буду использовать StaticFileHandler, так как не думаю, что он будет удален из ASP.NET в обозримом будущем.

4 голосов
/ 12 февраля 2014

Вам необходимо добавить TransferRequestHandler для обработки ваших статических файлов. Пожалуйста, смотрите следующий ответ https://stackoverflow.com/a/21724783/22858

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...