7

Mit RC1 von ASP.NET-Core 1.0 MVC 6 Sie Routen aus Ihrer Startup.Configure Funktion zuordnen können, wenn app.UseMvc aufrufen. Ich habe eine „Spa-Fallback“ Route zugeordnet, die sicherstellen, dass die HomeController und Index Ansicht die Standardwerte wie so ist:MVC 6 Routing, SPA Rückfall + 404 Fehler Seite

public void Configure(IApplicationBuilder app, 
         IHostingEnvironment env, 
         ILoggerFactory loggerFactory) 
{ 
    // ... omitted for brevity 
    app.UseExceptionHandler("/Home/Error"); 
    app.UseStatusCodePagesWithRedirects("/Home/Error/{0}"); 

    app.UseMvc(routes => 
    { 
     routes.MapRoute("default", "{controller=Home}/{action=Index}/{id?}"); 
     routes.MapRoute("spa-fallback", "{*anything}", new { controller = "Home", action = "Index" }); 
     routes.MapWebApiRoute("defaultApi", "api/{controller}/{id?}"); 
    }); 
} 

ich den Rückfall wünschen, so dass mein Angular2 App Routen werden nicht in einem HTTP führen Statuscode 404, nicht gefunden. Aber ich muss auch richtig umgehen, wenn ein Benutzer versehentlich versucht, zu einer nicht vorhandenen Seitenansicht zu navigieren. Sie werden feststellen, dass ich auch app.UseStatusCodePagesWithRedirects("/Home/Error/{0}"); angerufen habe.

Der Anruf auf meine Fehlerseite mit dem Statuscode und die "Spa-Fallback" Route scheinen sich gegenseitig ausschließen - das heißt, es scheint, dass ich nur die eine oder andere haben kann (aber leider nicht beides). Weiß jemand, wie ich es schaffen könnte, das Beste aus beiden Welten zu haben?

+0

Derzeit kann das neue Paket in "Microsoft.AspNetCore.SpaServices": "1.0.0-beta-000005" gefunden werden. –

+0

@SamanAhmadi, sah ich das ...danke –

+0

@DavidPine würden Sie erwägen, die akzeptierte Antwort zu ändern? Ich versuche, meine Street Cred zu bauen ;-) –

Antwort

12

Es hat einige Zeit gedauert, bis ich herausgefunden habe, wie ich das machen kann, ohne meinen Index mit MVC zu bedienen und trotzdem 404s für fehlende Dateien zu erhalten. Hier ist meine http-Pipeline:

public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory) 
    { 
     app.UseDefaultFiles(); 
     app.UseStaticFiles(); 

     app.UseMvc(    
      routes => { 
       routes.MapRoute(
        name: "api", 
        template: "api/{controller}/{action}/{id?}"); 

       // ## commented out since I don't want to use MVC to serve my index.  
       // routes.MapRoute(
       //  name:"spa-fallback", 
       //  template: "{*anything}", 
       //  defaults: new { controller = "Home", action = "Index" }); 
     }); 

     // ## this serves my index.html from the wwwroot folder when 
     // ## a route not containing a file extension is not handled by MVC. 
     // ## If the route contains a ".", a 404 will be returned instead. 
     app.MapWhen(context => context.Response.StatusCode == 404 && 
           !Path.HasExtension(context.Request.Path.Value), 
        branch => { 
          branch.Use((context, next) => { 
           context.Request.Path = new PathString("/index.html"); 
           Console.WriteLine("Path changed to:" + context.Request.Path.Value); 
           return next();}); 

        branch.UseStaticFiles(); 
     });    
    } 
+0

Vielen Dank, dass Sie sich das angesehen haben, ich hätte meine Frage aktualisieren oder sie vorher löschen sollen - da ich es bereits nach der Tat herausgefunden hatte. –

+0

Diese Lösung ist nett, da es keine MVC erfordert. Ich verwende derzeit ASP.NET als statischen Dateiserver (keine MVC), aber ich möchte in der Lage sein, nicht-Asset-Pfade zu "index.html" umzuleiten. –

+1

Nizza Antwort Ich empfehle für das Prädikat Wenn etwas besser Code: 'context => context.Response.StatusCode == 404 && Path.HasExtension (context.Request.Path.Value)' –

3

Ich kam mit zwei möglichen Problemumgehungen/Lösungen.

ASP.NET-Core 1.0 RC1

Mit Angular2 Insbesondere können wir tauschen einfach die LocationStrategy. Zum Beispiel in meinem wwwroot/app/boot.ts habe ich folgendes:

import {provide} from "angular2/core"; 
import {bootstrap} from "angular2/platform/browser"; 
import {LocationStrategy, HashLocationStrategy, ROUTER_PROVIDERS} from "angular2/router"; 
import {HTTP_PROVIDERS} from "angular2/http"; 

import {AppComponent} from "./app.component" 

bootstrap(AppComponent, 
    [ 
     ROUTER_PROVIDERS, 
     HTTP_PROVIDERS, 
     provide(LocationStrategy, { useClass: HashLocationStrategy }) 
    ]); 

Bitte beachte, dass ich die provide Funktion bin unter Verwendung der Standard-LocationStrategy mit dem HashLocationStrategy außer Kraft zu setzen. Dadurch wird die # in der URL und verhindert, dass MVC von falsch 404 des werfen, sondern auch Griffe reagiert richtig mit 404 des, wenn der Benutzer manuell Typen in einer URL, die nicht existiert.

ASP.NET-Core 1.0 RC2

einfach Microsoft.AspNet.NodeServices verwenden. Innerhalb dieser Bibliothek gibt es sowohl AngularServices als auch ReactServices, die speziell die Zuordnung von SPA-Routen über die MapSpaFallbackRoute-Funktion ermöglichen. Ich gebe an, dass wir auf RC2 mit dem Verständnis warten müssen, dass die aktuellen Implementierungen nicht vollständig wie gewünscht funktionieren.

+0

Danke, dass Sie mich darüber informiert haben, ich werde es überprüfen. Auf der eckigen Seite wollte ich Hash-Location-Strategie nicht verwenden, da dies bei HTML5-Browsern nicht erforderlich ist. –

0

starten:

public void Configure(IApplicationBuilder app, 
    IHostingEnvironment env, 
    ILoggerFactory loggerFactory) 
{ 
    app.UseExceptionHandler("/Home/Error"); 
    app.UseStatusCodePagesWithRedirects("/Home/Error/{0}"); 

    app.UseMvc(routes => 
    { 
     routes.MapRoute("default", "{controller=Home}/{action=Index}/{id?}"); 
     routes.MapWebApiRoute("defaultApi", "api/{controller}/{id?}"); 
    }); 

    app.Run(async context => 
    { 
     context.Response.Redirect("/Home/Index"); 
     await Task.CompletedTask; 
    }); 
} 

app.Run() werden alle Anfragen fangen, die keine der Routen vorher definierten überein. Auf diese Weise können Sie Ihr benutzerdefiniertes Spa Fallback erhalten und gleichzeitig app.UseStatusCodePagesWithRedirects() verwenden.