Www.example.org/ukやwww.example.org/deなどのURLが機能するASP.NETCore 2.1 Webサイトを構築して、表示するresx
ファイルとコンテンツを決定します。 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を使用するためのコードはどのようになるでしょうか?
// Use the routing logic of ASP.NET Core 2.1 or earlier:
services.AddMvc(options => options.EnableEndpointRouting = false)
.SetCompatibilityVersion(CompatibilityVersion.Version_2_2);
以前のバージョンのルーティングとの違い ここで何が起こっているかを説明します(私の強調):
リンク生成環境値無効化アルゴリズムは、エンドポイントルーティングで使用した場合の動作が異なります。
アンビエント値の無効化は、現在実行中のリクエストからのルート値(アンビエント値)をリンク生成操作で使用できるかどうかを決定するアルゴリズムです。従来のルーティングでは、別のアクションにリンクするときに、常に余分なルート値が無効になりました。 ASP.NET Core 2.2のリリース以前は、属性ルーティングにはこの動作はありませんでした。以前のバージョンのASP.NETCoreでは、同じルートパラメーター名を使用する別のアクションへのリンクにより、リンク生成エラーが発生していました。 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>
たとえば、これを少し繰り返しを少なくすることができます。アクションフィルターですが、概念は同じです。これを処理する別の方法があることはわかりませんが(たとえば、特定の値をアンビエントとしてマークできる)、おそらく他の誰かがそれにチャイムをかけることができます。
ルートデータから値を明示的に渡す必要があります。
@using Microsoft.AspNetCore.Routing;
<a ... asp-route-storeId="@this.Context.GetRouteValue("storeId")">Pay Button</a>