5

Ich erstelle eine Client/Server-Lösung mit einer AngularJS Single Page App als Client-Komponente und einer Self-Host ServiceStack RESTful API als Server-Komponente. Ein einzelnes Visual Studio Console-Anwendungsprojekt enthält HTML- und JavaScript-Dateien für die AngularJS-Komponente sowie C# -Klassen für das Bootstrapping des ServiceStack AppHost (ich habe die Verantwortlichkeiten für Interface und Service auf separate Visual Studio-Projekte übertragen).Wie kann ich AngularJS mit dem ServiceStack FallbackRoute-Attribut zur Unterstützung von HTML5-Pushstate-URLs erhalten?

Ich habe alle HTML- und JavaScript-Dateien auf eine 'Build Action' von 'None' und ein 'Copy to Output Directory' von 'Copy if newer' gesetzt.

Alles funktioniert sehr gut, solange ich bereit bin, ein '#' in meinen Site-URLs zu akzeptieren. Ich möchte dies mithilfe von HTML5-Pushstate-URLs eliminieren.

Effektiv bedeutet dies, dass ich ServiceStack dazu überreden muss, meine standardmäßige Single-Page-App-HTML-Shell-Seite zu bedienen, wenn eine nicht existierende Route angefordert wird. Es gibt jetzt ein FallbackRoute Attribut available in ServiceStack, das genau zu diesem Zweck hinzugefügt wurde.

Allerdings bin ich unsicher, wie man es benutzt. Ich habe Leute gefunden, die ähnliche Fragen stellen here, here und here. Aber die Antworten waren alle bevor das neue FallbackRoute-Attribut angekommen ist.

Im Wesentlichen bin ich auf der Suche nach einem einfachen, aber vollständigen Beispiel für die Verwendung des FallbackRoute-Attributs, um sicherzustellen, dass Anfragen an nicht vorhandene Routen auf eine einzige statische HTML-Seite umgeleitet werden.

Antwort

3

sehen es stellt sich heraus, es ist alles sehr einfach mit der FallbackRoute Funktionalität, wenn Sie herausfinden, wie zu Verwenden Sie es richtig:

[FallbackRoute("/{Path*}")] 
    public class Fallback 
    { 
     public string Path { get; set; } 
    } 

    public class FallBackService : Service 
    { 
     public object Any(Fallback request) 
     { 
      return new HttpResult(new FileInfo("index.html")) {ContentType = "text/html"}; 
     } 
    } 

Sobald dies an Ort und Stelle ist, finde ich 'index.html' wird in der Tat serviert immer wenn ich versuche, eine nicht existente Route zu treffen.

Alle statischen Dateien, wie JavaScript- und CSS-Ressourcen, werden als normal angezeigt (vorausgesetzt, sie haben natürlich die Einstellung 'Copy if newer' in 'Copy if newer').

Dies funktioniert wie ein Charme mit der HTML5 Push-state-Funktionalität in AngularJS.

3

Die RazorRockstars.Web hat eine Implementierung. Ich werde es ändern, um eine Wildcard Pfad und eine Standardansicht:

[FallbackRoute("/{Path*}")] 
public class Fallback 
{ 
    public string Path { get; set; } 
    public string PathInfo { get; set; } 
} 

public class RockstarsService : Service 
{ 
    [DefaultView("Index")] 
    public object Any(Fallback request) 
    { 
     request.PathInfo = base.Request.PathInfo; 
     return request; 
    } 
    // ... 
} 

Da dies ein Service ist es eine Seite anzeigen (details here) statt eine Inhaltsseite erfordert.

Im RockStars-Beispiel kann ich nicht bestimmen, welche Ansicht für die FallBackResponse gerendert wird, aber die explizite Einstellung der Ansicht sollte alles sein, was Sie brauchen.

Das Attribut [DefaultView("Index")], das ich der Any-Methode hinzugefügt habe, ordnet die Antwort einer Views/Index.cshtml-Datei zu. Die Index.cshtml Datei kann leer sein, aber für eine Template-Deklaration und die vollständige Markup für Ihre einzigen Seite App kann im Template-Datei (dh _Layout.cshtml)

Ohne Razor

lesen html einen String in und es zurückbringen, während die Inhaltstyp Einstellung eines Attributs „text/html“ mit, wiki docs on service return types

public class RockstarsService : Service 
{ 
    static string readContents; 

    [AddHeader(ContentType = "text/html")] 
    public string Any(Fallback request) 
    { 

     // check timestamp for changes for production use 
     if (readContents == '') { 
      using (StreamReader streamReader = new StreamReader(pathFromConfigFile, Encoding.UTF8)) 
      { 
       readContents = streamReader.ReadToEnd(); 
      } 
     } 
     return readContents; 
    } 
    // ... 
} 
+0

Das ist alles sehr cool. Allerdings würde ich das Razor Plugin lieber nicht hinzufügen müssen, wenn ich es nicht muss. Ich benutze eine einzelne statische HTML-Seite und es scheint übertrieben zu sein, eine Razor-Templating-Engine hinzuzufügen, um eine Fallback-Route hinzuzufügen. – Holf

+0

hinzugefügt 'ohne Rasiermesser' Option –

+0

Sieht sehr schön aus ... Ich werde es später ausprobieren. Vielen Dank! – Holf