webentwicklung-frage-antwort-db.com.de

Verwenden des ASP.NET-Routings zum Bereitstellen statischer Dateien

Kann ASP.Net-Routing (nicht MVC) zum Bereitstellen statischer Dateien verwendet werden?

Angenommen, ich möchte routen

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

zu

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

und ich möchte es dynamisch in dem Sinne tun, dass die umgeschriebene URL im laufenden Betrieb berechnet wird. Ich kann eine statische Route nicht ein für alle Mal einrichten.

Wie auch immer, ich kann eine Route wie diese erstellen:

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

Bei der Methode FileRouteHandler.ProcessRequest Kann ich den Pfad von /static/picture.jpg Zu /a/b/c/picture.jpg Umschreiben. Ich möchte dann einen Handler für statische Dateien erstellen. ASP.NET verwendet zu diesem Zweck das StaticFileHandler. Leider ist diese Klasse intern. Ich habe versucht, den Handler mit Reflection zu erstellen, und es funktioniert tatsächlich:

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

Die Verwendung interner Typen scheint jedoch nicht die richtige Lösung zu sein. Eine andere Möglichkeit besteht darin, mein eigenes StaticFileHandler zu implementieren, aber es ist nicht trivial, dies richtig zu tun (Unterstützung für HTTP-Inhalte wie Bereiche und Etags).

Wie gehe ich beim Routing statischer Dateien in ASP.NET vor?

69

Nachdem ich dieses Problem einige Stunden durchgearbeitet hatte, stellte ich fest, dass beim Hinzufügen von Ignorierregeln Ihre statischen Dateien bereitgestellt werden.

Fügen Sie in RegisterRoutes (RouteCollection-Routen) die folgenden Ignorierregeln hinzu:

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

Verwenden Sie dazu IIS? Sie können einfach eine Umleitungsregel erstellen, um Anforderungen von der ersten auf die zweite Route zu verweisen, bevor die Anforderung überhaupt an Ihre Anwendung gelangt eine schnellere Methode zum Umleiten von Anforderungen sein.

Angenommen, Sie haben IIS7 +, dann tun Sie so etwas wie ...

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

Oder, wenn Sie nicht umleiten müssen, wie von @ ni5ni6 vorgeschlagen:

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

Edit 2015-06-17 für @RyanDawkins:

Und wenn Sie sich fragen, wohin die Umschreiberegel führt, finden Sie hier eine Karte der Position im web.config Datei.

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

Ich hatte ein ähnliches Problem. Ich endete mit 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

Ich habe mir eine Alternative zum internen StaticFileHandler ausgedacht. Im IRouteHandler rufe ich 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.
  }

}

Das ist ein Hack. Das IRouteHandler soll ein IHttpHandler zurückgeben und die aktuelle Anfrage nicht abbrechen und übertragen. Es wird jedoch tatsächlich das erreicht, was ich will.

Die Verwendung des internen StaticFileHandler ist auch etwas hackig, da ich Reflektion brauche, um Zugriff darauf zu erhalten, aber zumindest gibt es einige Dokumentation zu StaticFileHandler auf MSDN so dass es ein etwas mehr "offizielle" Klasse. Leider glaube ich nicht, dass es möglich ist, interne Klassen in einer partiellen Vertrauensumgebung zu reflektieren.

Ich bleibe bei der Verwendung von StaticFileHandler, da ich nicht glaube, dass es in absehbarer Zukunft aus ASP.NET entfernt wird.

6

Sie müssen TransferRequestHandler hinzufügen, um Ihre statischen Dateien verarbeiten zu können.Bitte lesen Sie die folgende Antwort https://stackoverflow.com/a/21724783/22858

4
Prerak K