2016-02-20 8 views
7

Piszę aplikację jednostronicową z kątami 2 i MVC5. Jestem jednak nowicjuszem i mam problem z routingiem.Routing MVC6 do aplikacji jednostronicowej bez utraty 404

Chciałbym dopasować adresy jak:

  • / -> przejdź do mojej strony indeksu, który bootstraps kątowe
  • /api/{controller}/{id?}
  • -> REST API
  • /{*anythingelse} -> jeśli plik istnieje tam , zwróć go jako statyczną treść; w przeciwnym razie, jeśli kanciasty może go poprowadzić, należy wyznaczyć trasę kątową; w przeciwnym razie zwróci 404.

Drugi punkt jest dość łatwy, i mogę sprawić, że routing po stronie klienta będzie działał, jeśli będę chciał zrezygnować z 404 zwrotów, ale nie mogę tego pogodzić.

Wydaje się, że to powinno działać:

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" }); 
}); 

oraz:

@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 }, 
]) 

Ale to właśnie służy Index.cshtml dla każdego wniosku, że nie jest plikiem statycznym.

Czuję, że to już musi być rozwiązany problem, ale nie udało mi się znaleźć niczego w Internecie. Jak to zrobić właściwie?

Używam ścieżek w stylu "HTML5", a nie w stylu mieszania.

+0

Czy Twój API REST za pomocą WebApi? WebApi jest oddzielną strukturą od MVC i ma oddzielną konfigurację trasy. Jeśli używasz MVC (nie WebApi), nie masz tego poprawnie skonfigurowanego - musisz podać domyślną akcję 'defaults: new {action =" Index "}' lub akcję w adresie URL 'api/{controller}/{ akcja}/{id?} '. – NightOwl888

+0

Również twoje założenie o porządku trasy jest niemożliwe.Angularne przebiegi w przeglądarce, więc najpierw będzie trasa. W przeciwnym razie spróbuje skonfigurowane trasy w dokładnej kolejności, w jakiej je skonfigurujesz po stronie serwera. Gdy żądanie trafi na serwer, nie możesz ponownie przekazać kontroli do Angular. – NightOwl888

+0

Ach, przepraszam. Odłożyłem MVC5, ale faktycznie oznaczało MVC6 na ASP.NET 5. W ASP.NET 5 routery WebAPI i MVC zostały scalone. – Emdot

Odpowiedz

0

Są dwa sposoby na zrobienie tego. Jeśli używasz HashLocationStrategy, zdecydowanie zachęcam do zrobienia tego przy implementacji po stronie serwera, ponieważ okazało się, że łatwiej sobie z tym poradzić.

W przeciwnym razie można utworzyć własny składnik RouterOutlet, który obsługuje wyjątki. Nie jestem w 100% jasne, w jaki sposób można uzyskać go do pracy z RouterConfig, ponieważ nie zagłębiłem się głęboko w aspekt routingu, ale założę się, że można zobaczyć, czy istnieje trasa, a następnie przejdź w przeciwnym razie 404 błąd. Oto mój kod, który zajmuje się sprawdzaniem, czy użytkownik jest zalogowany przy użyciu tokenów 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); 
    } 
} 

Jak widać obsłużyć mój sprawdzanie na zasadzie, a jeśli nie mają one token mogą iść tylko do mojej strony logowania. Następnie w komponencie app.component lub bootstrapped używaj tego jako gniazda routera zamiast oryginału.

Przykro mi, ale nie mogę być bardziej pomocny, ale mam nadzieję, że to pozwoli ci wskazać właściwy kierunek!

+0

Być może jestem po prostu gęsty, ale nie śledzę, w jaki sposób przechodzisz z nadpisanego RouterOutlet (po stronie klienta) do 404 (po stronie serwera). – Emdot

+0

Więc próbowałem ci pokazać, że możesz obsłużyć 'jeśli nie istnieje w RoutesConfig route 404' z tym samym rodzajem funkcjonalności, ponieważ za każdy adres URL, który zostanie odebrany przejdzie przez twój nowy router-outlet i zrobi czek . –

+0

Być może mówisz o nie znalezionej stronie, która po prostu _says_ "404"? Szukam rzeczywistego kodu odpowiedzi HTTP 404 z serwera WWW. – Emdot

0

myślę szukasz regex przymusu Trasa:

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

Zapobiegnie to złapać wszystkie trasy od mapowania na każdy wniosek, który zaczyna się od „api /”

Powiązane problemy