Wie man 404 mit Owin Middleware abfängt

Hintergrun

assen Sie mich zunächst den Hintergrund erläutern. Ich arbeite an einem Projekt, bei dem versucht wird, einen Back-End-Server mit einer Web-API zu verbinden, die über OWIN konfiguriert wurde - der jetzt auf IIS gehostet wird, möglicherweise jedoch über andere von OWIN unterstützte Hosts - und ein Frontend mit AngularJS.

Das AngularJS-Frontend ist vollständig statischer Inhalt. Ich vermeide vollständig serverseitige Technologien wie MVC / Razor, WebForms, Bundles, alles, was mit dem Frontend und den verwendeten Assets zu tun hat, und verschiebe mich stattdessen auf die neuesten und besten Techniken mit Node.js, Grunt / Gulp usw Aus Gründen, auf die ich hier nicht näher eingehen möchte, behalte ich das Frontend und die Serverprojekte an verschiedenen Orten innerhalb desselben Projekts (anstatt sie alle direkt im Host - Projekt zu speichern (siehe roh) Diagramm unten).

MyProject.sln
server
  MyProject.Host
     MyProject.Host.csproj
     Startup.cs
     (etc.)
frontend
  MyProjectApp
     app.js
     index.html
     MyProjectApp.njproj
     (etc.)

So was das Frontend betrifft, muss ich nur meinen Host dazu bringen, meinen statischen Inhalt bereitzustellen. In Express.js ist dies trivial. Mit OWIN konnte ich dies einfach mit @ tu Microsoft.Owin.StaticFiles Middleware, und es funktioniert super (es ist sehr glatt).

Hier ist meinOwinStartup Aufbau

string dir = AppDomain.CurrentDomain.RelativeSearchPath; // get executing path
string contentPath = Path.GetFullPath(Path.Combine(dir, @"../../../frontend/MyProjectApp")); // resolve nearby frontend project directory

app.UseFileServer(new FileServerOptions
{
    EnableDefaultFiles = true,
    FileSystem = new PhysicalFileSystem(contentPath),
    RequestPath = new PathString(string.Empty) // starts at the root of the host
});

// ensure the above occur before map handler to prevent native static content handler
app.UseStageMarker(PipelineStage.MapHandler);
Der Fan

rundsätzlich hostet es nur alles infrontend/MyProjectApp als wäre es direkt im Stammverzeichnis von MyProject.Host. Wenn Sie also eine Datei anfordern, die nicht vorhanden ist, generiert IIS natürlich einen 404-Fehler.

Now, da dies eine AngularJS-App ist und @ unterstüthtml5mode, Ich werde einige Routen haben, die keine physischen Dateien auf dem Server sind, aber in der AngularJS-App als Routen behandelt werden. Wenn ein Benutzer auf ein AngularJS fallen würde (alles andere alsindex.html oder eine Datei, die physisch existiert (in diesem Beispiel), würde ich eine 404 erhalten, obwohl diese Route in der AngularJS-App gültig sein könnte. Daher brauche ich meine OWIN Middleware, um das @ zurückzugebeindex.html -Datei für den Fall, dass eine angeforderte Datei nicht vorhanden ist, und lassen Sie meine AngularJS-App herausfinden, ob es sich wirklich um eine 404 handelt.

Wenn Sie mit SPAs und AngularJS vertraut sind, ist dies ein normaler und unkomplizierter Ansatz. Wenn ich MVC- oder ASP.NET-Routing verwende, kann ich einfach die Standardroute zu einem MVC-Controller festlegen, der mein @ zurückgibindex.html oder so ähnlich. Ich habe jedoch bereits angegeben, dass ich MVC nicht verwende, und ich versuche, dies so einfach und leicht wie möglich zu halten.

Dieser Benutzer hatte ein ähnliches Dilemma und löste es mit dem Umschreiben von IIS. In meinem Fall funktioniert es nicht, weil a) mein Inhalt physisch dort nicht vorhanden ist, wo das URL-Umschreibemodul ihn finden kann, alsoimme kehrt zurückindex.html und b) Ich möchte etwas, das nicht auf IIS angewiesen ist, sondern in der OWIN-Middleware verarbeitet wird, damit es flexibel verwendet werden kann.

TL; DNR ich, für lautes Schreien.

Einfach, wie kann ich einen 404 Not Found abfangen und den Inhalt von (note:nich redirect) myFileServer-serviertindex.html mit OWIN Middleware?

Antworten auf die Frage(8)

Ihre Antwort auf die Frage