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 neu geschriebene URL im laufenden Betrieb berechnet wird. Ich kann keine statische Route 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())
);
In der FileRouteHandler.ProcessRequest
Methode kann ich den Pfad von /static/picture.jpg
nach umschreiben /a/b/c/picture.jpg
. Ich möchte dann einen Handler für statische Dateien erstellen. ASP.NET verwendet das StaticFileHandler
zu diesem Zweck. Leider ist diese Klasse intern. Ich habe versucht, den Handler mithilfe von 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, meine eigenen zu implementieren StaticFileHandler
, aber dies richtig zu tun (HTTP-Inhalte wie Bereiche und Etags zu unterstützen) ist nicht trivial.
Wie gehe ich beim Routing statischer Dateien in ASP.NET vor?
quelle
/static
nach/a/b/c
(was das OP verlangt hat)? Könnten Sie bitte etwas mehr Licht auf Ihre Antwort werfen, ich würde diese Lösung wirklich gerne verstehen.Warum nicht IIS verwenden, um dies zu tun? Sie können einfach eine Umleitungsregel erstellen, um alle Anforderungen von der ersten auf die zweite Route zu verweisen, bevor die Anforderung überhaupt in Ihre Anwendung gelangt. Aus diesem Grund wäre dies eine schnellere Methode zum Umleiten von Anforderungen.
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 ihres Speicherorts in der
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>
quelle
Ich hatte ein ähnliches Problem. Am Ende habe ich HttpContext.RewritePath verwendet :
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)); } } }
quelle
filename.v1234.js
, verwende ichprivate readonly Regex regJS = new Regex("^(.*)([.]v[0-9]+)([.](js|css))$", RegexOptions.IgnoreCase);
und dann auf Übereinstimmungen, die ich macheContext.RewritePath(string.Format("{0}{1}", matchJS.Groups[1].Value, matchJS.Groups[3].Value));
Ich habe mir eine Alternative zur internen Verwendung ausgedacht
StaticFileHandler
. In derIRouteHandler
rufe ich anHttpServerUtility.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. Der
IRouteHandler
soll eine zurückgebenIHttpHandler
und die aktuelle Anfrage nicht abbrechen und übertragen. Es erreicht jedoch tatsächlich das, was ich will.Das interne zu verwenden
StaticFileHandler
ist auch ein Hack, da ich Reflexion brauche, um Zugriff darauf zu erhalten, aber zumindest gibt es einige DokumentationenStaticFileHandler
zu MSDN , die es zu einer etwas "offizielleren" Klasse machen. Leider glaube ich nicht, dass es möglich ist, interne Klassen in einer partiellen Vertrauensumgebung zu reflektieren.Ich werde mich an die Verwendung halten,
StaticFileHandler
da ich nicht glaube, dass sie in absehbarer Zeit aus ASP.NET entfernt wird.quelle
Sie müssen TransferRequestHandler hinzufügen, um Ihre statischen Dateien zu verarbeiten. Bitte sehen Sie die folgende Antwort: https://stackoverflow.com/a/21724783/22858
quelle