.Net Core MVC 路由:根据控制器有条件地设置 MapSpaFallbackRoute

.Net Core MVC Routing: Setting MapSpaFallbackRoute Conditionally Per Controller

我正在开发一个项目,该项目涉及托管在单个 .Net Core 1.0 Web 应用程序上的多个单页应用程序。

目标是对每个 SPA 进行分区,以便它们都单独存在,每个 SPA 都有自己的视图和控制器。

在 Startup.cs 中,我使用 Microsoft.AspNetCore.SpaServices MapSpaFallbackRoute 将深层链接传递给 SPA(在本例中为 Angular 2),因此 MVC 不会混淆并抛出页面刷新 404。

当我在 MapSpaFallbackRoute 中手动设置控制器时,我一次可以为一个 SPA 工作,但我想不出一种方法来为每个 SPA 控制器有条件地设置它。

我假设 Mapwhen() 和 运行() 的组合会让我到达我需要去的地方,但我似乎无法获得正确的语法。

假设 SPA 被命名为 'Dash1'、'Dash2' 等。以下后备路线非常适合 Dash1:

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

            routes.MapSpaFallbackRoute("spa-fallback", new { controller = "Dash1", action = "Index" });
        });

我试过这个:

public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
    {

        app.UseMvc(routes =>
        {
            routes.MapRoute(
                name: "default",
                template: "{controller=Home}/{action=Index}/{id?}");
        });
        app.Map("/Dash1", HandleDash1);

    }

    private static void HandleDash1(IApplicationBuilder app)
    {
        app.UseMvc(routes =>
        {
            routes.MapSpaFallbackRoute("spa-fallback", new { controller = "Dash1", action = "Index" });
        });
    }
}

...但是当我导航到 Dash1 并尝试刷新页面时,浏览器会在所有 http 请求前添加“/Dash1/”并破坏所有内容。

我让它与 MapWhen() 一起工作,但每个 SPA 都必须以这种方式注册。

app.MapWhen(context => context.Request.Path.Value.StartsWith("/Dash1"), builder =>
{
    builder.UseMvc(routes =>
    {
        routes.MapSpaFallbackRoute("dash1-fallback", new { controller = "Dash1", action = "Index" });
    });
});

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

我正在使用这种方法托管 Angular(2+) 个应用程序。我最初使用 SystemJS 并将所有应用程序保留在一个项目中,但是当版本 4 发布时我转向了 Angular CLI。

我发现管理应用程序的最佳方法是在解决方案中为每个应用程序创建一个单独的项目,并使用 NPM 脚本将捆绑文件复制到 "master" 项目的 wwwroot 内的文件夹中.

我没有返回视图,而是提供由 CLI 创建的静态 html 文件,但视图也工作正常。

public IActionResult Index()
{
    return PhysicalFile(Path.Combine(Directory.GetCurrentDirectory(), "wwwroot/dash1", "index.html"), "text/HTML");
}

棘手的部分是管理路由器。您必须通过设置 window['_app_base'] 来设置 base href 并将路由切换到 Angular 路由器以对应于当前控制器的路由。

在 index.html 中包含以下内容:

<head>
    // Set base href. 
    // You need to include the path if serving the static file from wwwroot
    // Use '/' if using a View (I think, I had to change this when I switched to static files).

    <base href="/dash1/"> 

    <script>
        (function () {
            // You could type the controller path here again but this will infer it.

            window['_app_base'] = '/' + window.location.pathname.split('/')[1];

        })();
    </script>
</head>

然后,Angular 路由器必须从 window['_app_base'] 获取它的方位。在 app.module.ts 中包括以下内容:

import { NgModule, Provider } from '@angular/core';
import { APP_BASE_HREF, Location } from '@angular/common';
const baseHref: Provider = {
    provide: APP_BASE_HREF,
    useValue: window['_app_base'] || '/'
};

最后,在@NgModule 的providers 数组中包含baseHref。