11

www.example.org/ukwww.example.org/deresxなどの URL が表示するファイルとコンテンツを決定する ASP.NET Core 2.1 Web サイトを構築しました。ASP.NET Core 2.2 にアップグレードした後、ページは読み込まれますが、生成されたすべてのリンクで空白/空の href が生成されます。

たとえば、次のリンクです。

<a asp-controller="Home" asp-action="Contact">@Res.ContactUs</a>

2.2 では、次のように空の href が生成されます。

<a href="">Contact us</a>

しかし、2.1 では正しい href を取得します。

<a href="/uk/contact">Contact us</a>

URL ベースの言語機能を管理するために制約マップを使用しています。コードは次のとおりです。

Startup.cs

// configure route options {lang}, e.g. /uk, /de, /es etc
services.Configure<RouteOptions>(options =>
{
    options.LowercaseUrls = true;
    options.AppendTrailingSlash = false;
    options.ConstraintMap.Add("lang", typeof(LanguageRouteConstraint));
 });

 ...

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

LanguageRouteConstraint.cs

public class LanguageRouteConstraint : IRouteConstraint
{
    private readonly AppLanguages _languageSettings;

    public LanguageRouteConstraint(IHostingEnvironment hostingEnvironment)
    {
        var builder = new ConfigurationBuilder()
            .SetBasePath(hostingEnvironment.ContentRootPath)
            .AddJsonFile("appsettings.json", optional: false, reloadOnChange: true);

        IConfigurationRoot configuration = builder.Build();

        _languageSettings = new AppLanguages();
        configuration.GetSection("AppLanguages").Bind(_languageSettings);
    }

    public bool Match(HttpContext httpContext, IRouter route, string routeKey, RouteValueDictionary values, RouteDirection routeDirection)
    {
        if (!values.ContainsKey("lang"))
        {
            return false;
        }

        var lang = values["lang"].ToString();
        foreach (Language lang_in_app in _languageSettings.Dict.Values)
        {
            if (lang == lang_in_app.Icc)
            {
                return true;
            }
        }
        return false;
    }
}

問題を絞り込みましたが、解決する方法が見つかりません。基本的には 2.2 です。IRouteConstraint Match上記の方法では、いくつかのパラメータが設定されていません。

httpContext = null
route = {Microsoft.AspNetCore.Routing.NullRouter)

2.1で

 httpContext = {Microsoft.AspNetCore.Http.DefaultHttpContext}
 route = {{lang:lang}/{controller=Home}/{action=Index}/{id?}}

2.1 と 2.2 の唯一の違いは、

var builder = new ConfigurationBuilder()
   .SetBasePath(Directory.GetCurrentDirectory())
   .AddJsonFile("appsettings.json", optional: false, reloadOnChange: true);

以下に( https://github.com/aspnet/AspNetCore/issues/4206による)

 var builder = new ConfigurationBuilder()
    .SetBasePath(hostingEnvironment.ContentRootPath) // using IHostingEnvironment 
    .AddJsonFile("appsettings.json", optional: false, reloadOnChange: true);

何か案は?

更新https://docs.microsoft.com/en-us/aspnet/core/fundamentals/routing?view=aspnetcore-2.2#parameter-transformer-reference ASP.NET Core 2.2 は EndpointRouting を使用 しますが、2.1 は IRouter 基本ロジックを使用します。それは私の問題を説明しています。さて、私の質問は、2.2 で新しい EndpointRouting を使用するためのコードはどのようになるでしょうか?

4

3 に答える 3

4

ルーティングの以前のバージョンとの違いは、ここで何が起こっているかを説明しています (私の強調):

リンク生成のアンビエント値の無効化アルゴリズムは、エンドポイント ルーティングで使用すると動作が異なります。

アンビエント値の無効化は、現在実行中のリクエストのどのルート値 (アンビエント値) をリンク生成操作で使用できるかを決定するアルゴリズムです。従来のルーティングでは、別のアクションにリンクするときに、余分なルート値が常に無効になりました。ASP.NET Core 2.2 のリリース前は、属性ルーティングにはこの動作がありませんでした。以前のバージョンの ASP.NET Core では、同じルート パラメーター名を使用する別のアクションへのリンクにより、リンク生成エラーが発生しました。ASP.NET Core 2.2 以降では、どちらの形式のルーティングも、別のアクションにリンクするときに値を無効にします。

...

リンク先が別のアクションまたはページである場合、アンビエント値は再利用されません。

あなたの例でlangは、アンビエント値であるため、 (別のアクション)Home/Indexに移動するときに再利用されていません。Home/Aboutに値が指定されてlangいない場合、一致するアクションがないため、空の href が生成されます。これは、ドキュメントでもエンドポイント ルーティングの違いとして説明されています。

ただし、アクションが存在しない場合、エンドポイント ルーティングは空の文字列を生成します。概念的には、アクションが存在しない場合、エンドポイント ルーティングはエンドポイントが存在するとは想定しません。

lang引き続きエンドポイント ルーティングを使用する場合は、コントローラーからビューに値を渡し、明示的に設定する必要があるようです。次に例を示します。

public class HomeController : Controller
{
    public IActionResult Index(string lang)
    {
        ViewData["lang"] = lang; // Using ViewData just for demonstration purposes.
        return View();
    }
}
<a asp-controller="Home" asp-action="Contact"
    asp-route-lang="@ViewData["lang"]">@Res.ContactUs</a>

アクション フィルターなどを使用すると、これを少し繰り返しなくすることができますが、概念は同じです。これを処理する別の方法 (たとえば、特定の値をアンビエントとしてマークできるなど) があるかどうかはわかりませんが、おそらく他の誰かがそれに参加できるでしょう。

于 2018-12-07T12:58:12.053 に答える
1

ルート データから値を明示的に渡す必要があります。

@using Microsoft.AspNetCore.Routing;
<a ... asp-route-storeId="@this.Context.GetRouteValue("storeId")">Pay Button</a>
于 2019-10-21T09:18:49.723 に答える