web-dev-qa-db-ja.com

ASP.NETルーティングを使用して静的ファイルを提供する

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を実装することですが、適切に実装する(範囲やetagなどのHTTPをサポートする)のは簡単ではありません。

ASP.NETの静的ファイルのルーティングにはどのようにアプローチすればよいですか?

69

この問題を数時間掘り下げた後、無視ルールを追加するだけで静的ファイルが提供されることがわかりました。

RegisterRoutes(RouteCollection routes)で、次の無視ルールを追加します。

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

なぜIISを使用してこれを行うのですか?リクエストがアプリケーションに到達する前に、最初のルートから2番目のルートへのリクエストをポイントするリダイレクトルールを作成することができます。リクエストをより迅速にリダイレクトする方法である。

あなたが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>

@ RyanDawkinsの2015-06-17を編集

書き換えルールがどこに行くのか疑問に思っている場合は、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>
52
Dan Atkinson

同様の問題がありました。最終的に 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));
        }
    }
}
11
sheikhomar

内部StaticFileHandlerを使用する代わりに考えました。 IRouteHandlerHttpServerUtility.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.
  }

}

これはハックです。 IRouteHandlerIHttpHandlerを返し、現在のリクエストを中止して転送することはありません。しかし、実際には私が望むものを達成します。

内部のStaticFileHandlerを使用することも、ハッキングです。アクセスするにはリフレクションが必要ですが、少なくともいくつかの MSDNのStaticFileHandlerに関するドキュメント もう少し「公式」なクラス。残念ながら、部分的な信頼環境で内部クラスを反映することは不可能だと思います。

近い将来、ASP.NETから削除されるとは思わないので、StaticFileHandlerの使用に固執します。

6

静的ファイルを処理するためにTransferRequestHandlerを追加する必要があります。次の回答を参照してください https://stackoverflow.com/a/21724783/22858

4
Prerak K