none
ASP.NET Core 3.0 にて Area を含んだルーティングが正しく動作しない RRS feed

  • 質問

  • ASP.NET Core 2.2 から 3.0 になった際、Startup.cs のルーティング部分の定義が変更されたので合わせて修正してみたのですが、想定した動きにならないため質問させていただきます。2.2 のころは正常に意図した動作をしていました。ちなみに MVC プロジェクトです。

    まず、エリアの構成ですが特別なことはしておらず、新規プロジェクトにエリアを追加したぐらいの構成になっています。直接 URL を入力すればルーティングの設定にもよりますが、エリアで設定した内容が表示されることは確認しています。

    (HomeController の属性に [Area("TestArea")] は追加しています。)

    で、今回設定したいルーティングは以下のものとなっています。

    endpoints.MapAreaControllerRoute(
         name: "TestArea",
         areaName: "TestArea",
         pattern: "{culture}/{area:exists}/{controller=Home}/{action=Index}");

    ちなみに他のサイトにもよく載っている「pattern: "{area:exists}/{controller=Home}/{action=Index}"」のパターンは正しく動作していることは確認しています。要は URL の前に culture を指定できるようにしたいのです。

    UseEndpoints の部分の定義は以下のようにしています。

    app.UseEndpoints(endpoints =>
    {
      endpoints.MapAreaControllerRoute(
        name: "TestArea",
        areaName: "TestArea",
        pattern: "{culture}/{area:exists}/{controller=Home}/{action=Index}");
    
      endpoints.MapControllerRoute(
        name: "culture",
        pattern: "{culture}/{controller=Home}/{action=Index}/{id?}");
    
      endpoints.MapControllerRoute(
        name: "default",
        pattern: "{controller=Home}/{action=Index}/{id?}");
    });
    

    この設定で実行しhttps://localhost:xxxxx/ja/」にアクセスすると TestArea の HomeController の方が呼ばれ表示されてしまいます。

    おそらくこれは「area:exists」を指定しているからだと思いましたので代わりに以下のように直接 TestArea を pattern に入れてみました。

    endpoints.MapAreaControllerRoute(
      name: "TestArea",
      areaName: "TestArea",
      pattern: "{culture}/TestArea/{controller=Home}/{action=Index}");
    このパターンで「https://localhost:xxxxx/ja/」にアクセスすると TestArea ではない純粋な HomeController が呼ばれました。

    この状態でルート URL から TestArea に対してリンクを張りたいので以下のパターンでリンクを張ってみました。

    <ul> <li><a asp-area="TestArea">TestArea area</a></li> <li><a asp-area="TestArea" asp-controller="Home">TestArea area controller</a></li> <li><a asp-area="TestArea" asp-controller="Home" asp-action="Index">TestArea area controller action</a></li> <li><a asp-area="TestArea" asp-controller="Home" asp-action="Privacy">TestArea Privacy</a></li>
    <li><a asp-area="" asp-controller="Home" asp-action="Index">Index</a></li>
    <li>@Html.ActionLink("ActionLink - Home - Index", "Index", "Home")</li>
    </ul>

    この状態で実行し「https://localhost:xxxxx/ja/」にアクセスしました。期待するリンク URLは

    • /ja/TestArea/
    • /ja/TestArea/Home/    (Home はなくてもよい)
    • /ja/TestArea/Home/Index    (Home/Index はなくてもよい)
    • /ja/TestArea/Home/Privacy
    • /ja/Home/Index    (Home/Index はなくてもよい)
    • /ja/Home/Index    (Home/Index はなくてもよい)

    なのですが、実際には以下のリンク URL が生成されてしまいます。

    • /?area=TestArea
    • /?area=TestArea
    • /?area=TestArea
    • /Home/Privacy?area=TestArea
    • /ja
    • /ja

    となってしまいます。

    ASP.NET Core MVC 2.2 のころはこのような指定でも問題なく動作したのですが、3.0 ではどう指定すれば正しい動作になってくれるかがよくわかっておりません。

    ちなみに他サイトを参考にして以下のようなパターンを試してみましたがいずれも想定した動作にはなってくれませんでした。

    • デフォルトルーティングの「pattern: "{controller=Home}/{action=Index}/{id?}」を削除する。
    • TestArea の HomeController の属性に [Route("{culture}/TestArea/[controller]/[action]")] を追加する。
    • TestArea ルーティングからデフォルト値を削除する。「pattern: "{culture}/TestArea/{controller}/{action}"
    • MapAreaControllerRoute の処理を MapControllerRoute の後に配置する。

    ASP.NET Core 3.0 でエリアを含めたルーティング方法に詳しい方がいればご教示いただければと思います。

    2019年10月22日 10:11

