2016-02-20 15 views
7

Sto scrivendo un'applicazione a pagina singola con angular2 e MVC5. Sono nuovo ad entrambi, però, e ho problemi con il routing.Routing MVC6 all'applicazione a pagina singola senza perdere 404

mi piacerebbe corrispondere gli URL come:

  • / -> vai alla mia pagina di indice, che bootstraps angolari
  • /api/{controller}/{id?} -> REST API
  • /{*anythingelse} -> se un file esiste lì , restituirlo come contenuto statico; altrimenti se l'angolare può instradarlo, avere percorso angolare; altrimenti restituire 404.

Il secondo punto è abbastanza semplice, e posso ottenere il routing sul lato client funzionante se sono disposto a rinunciare a 404 ritorni, ma non riesco a riconciliare tutto.

Sembra che questo dovrebbe funzionare:

app.UseStaticFiles(); 
app.UseMvc(routes => 
{ 
    routes.MapRoute(
     name: "api", 
     template: "api/{controller}/{id?}"); 
    routes.MapRoute(
     name: "spa", 
     template: "{*anythingelse}", 
     defaults: new { controller = "Home", action = "Index" }); 
}); 

e:

@RouteConfig([ 
    { path: "/", name: 'Splash', component: SplashView }, 
    { path: '/accounts/login', name: 'Login', component: LoginView }, 
    { path: '/accounts/register', name: 'Registration', component: RegistrationView }, 
    { path: '/home/...', name: 'Home', component: HomeView }, 
]) 

ma che semplicemente serve Index.cshtml per ogni richiesta che non è un file statico.

Mi sento come se questo fosse già un problema risolto, ma non sono stato in grado di trovare nulla online. Come si fa a farlo correttamente?

Sto utilizzando percorsi in stile "HTML5" anziché in stile hash.

+0

È il vostro API REST utilizzando WebAPI? WebApi è un framework separato da MVC e ha una propria configurazione di route separata. Se usi MVC (non WebApi), non lo hai configurato correttamente - devi fornire un'azione predefinita 'default: new {action =" Index "}' o un'azione nell'URL 'api/{controller}/{ azione}/{id?} '. – NightOwl888

+0

Inoltre, la tua ipotesi sull'ordine di instradamento è impossibile.Esegui angolare nel browser, quindi verrà instradato per primo. Altrimenti tenterà i percorsi che hai configurato nell'ordine esatto in cui li hai configurati sul lato server. Una volta che la richiesta raggiunge il server, non è possibile restituire nuovamente il controllo ad Angular. – NightOwl888

+0

Ah, mi scuso. Ho messo giù MVC5 ma in realtà significava MVC6 su ASP.NET 5. In ASP.NET 5 i router WebAPI e MVC sono stati uniti. – Emdot

risposta

0

Quindi ci sono due modi per farlo. Se stai usando HashLocationStrategy, ti incoraggio vivamente a farlo sull'implementazione lato server perché ho trovato molto più facile gestirlo.

In caso contrario, è possibile creare il proprio componente RouterOutlet che gestisce le eccezioni. Non sono al 100% chiaro su come potresti farlo funzionare con il tuo RouterConfig perché non ho approfondito l'aspetto del routing, ma scommetto che potresti vedere se esiste una rotta, quindi vai lì altrimenti errore 404. Ecco il mio codice che si occupa di vedere se un utente è loggato con token JSON Web.

import {Directive, Attribute, ElementRef, DynamicComponentLoader} from 'angular2/core'; 
import {Router, RouterOutlet, ComponentInstruction} from 'angular2/router'; 

@Directive({ 
    selector: 'router-outlet' 
}) 
export class LoggedInRouterOutlet extends RouterOutlet { 
    publicRoutes: any; 
    private parentRouter: Router; 

    constructor(_elementRef: ElementRef, _loader: DynamicComponentLoader, 
       _parentRouter: Router, @Attribute('name') nameAttr: string) { 
    super(_elementRef, _loader, _parentRouter, nameAttr); 

    this.parentRouter = _parentRouter; 

    } 

    activate(instruction: ComponentInstruction) { 

    if (!localStorage.getItem('jwt') || !tokenNotExpired('jwt')) {//Public Routes does not work with Hash Location Strategy, need to come up with something else. 
     // todo: redirect to Login, may be there is a better way? 
     if(localStorage.getItem('jwt')){ 
     localStorage.removeItem('jwt'); 
     } 
     this.parentRouter.navigate(['Login']); 
    } 
    return super.activate(instruction); 
    } 
} 

Come potete vedere gestisco il mio controllo per il Segno, e se non hanno un gettone possono andare solo alla mia pagina di login. Quindi, nel tuo app.component o nel tuo componente bootstrap, utilizzalo come router-outlet anziché come originale.

Mi dispiace non posso essere più utile, ma spero che questo ti porti nella giusta direzione!

+0

Forse sto semplicemente diventando denso, ma non seguo il modo in cui si ottiene da un RouterOutlet sottoposto a override (lato client) a un 404 (lato server). – Emdot

+0

Quindi quello che stavo cercando di mostrarti è che potresti gestire un 'se non esiste in RouterConfig route 404' con lo stesso tipo di funzionalità, perché per ogni url che viene ricevuto passerà attraverso il tuo nuovo router-outlet e fare un check . –

+0

Stai forse parlando di una pagina non trovata che solo _says_ "404"? Sto cercando un codice di risposta HTTP 404 effettivo dal server web. – Emdot

0

Penso che tu sia alla ricerca di un vincolo percorso regex:

routes.MapRoute("app", "{*anything}", 
    new { controller = "Home", action = "Index" }, 
    new {anything = new RegexRouteConstraint("^(?!api\\/).+") }); 

Questo eviterà che il pescato tutto percorso da mapping a qualsiasi richiesta che inizia con "api /"

Problemi correlati