Asp.net core mvc MVC6路由到单页应用程序而不丢失404

Asp.net core mvc MVC6路由到单页应用程序而不丢失404,asp.net-core-mvc,angular2-routing,Asp.net Core Mvc,Angular2 Routing,我正在用angular2和MVC5编写一个单页应用程序。不过,我对这两个都是新手,而且我在路由方面遇到了麻烦 我希望将URL匹配为: /->转到我的索引页面,该页面将引导 /api/{controller}/{id?}->restapi /{*anythingelse}->如果文件存在,则将其作为静态内容返回;否则,如果角度可以路由它,有角度路由它;否则返回404 第二点很简单,如果我愿意放弃404返回,我可以让客户端路由正常工作,但我似乎无法协调这一切 看来这应该行得通: app.UseS

我正在用angular2和MVC5编写一个单页应用程序。不过,我对这两个都是新手,而且我在路由方面遇到了麻烦

我希望将URL匹配为:

  • /
    ->转到我的索引页面,该页面将引导
  • /api/{controller}/{id?}
    ->restapi
  • /{*anythingelse}
    ->如果文件存在,则将其作为静态内容返回;否则,如果角度可以路由它,有角度路由它;否则返回404
第二点很简单,如果我愿意放弃404返回,我可以让客户端路由正常工作,但我似乎无法协调这一切

看来这应该行得通:

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

但这只是为不是静态文件的每个请求提供Index.cshtml

我觉得这个问题一定已经解决了,但我还没能在网上找到任何关于它的信息。如何正确地做到这一点


我使用的是“HTML5”样式的路径,而不是散列样式。

所以有两种方法可以做到这一点。如果您使用的是HashLocationStrategy,我强烈建议您在服务器端实现中使用它,因为我发现它更容易处理

否则,您可以创建自己的RouteOutlet组件来处理异常。我不是100%清楚如何让它与您的RouterConfig一起工作,因为我没有深入研究路由方面,但我打赌您可以看到是否存在路由,然后转到那里,否则404错误。下面是我的代码,用于查看用户是否使用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);
  }
}
如您所见,我负责检查令牌,如果他们没有令牌,他们只能转到我的登录页面。然后在您的app.component或引导组件中,只需将其用作路由器出口,而不是原始出口


对不起,我帮不了你什么忙,但我希望这能帮你找到正确的方向

我认为您正在寻找正则表达式路由约束:

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

这将防止您的全面捕获路由映射到以“api/”开头的任何请求。

您的RESTAPI是否使用WebApi?WebApi是一个独立于MVC的框架,具有自己的独立路由配置。如果使用MVC(不是WebApi),您没有正确配置它-您需要提供一个默认操作
默认值:new{action=“Index”}
或URL
api/{controller}/{action}/{id?}
中的操作。此外,关于路由顺序的假设是不可能的。角度在浏览器中运行,因此它将首先布线。否则,它将尝试按照您在服务器端配置路由的正确顺序配置路由。一旦请求到达服务器,你就不能再把控制权交给Angular了。啊,我道歉。我写下了MVC5,但实际上是指ASP.NET5上的MVC6。在ASP.NET 5中,WebAPI和MVC路由器已经合并。从角度导航应该不是问题,因为我只提供对现有页面的导航,因此不需要404。我主要关注的是用户直接输入URI的情况。在那里,服务器得到了第一个破解,如果它知道客户端将接受哪个URI,则可能返回404。也许我可以通过某种方式通过工具告诉服务器。也许我只是简单地说得很密集,但我不明白你是如何从一个被覆盖的RouterOutlet(客户端)到一个404(服务器端)的。所以我想告诉你的是,如果RouterConfig route 404中不存在同样的功能,你可以处理一个
,因为收到的每个url都会经过新的路由器出口并进行检查。你是在说一个只写着“404”的未找到页面吗?我正在从web服务器上寻找一个实际的404HTTP响应代码。我可能会看看Angular2的服务器端渲染。我没有深入研究它,但是您可以处理404服务器端,然后将其发送到angular。
routes.MapRoute("app", "{*anything}", 
    new { controller = "Home", action = "Index" }, 
    new {anything = new RegexRouteConstraint("^(?!api\\/).+") });