すべての返信

  • 特に回答がないようなのでいったん

    app.UseMvc

    で回避しようかと思います。(ASP.NET Core 3.0 でも使えるっぽいです)

    2019年10月29日 5:37
  • おのでらさん、こんにちは。フォーラムオペレーターのクモです。
    MSDN
    フォーラムにご投稿くださいましてありがとうございます

    ご説明いただいたことによると、これはASP.NET Coreルーティング、 ASP.NET Coreカルチャと ASP.NET Coreエリアなどの複数のパーツに関わるかと思います。
    この問題を再現できるデモなどをご提供いただくことで他のユーザー様よりのご意見が集まりやすくなります

    どうぞよろしくお願いいたします

    MSDN/ TechNet Community Support kumo 
    ~参考になった投稿には「回答としてマーク」をご設定ください。なかった場合は「回答としてマークされていない」も設定できます。同じ問題で後から参照した方が、情報を見つけやすくなりますので、 ご協力くださいますようお願いいたします。また、MSDNサポートに賛辞や苦情がある場合は、MSDNFSF@microsoft.comまでお気軽にお問い合わせください。~

    2019年10月29日 7:26
  • 回答ありがとうございます。

    例として Culture と入れてありますが、実際のサンプルでは Culture に関する処理は一切入れておりません。(Route の名前にしているだけです)

    デモということですが、以下の手順で簡単に再現できると思います。

    1. ASP.NET core MVC 3.0 のプロジェクトを新規で作成する
    2. Area を追加する。(処理が来るか確認するだけでいいので Area のコードは Controller だけでもいいです)
    3. 前述のルーティングを登録する。
    4. 初期配置の index.html にリンクを置く
    5. 実行して Web ブラウザでアクセス

    2019年11月8日 13:19
  • おのでらさん、こんにちは。フォーラムオペレーターのクモです。
    ご返信いただきありがとうございます。

    MVC コントローラというドキュメントによって、次の手順で問題を再現できません。

    1. ASP.NET core MVC 3.0 のプロジェクトを新規で作成する
    2. `HomeController` and `[Area("TestArea")]`でArea を追加する。

    ```
        [Area("TestArea")]
        public class HomeController : Controller
        {
            public IActionResult Index()
            {
                return View();
            }
        }
    ````

    3. `Startup.cs`

    ```
            public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
            {
                if (env.IsDevelopment())
                {
                    app.UseDeveloperExceptionPage();
                }
                else
                {
                    app.UseExceptionHandler("/Home/Error");
                    // The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.
                    app.UseHsts();
                }
                app.UseHttpsRedirection();
                app.UseStaticFiles();
    
                app.UseRouting();
    
                app.UseAuthorization();
    
                app.UseEndpoints(endpoints =>
                {
                    endpoints.MapAreaControllerRoute(
                        "TestArea",
                        "TestArea",
                        "TestArea/{controller=Home}/{action=Index}/{id?}");
                    endpoints.MapControllerRoute(
                        "default", "{controller=Home}/{action=Index}/{id?}");            
    
                });
    
            }
    ```

    4. Result

    既定ルートは` TestArea/{controller=Home}/{action=Index}/{id?}`ですので、“/TestArea”は`/TestArea/Home/Index`に変わりません。
     <a asp-area="TestArea" asp-controller="Home" asp-action="Privacy">

    は特定アクションに変わりました。

    どうぞよろしくお願いいたします。 


    MSDN/ TechNet Community Support Kumo ~参考になった投稿には「回答としてマーク」をご設定ください。なかった場合は「回答としてマークされていない」も設定できます。同じ問題で後から参照した方が、情報を見つけやすくなりますので、 ご協力くださいますようお願いいたします。また、MSDNサポートに賛辞や苦情がある場合は、MSDNFSF@microsoft.comまでお気軽にお問い合わせください。~

    2019年11月11日 8:25
  • kumo-msft さん回答ありがとうございます。

    以下の2つの手順の追加をお願いできますでしょうか。

    【1】UseEndpoints の追加

    app.UseEndpoints(endpoints =>
    {
      endpoints.MapAreaControllerRoute(
        name: "TestArea",
        areaName: "TestArea",
        pattern: "{xxxx}/TestArea/{controller=Home}/{action=Index}");
    
      endpoints.MapControllerRoute(
        name: "xxxx",
        pattern: "{xxxx}/{controller=Home}/{action=Index}/{id?}");
    
      endpoints.MapControllerRoute(
        name: "default",
        pattern: "{controller=Home}/{action=Index}/{id?}");
    });

    【2】Web ブラウザで「http://localhost/xxxx/」にアクセス

    ※「localhost」やポート番号については実行環境に合わせてください。「xxxx」はなんでもいいです。

    よろしくお願いいたします。



    2019年11月11日 9:07
  • 追記になりますが、以下は UseMvc の方を使用して意図した動作(リンクURL)になるものとなります。(これと同じ動作を UseEndpoints でもできるかどうか)

    Startup.cs

    // This method gets called by the runtime. Use this method to add services to the container.
    public void ConfigureServices(IServiceCollection services)
    {
      services.AddControllersWithViews();
    
      // ここを追加
      services.AddMvc(options =>
      {
        options.EnableEndpointRouting = false;
      });
    }
    
    // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
    public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
    {
      if (env.IsDevelopment())
      {
        app.UseDeveloperExceptionPage();
      }
      else
      {
        app.UseExceptionHandler("/Home/Error");
        // The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.
        app.UseHsts();
      }
      app.UseHttpsRedirection();
      app.UseStaticFiles();
    
      app.UseRouting();
    
      app.UseAuthorization();
    
      // UseMvc に置き換えるのでコメントアウト
      //app.UseEndpoints(endpoints =>
      //{
      //});
    
      app.UseMvc(routes =>
      {
        routes.MapAreaRoute(
          name: "TestArea",
          areaName: "TestArea",
          template: "{culture}/TestArea/{controller=Home}/{action=Index}/");
    
        routes.MapRoute(name: "culture", template: "{culture}/{controller=Home}/{action=Index}");
    
        routes.MapRoute(name: "default", template: "{controller=Home}/{action=Index}");
      });
    }


    2019年11月11日 9:22
  • おのでらさん、こんにちは。フォーラムオペレーターのクモです。
    ご返信いただきありがとうございます。

    「UseMvc を使用する」とはどういう意味ですか?
    'UseEndpoints ' を使用してコードを共有していましたが、'/jp/testarea' のような期待どおりの結果が得られました。

    期待される結果は何でしょうか?
    現在の結果は次の構成です:
    app.UseEndpoints(endpoints =>
                {
                    endpoints.MapAreaControllerRoute(
                        name: "TestArea",
                        areaName: "TestArea",
                        pattern: "jp/TestArea/{controller=Home}/{action=Index}");
    
                    endpoints.MapControllerRoute(
                      name: "jp",
                      pattern: "jp/{controller=Home}/{action=Index}/{id?}");
    
                    endpoints.MapControllerRoute(
                      name: "default",
                      pattern: "{controller=Home}/{action=Index}/{id?}");
    
    
                    //endpoints.MapAreaControllerRoute(
                    //    "TestArea",
                    //    "TestArea",
                    //    "TestArea/{controller=Home}/{action=Index}/{id?}");
                    //endpoints.MapControllerRoute(
                    //    "default", "{controller=Home}/{action=Index}/{id?}");               
                });

    どうぞよろしくお願いいたします。 

    MSDN/ TechNet Community Support Kumo ~参考になった投稿には「回答としてマーク」をご設定ください。なかった場合は「回答としてマークされていない」も設定できます。同じ問題で後から参照した方が、情報を見つけやすくなりますので、 ご協力くださいますようお願いいたします。また、MSDNサポートに賛辞や苦情がある場合は、MSDNFSF@microsoft.comまでお気軽にお問い合わせください。~

    2019年11月12日 1:33
  • 回答ありがとうございます。

    期待される結果については貼っていただいた画像の通りで大丈夫です。(すみません、なぜかこのアカウントではが画像やリンクが貼れないのでご容赦ください)

    UseEndpoints の箇所については「jp」は固定ではありません。任意の値を入れられるようにしたいので以下のように記載お願いします。(「en」とか「fr」とか入れたい)

    app.UseEndpoints(endpoints =>
    {
      endpoints.MapAreaControllerRoute(
        name: "TestArea",
        areaName: "TestArea",
        pattern: "{culture}/TestArea/{controller=Home}/{action=Index}");
    
      endpoints.MapControllerRoute(
        name: "culture",
        pattern: "{culture}/{controller=Home}/{action=Index}/{id?}");
    
      endpoints.MapControllerRoute(
        name: "default",
        pattern: "{controller=Home}/{action=Index}/{id?}");
    });


    で、「UseMvc」の方ではこの pattern (template) の指定の仕方でも、貼っていただいた画像のようにリンクが生成されますが、UseEndpoints ではリンクが「https://localhost/?area=TestArea」のようになってしまいます。




    2019年11月12日 1:42
  • おのでらさん、こんにちは。フォーラムオペレーターのクモです。
    ご返信いただきありがとうございます。

    ご説明に基づいて、ご質問は「culture」に関連していますが、
    カルチャ機能の設定方法を教えていただけませんか?

    問題を再現できるミニデモをご提供いただければ役に立ちます。

    どうぞよろしくお願いいたします。 

    MSDN/ TechNet Community Support Kumo ~参考になった投稿には「回答としてマーク」をご設定ください。なかった場合は「回答としてマークされていない」も設定できます。同じ問題で後から参照した方が、情報を見つけやすくなりますので、 ご協力くださいますようお願いいたします。また、MSDNサポートに賛辞や苦情がある場合は、MSDNFSF@microsoft.comまでお気軽にお問い合わせください。~


    2019年11月12日 2:25
  • kumo-msft さん

    回答ありがとうございます。

    スレッドが戻ってしまいますが、今回のサンプルでは culture に関する設定は特に何もしておりません。(これまでのスレッドの流れが全てで、これ以上追加するものはありません)。ルーティングの culture については例えで出しているだけですので、culture」と入れている部分は、実際には「aa」でも「bb」でもなんでもかまいません。

    質問内容は UseEndpoints でルーティングを指定しているにも関わらず「<a asp-area="TestArea" ....」が生成するリンクの URL が「jp/TestArea/Home/Privacy」ようになってくれないのがなぜなのかという質問でした。

    ASP.NET Core 2.2 まではルーティングの設定は「app.UseMvc」メソッドで行っていましたが、ルーティングを「template: "{culture}/TestArea/{controller=Home}/{action=Index}」のように指定するだけで<a asp-area="TestArea" ....」がjp/TestArea/Home/Privacy」という URL を生成してくれます。

    ASP.NET Core 3.0 でプロジェクトを新規で作るとルーティングの設定が UseEndpoints で作られていたのでこちらに切り替えようと思い試してみたら生成されるリンクが意図していないもの(/?area=TestArea のように)になったので質問させていただきました。

    分かりにくくてすみません。

    【追記】

    全然関係ない話なのですが、リンクや画像が貼れず、ファイルのアップロードもできないのですがミニデモなどはどのように提示すればよろしいでしょうか?



    2019年11月12日 2:41
  • おのでらさん、こんにちは。フォーラムオペレーターのクモです。
    ご返信いただきありがとうございます。

    生成された URL として「jp」を取得したいんですか、それともリクエストパスに基づいて動的カルチャ文字列を取得したいんですか?

    デフォルトで「jp/TestArea/Home/Privacy」 を生成したい場合は、次のコードを試してみてください。
    app.UseEndpoints(endpoints =>
                {
                    endpoints.MapAreaControllerRoute(
                        name: "TestArea",
                        areaName: "TestArea",
                        pattern: "{culture=jp}/TestArea/{controller=Home}/{action=Index}");
    
                    endpoints.MapControllerRoute(
                      name: "culture",
                      pattern: "{culture=jp}/{controller=Home}/{action=Index}/{id?}");
    
                    endpoints.MapControllerRoute(
                      name: "default",
                      pattern: "{controller=Home}/{action=Index}/{id?}");           
                });
    URL 生成の場合は、 DefaultLinkGeneratorによってできます。

     「endpoints.MapControllerRoute」、または 「asp-route-culture="en" 」で 「カルチャ」をパスしなかった場合は、「カルチャ」の値を決定することができません。
     次に、「?area=testarea」のようなクエリ文字列 URL のみが生成されます。

    そして、「asp-area」関数で動的なカルチャパラメータを決定することはできないことに気になっています。
    カルチャを設定したい場合は、次のように試してみてください。
     <li><a asp-area="TestArea" asp-route-culture="en">TestArea area</a></li>
    どうぞよろしくお願いいたします。 

    MSDN/ TechNet Community Support Kumo ~参考になった投稿には「回答としてマーク」をご設定ください。なかった場合は「回答としてマークされていない」も設定できます。同じ問題で後から参照した方が、情報を見つけやすくなりますので、 ご協力くださいますようお願いいたします。また、MSDNサポートに賛辞や苦情がある場合は、MSDNFSF@microsoft.comまでお気軽にお問い合わせください。~

    2019年11月12日 7:40
  • kumo-msft さん、回答ありがとうございます。

    基本的にはルーティングや A タグ(asp-route-culture など)には初期値は与えず、URL で「http://localhost/xxxx/」などにアクセスしたときの xxxx の部分に入力された値をもとにリンクを生成したいと思っております。

    app.UseMvc の動作になりますが、例えばルーティングの部分を

    app.UseMvc(routes =>
    {
      routes.MapAreaRoute(
        name: "TestArea",
        areaName: "TestArea",
        template: "{culture}/TestArea/{controller=Home}/{action=Index}/");
    
      routes.MapRoute(name: "culture", template: "{culture}/{controller=Home}/{action=Index}");
    
      routes.MapRoute(name: "default", template: "{controller=Home}/{action=Index}");
    });

    と定義し、.cshtml のリンク部分を

    <ul>
    	<li><a asp-area="TestArea">TestArea area</a></li>
    	<li><a asp-area="TestArea" asp-controller="Home">TestArea area controller</a></li>
    	<li><a asp-area="TestArea" asp-controller="Home" asp-action="Index">TestArea area controller action</a></li>
    	<li><a asp-area="TestArea" asp-controller="Home" asp-action="Privacy">TestArea Privacy</a></li>
    	<li><a asp-area="" asp-controller="Home" asp-action="Index">Index</a></li>
    	<li>@Html.ActionLink("ActionLink - Home - Index", "Index", "Home")</li>
    </ul>

    と定義したときに (コードは今まで記載したものと同じです)、Web ブラウザで「http://localhost/ja」にアクセスすると生成されるリンクは

    • /ja/TestArea
    • /ja/TestArea
    • /ja/TestArea
    • /ja/TestArea/Home/Privacy
    • /ja
    • /ja

    となります。「http://localhost/en」でアクセスすれば

    • /en/TestArea
    • /en/TestArea
    • /en/TestArea
    • /en/TestArea/Home/Privacy
    • /en
    • /en

    となり、適当に「http://localhost/zzzzz」とアクセスすれば

    • /zzzzz/TestArea
    • /zzzzz/TestArea
    • /zzzzz/TestArea
    • /zzzzz/TestArea/Home/Privacy
    • /zzzzz
    • /zzzzz

    となってくれます。何も指定せずに「http://localhost/」とアクセスした場合はリダイレクトを考えているので無視しても大丈夫です。UseMvc を使用したときはこのコードだけで目的の URL を生成してくれたので、ほかの画面でリンクを作るときもルーティングの「culture」の部分を意識せずに Area, Controller, Action の指定だけでリンクを構築することができました。

    DefaultLinkGenerator については存在を知りませんでした。こちらも調べてみたいと思います。

    2019年11月12日 8:11
  • おのでらさん、こんにちは。フォーラムオペレーターのクモです。
    ご返信いただきありがとうございます。

    それは不可能です。そして、これは仕様です。

    エンドポイント ルーティングで使用する場合は、リンク生成のアンビエント値の無効化アルゴリズム の動作が異なります。
    アンビエント値の無効化 は、現在実行中の要求からのルート値 (アンビエント値) のうち、どちらがリンク生成操作で使用できのかを判断するアルゴリズムです。 規則ルーティングでは、異なるアクションへのリンク時に余分なルート値が常に無効化されました。 属性ルーティングは、ASP.NET Core 2.2 のリリースより前ではこのように動作しませんでした。 以前のバージョンの ASP.NET Core では、同じルート パラメーター名を使用する別のアクションへのリンクでリンク生成エラーが発生しました。 ASP.NET Core 2.2 以降では、両方の形式のルーティングで、別のアクションへのリンク時に値が無効化されます。

    もっと詳しい情報は、次のリンクをご参照ください。
    https://docs.microsoft.com/ja-jp/aspnet/core/fundamentals/routing?view=aspnetcore-3.0#endpoint-routing-differences-from-earlier-versions-of-routing

    どうぞよろしくお願いいたします。 


    MSDN/ TechNet Community Support Kumo ~参考になった投稿には「回答としてマーク」をご設定ください。なかった場合は「回答としてマークされていない」も設定できます。同じ問題で後から参照した方が、情報を見つけやすくなりますので、 ご協力くださいますようお願いいたします。また、MSDNサポートに賛辞や苦情がある場合は、MSDNFSF@microsoft.comまでお気軽にお問い合わせください。~

    2019年11月12日 9:35
  • kumo-msft さん、回答ありがとうございます。また、情報の提示ありがとうございます。

    いろいろなパターンのリンクを作って試してみた結果、エリア間を移動するようなリンクを生成しようとした場合に目的のリンクが生成されないことが分かりました。

    ■問題なくリンクが生成されるパターン

    • エリアなし ⇔ エリアなし の相互移動
    • Aエリア ⇔ Aエリア (同一エリア内) の相互移動

    ■リンクの生成に問題のあるパターン

    • エリアなし ⇔ エリアあり の相互移動
    • Aエリア ⇔ Bエリア (別エリア間) の相互移動

    方針はまだ決まっていないのですが、とりあえず以下のどれかで対応しようと思っています。

    • これまでと同様 UseMvc のルーティングを使用して進める。(ただしいつまで使えるのかが気になる)
    • エリア間を移動するリンクを作る場合は「<a asp-area="TestArea" asp-route-xxxx="yyyy">」のyyyyの部分を現在の URL (またはそれに付随する設定値) によって動的に設定するようにする。(まだ未確認)
    2019年11月13日 2:52
  • おのでらさん、こんにちは。フォーラムオペレーターのクモです。
    ご返信いただきありがとうございます。

    ご要求を満たしているかどうかを確認するために、以下の構成を試してみることをお勧めします。
    app.UseEndpoints(endpoints =>
                {
                    endpoints.MapControllerRoute(
                      name: "culture",
                      pattern: "{culture=jp}/{area}/{controller=Home}/{action=Index}/{id?}");
                    endpoints.MapControllerRoute(
                      name: "default",
                      pattern: "{culture=jp}/{controller=Home}/{action=Index}/{id?}");
                });
    

    どうぞよろしくお願いいたします。 

    MSDN/ TechNet Community Support Kumo ~参考になった投稿には「回答としてマーク」をご設定ください。なかった場合は「回答としてマークされていない」も設定できます。同じ問題で後から参照した方が、情報を見つけやすくなりますので、 ご協力くださいますようお願いいたします。また、MSDNサポートに賛辞や苦情がある場合は、MSDNFSF@microsoft.comまでお気軽にお問い合わせください。~

    2019年11月13日 8:14
  • kumo-msft さん、回答ありがとうございます。

    試してみたところ、「asp-route-culture="xxxx"」を入れなくても概ね期待通りのリンクが生成されました。(例えば https://localhost/en でアクセスすればほとんどのリンクで en が維持される)

    ただ1点、「エリアあり」から「エリアなし」へのリンクの場合、culture の部分は消えてしまうようです。

    1. https://localhost/en/TestArea/Home/Index」にアクセス
    2. <a asp-area="" asp-controller="Home" asp-action="Index">"" - Home - Index</a>」が生成されるリンクが「/」となる。
      また「
      <a asp-area="" asp-controller="Home" asp-action="Privacy">"" - Home - Privacy</a>」が生成されるリンクは「/jp/Home/Privacy」となる。

    いろいろ調査していただきありがとうございます。

    2019年11月13日 9:22
  • おのでらさん、こんにちは。フォーラムオペレーターのクモです。
    ご返信いただきありがとうございます。

    次のような異なるシナリオに異なるルートテンプレートを指定してみようとすることができると思います。

     app.UseEndpoints(endpoints =>
                {
    
                    endpoints.MapControllerRoute(
                      name: "culture",
                      pattern: "{culture}/{area:exists}/{controller=Home}/{action=Index}/{id?}");
                    endpoints.MapControllerRoute(
                      name: "defaultculture",
                      pattern: "{culture}/{area=''}/{controller=Home}/{action=Index}/{id?}");
                    endpoints.MapControllerRoute(
                      name: "defaultarea",
                      pattern: "{area:exists}/{controller=Home}/{action=Index}/{id?}");
                    endpoints.MapControllerRoute(
                      name: "default",
                      pattern: "{culture}/{controller=Home}/{action=Index}/{id?}");
    
                    endpoints.MapControllerRoute(
                      name: "default",
                      pattern: "{controller=Home}/{action=Index}/{id?}");
    
                });
    

    エリアとエリアなしの間でリンクを作成する場合は、「asp-area」や、

     @Html.ActionLink("ActionLink - Home - Index", "Index", "Home",new { area = "" }) 
    や、または、
    @Html.ActionLink("ActionLink - Home - Index", "Index", "Home", new { area = "TestArea" })

    の値を明確的に設定する必要があります。

    どうぞよろしくお願いいたします。 


    2019年11月14日 7:05
  • kumo-msft さん、回答ありがとうございます。

    いただいたルーティングをそのまま使ったり加工したりいろいろ試してみたのですが、

    1. 「Area あり」の画面から「Area なし」へリンクを張ると URL から culture 部分(ja とか en)が消えてしまう。
    2. リンクに「https://localhost/ja/%27%27/Home/Privacy」が生成されてしまう

    などあり、お互いの画面を正しく遷移することはできませんでした。

    ちなみに今試している環境では「Area なし (初期設定)」「TestArea」「TestArea2」を作成し、それぞれに「Index.cshtml」「Privacy.cshtml」のビューを用意、6つの画面に以下のリンクを置いて試しています。(少し余分なコードが入っているかもしれません。)

    <ul>
    	<li><a asp-area="TestArea">TestArea</a></li>
    	<li><a asp-area="TestArea" asp-controller="Home">TestArea - Home</a></li>
    	<li><a asp-area="TestArea" asp-controller="Home" asp-action="Index">TestArea - Home - Index</a></li>
    	<li><a asp-area="TestArea" asp-controller="Home" asp-action="Privacy">TestArea - Home - Privacy</a></li>
    	<li><a asp-area="" asp-controller="Home" asp-action="Index">"" - Home - Index</a></li>
    	<li><a asp-area="" asp-controller="Home" asp-action="Privacy">"" - Home - Privacy</a></li>
    	<li><a asp-controller="Home" asp-action="Index">Home - Index</a></li>
    	<li><a asp-controller="Home" asp-action="Privacy">Home - Privacy</a></li>
    	<li>-------------------</li>
    	<li>@Html.ActionLink("ActionLink - TestArea - Home - Index", "Index", "Home", new { area = "TestArea" })</li>
    	<li>@Html.ActionLink("ActionLink - TestArea - Home - Privacy", "Privacy", "Home", new { area = "TestArea" })</li>
    	<li>@Html.ActionLink("ActionLink - \"\" - Home - Index", "Index", "Home", new { area = "" })</li>
    	<li>@Html.ActionLink("ActionLink - \"\" - Home - Privacy", "Privacy", "Home", new { area = "" })</li>
    	<li>@Html.ActionLink("ActionLink - Home - Index", "Index", "Home")</li>
    	<li>@Html.ActionLink("ActionLink - Home - Privacy", "Privacy", "Home")</li>
    	<li>-------------------</li>
    	<li><a asp-area="TestArea" asp-route-culture="en">TestArea - _ - _ - en</a></li>
    	<li><a asp-area="TestArea" asp-controller="Home" asp-route-culture="en">TestArea - Home - _ - en</a></li>
    	<li><a asp-area="TestArea" asp-controller="Home" asp-action="Index" asp-route-culture="en">TestArea - Home - Index - en</a></li>
    	<li><a asp-area="TestArea" asp-controller="Home" asp-action="Privacy" asp-route-culture="en">TestArea - Home - Privacy - en</a></li>
    	<li><a asp-area="" asp-controller="Home" asp-action="Index" asp-route-culture="en">"" - Home - Index - en</a></li>
    	<li><a asp-area="" asp-controller="Home" asp-action="Privacy" asp-route-culture="en">"" - Home - Privacy - en</a></li>
    	<li><a asp-controller="Home" asp-action="Index" asp-route-culture="en">Home - Index - en</a></li>
    	<li><a asp-controller="Home" asp-action="Privacy" asp-route-culture="en">Home - Privacy - en</a></li>
    	<li>-------------------</li>
    	<li><a asp-area="TestArea2">TestArea2</a></li>
    	<li><a asp-area="TestArea2" asp-controller="Home">TestArea2 - Home</a></li>
    	<li><a asp-area="TestArea2" asp-controller="Home" asp-action="Index">TestArea2 - Home - Index</a></li>
    	<li><a asp-area="TestArea2" asp-controller="Home" asp-action="Privacy">TestArea2 - Home - Privacy</a></li>
    	<li>@Url.Action("Privacy", "Home")</li>
    	<li>@Url.RouteUrl("TestArea")</li>
    </ul>
    

    asp-route-culture="yyyy" を置いたリンクが今のところ正しく動作しているようなので、ほかに対応策がなさそうであればこちらの方法も試したいと思います。(動的設定と各リンクに追加が必要なのでまだ試せてませんがたぶん行けるのではないかと思ってます)

    2019年11月14日 10:33
  • おのでらさん、こんにちは。フォーラムオペレーターのクモです。
    ご返信いただきありがとうございます。

    Asp.Net Core Endpoints ルーティングは、異なるロジックで、リクエストをアクションにルーティングし、URL を生成するNet Core3.0 の新機能です。

    「asp-route-culture = "yyyy" 」を試してプロジェクトに取り組むことをお勧めします。

    どうぞよろしくお願いいたします。 

    MSDN/ TechNet Community Support Kumo ~参考になった投稿には「回答としてマーク」をご設定ください。なかった場合は「回答としてマークされていない」も設定できます。同じ問題で後から参照した方が、情報を見つけやすくなりますので、 ご協力くださいますようお願いいたします。また、MSDNサポートに賛辞や苦情がある場合は、MSDNFSF@microsoft.comまでお気軽にお問い合わせください。~

    2019年11月15日 2:31
  • kumo-msft さん、回答ありがとうございます。

    今は UseMvc で代用していますが、Asp.Net Core Endpoints ルーティングが今後の主流になるようであれば asp-route-culture を付加したパターンで進めてみたいと思います。

    ありがとうございました。

    2019年11月15日 4:57