web-dev-qa-db-ja.com

.Net Core MVCルーティング:コントローラーごとに条件付きでMapSpaFallbackRouteを設定

私は、単一の.Net Core 1.0Webアプリでホストされている複数のシングルページアプリケーションを含むプロジェクトを開発しています。

目標は、各SPAを分割して、それぞれが独自のビューとコントローラーを持つ個別に存在するようにすることです。

Startup.csで、Microsoft.AspNetCore.SpaServices MapSpaFallbackRouteを使用してSPAへのディープリンク(この場合はAngular 2))を渡すため、MVCが混乱して404をスローすることはありません。ページの更新。

MapSpaFallbackRouteでコントローラーを手動で設定すると、一度に1つのSPAで機能しますが、各SPAコントローラーに条件付きで設定する方法がわかりません。

Mapwhen()とRun()を組み合わせると、必要な場所に移動できると思いますが、構文が正しくないようです。

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 /」を追加し、すべてを中断します。

9
David

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を使用していて、すべてのアプリを1つのプロジェクトに保持していましたが、バージョン4がリリースされたときにAngular CLIに移行しました。

アプリを管理するために私が見つけた最善の方法は、アプリごとにソリューションで個別のプロジェクトを作成し、NPMスクリプトを使用して、バンドルされたファイルを「マスター」プロジェクトのwwwroot内のフォルダーにコピーすることです。

ビューを返す代わりに、CLIによって作成された静的htmlファイルを提供しているだけですが、ビューも正常に機能します。

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

トリッキーな部分はルーターの管理です。現在のコントローラーのルートに対応するようにwindow ['_ app_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ルーターはウィンドウ['_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を含めます。

19
David