MVC6 for single-page lossless application 404

I am writing a single page application with angular2 and MVC5. I am new to both and am having problems with routing.

I would like to match the urls as:

  • / → go to my index page which will load angular
  • /api/{controller}/{id?} → REST API
  • /{*anythingelse} → if the file exists there, return it as static content; otherwise, if angular can route it, angular its route; otherwise return 404.

The second point is quite simple, and I can configure client-side routing if I am willing to refuse 404 returns, but I cannot reconcile all this.

This seems to work:

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

and

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

But it just serves as Index.cshtml for every request that is not a static file.

It seems to me that this is already a problem, but I could not find anything on the Internet. How to do it right?

I use "HTML5" types, not a hash style.

+7
asp.net-core-mvc angular2-routing
source share
2 answers

So there are two ways to do this. If you use HashLocationStrategy, I would strongly recommend that you do this on the side of your server side implementation, since it was much easier for me to handle it.

Otherwise, you can create your own RouterOutlet component that handled exceptions. I am not 100% understandable how you can make it work with your RouterConfig, since I did not guess about it in the direction of routing, but I am sure you can see if the route exists and then go there, otherwise - error 404 Here is my code that deals with viewing if the user is logged in with Json Web tokens.

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

As you can see, I am processing my check for Token, and if they do not have a token, they can only go to my login page. Then in your app.component application or your boot component, just use this as your exit router instead of the original.

Sorry, I could not be more helpful, but I hope this makes you point in the right direction!

0
source share

I think you are looking for a regex route restriction:

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

This will prevent your route from route to any request starting with "api /"

0
source share

All Articles