オリジナル:動的ASP.NET 3.0コアでコントローラーをルーティング
:著者フィリップWの
翻訳:https://www.cnblogs.com/lwqlun/p/11461657.html
翻訳:Lamond呂
翻訳者注
インターネット今日は誰もが変換する例は、本明細書に必ずしも日常のコーディングでは発生しませんが、非常に興味深い感じ、ASP.NETコアダイナミックルーティングでこの記事を参照して、だけでなく、いくつかのアイデアを提供してくれます。
序文
ASP.NET MVCとASP.NET MVCのコアルーティングがでています、以前のバージョンに比べては、ASP.NETコア3.0で素敵な拡張点を追加した後、ルートを取得することですプログラムは、それが動的に与えられたを指すことができますコントローラ/アクション。
この機能は、使用シナリオをたくさん持っています。あなたが7から後でASP.NETコア3.0のプレビューを使用している場合は、ASP.NETで、コア3.0でそれを使用することができます。
PS:公式のリリースノートでこれを言及しませんでした。
のは、ASP.NETコア3.0で動的ルーティングを見てみましょう。
背景
我々はMVCルートを使用する場合、最も一般的な使用方法は、我々は、ルーティング情報を定義するルーティング機能(ルート属性)を使用します。この方法を使用して、我々は、明示的に各ルートに宣言する必要があります。
public class HomeController : Controller
{
[Route("")]
[Route("Home")]
[Route("Home/Index")]
public IActionResult Index()
{
return View();
}
}
これとは対照的に、あなたがこのアプローチを使用して、ルートモデルの中心を使用することができ、明示的ルートのそれぞれを宣言する必要はありません - これらは自動的に検出されたすべてのコントローラを識別し、自動的にルーティングされます。しかし、この前提を行うには、すべてのコントローラが存在しなければならないということです。
以下は、新しい構文エンドポイントのルーティングの実装を使用してASP.NETコア3.0です。
app.UseEndpoints(
endpoints =>
{
endpoints.MapControllerRoute("default",
"{controller=Home}/{action=Index}/{id?}");
}
);
一般的に2つのメソッドの上にアプリケーションの起動時にすべてのルーティング情報がロードされなければならないということです。
しかし、あなたがする方法を、動的ルーティングを定義し、アプリケーションが実行されているときにそれらを追加/削除できるようにしたい場合は?
今、私はあなたがいくつかの使用シナリオに名前を付けるために、ダイナミックルーティングを定義与えます。
- 多言語経路、ならびに新しい言語、それらの新しいルートの改変言語を使用する場合。
- システムのCMSタイプでは、我々はいくつかの新しい動的なページを追加するかもしれないが、これらのコントローラは、ソースコードにハードコードされた新しいページまたはルーティング情報を作成する必要はありません。
- マルチテナントアプリケーション、テナント動的ルーティングは、実行時にアクティブまたは非アクティブにすることができます。
この問題の処理は、合理的によく理解されなければなりません。我々は、その現在のルーティング解像度の値を確認し、ルーティングプロセスを傍受するために、できるだけ早く願って、データベース内のデータを使用して、例えば、それらはルート値の新しいセットに「変換」になり、これらの新しいルートの値は、実際の制御の存在を指し示しますデバイス。
質問の例 - 複数の言語の翻訳ルーティングの問題
ASP.NET MVCコアの古いバージョンでは、我々は通常カスタムを経由してIRouter
この問題を解決するためのインタフェース。しかし、ASP.NETコア3.0でそれがルートは、上記の処理されたエンドポイント・ルーティングにより変更されていることから、このように動作していません。ありがたいことに、3.0プレビュー7およびASP.NETコアのそれ以降のバージョンでは、我々は新しい機能渡すことができますMapDynamicControllRoute
し、拡張ポイントDynamicRouteValueTransformer
我々のニーズをサポートするために。のは、具体的な例を見てみましょう。
プロジェクトに想像し、そこにあるOrderController
、あなたはそれが多言語翻訳・ルーティングをサポートする、コントローラ。
public class OrdersController : Controller
{
public IActionResult List()
{
return View();
}
}
私たちは、URLは大文字で要求する場合があり、例えば、
- 英語- / EN /受注/一覧
- ドイツ語- /デ/ bestellungen / LISTE
- ポーランド- / PL / zamowienia /リスタ
ダイナミックルーティングを使用すると、多言語翻訳のルーティングの問題を扱います
だから今、どのように我々はこの問題を解決するのですか?私たちは、新しい機能を使用することができますMapDynamicControllerRoute
デフォルトのMVCのルートを置き換えるために、そして私たちのカスタムを指すようにDynamicRouteValueTransformer
、我々は前に述べたルーティング変換値を実装するクラス。
public class Startup
{
public void ConfigureServices(IServiceCollection services)
{
services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Latest);
services.AddSingleton<TranslationTransformer>();
services.AddSingleton<TranslationDatabase>();
}
public void Configure(IApplicationBuilder app)
{
app.UseRouting();
app.UseEndpoints(endpoints =>
{
endpoints.MapDynamicControllerRoute<TranslationTransformer>("{language}/{controller}/{action}");
});
}
}
ここでは、定義TranslationTransformer
継承するクラスDynamicRouteValueTransformer
クラスを。この新しいクラスは、私たちは、コントローラ/アクションルート値ディクショナリと一致するようにアプリケーションを変換することができ、特定の言語のルート値を担当するが、これらの値は、通常、任意のコントローラおよび/アクションの試合で私たちの直接のアプリケーションではありません。そこでここでは簡単に言えば、ドイツのシーンの下で、コントローラ名はアクション名「LISTE」が「リスト」に変換され、「受注」に「Bestellungen」から変換されますされています。
TranslationTransformer
クラスを渡すジェネリック型パラメータとして使用されるMapDynamicControllerRoute
方法を、それが血管のレジスタ依存性に注入しなければなりません。ここで、我々はまたのためにサインアップする必要がありTranslationDatabase
、我々はそれを後で必要になり、クラスが、クラスでは唯一の実証を支援します。
public class TranslationTransformer : DynamicRouteValueTransformer
{
private readonly TranslationDatabase _translationDatabase;
public TranslationTransformer(TranslationDatabase translationDatabase)
{
_translationDatabase = translationDatabase;
}
public override async ValueTask<RouteValueDictionary> TransformAsync(HttpContext httpContext
, RouteValueDictionary values)
{
if (!values.ContainsKey("language")
|| !values.ContainsKey("controller")
|| !values.ContainsKey("action")) return values;
var language = (string)values["language"];
var controller = await _translationDatabase.Resolve(language,
(string)values["controller"]);
if (controller == null) return values;
values["controller"] = controller;
var action = await _translationDatabase.Resolve(language,
(string)values["action"]);
if (action == null) return values;
values["action"] = action;
return values;
}
}
このコンバータでは、我々は3つのルーティングパラメータを抽出しようとする必要がある、language
、controller
、action
その後、我々は、データベースクラスのシミュレーションを使用して対応する翻訳を見つける必要があります。我々は前に述べたように、あなたは通常、この方法は、我々は、アプリケーションのライフサイクルの任意の時点でできるダイナミックエフェクト・ルーティングので、データベースから対応するコンテンツを見つけることを期待します。この点を説明するために、我々は、使用されますTranslationDatabase
、あなたが実際のデータベース・ウェアハウスサービスと考えることができ、データベースの操作をシミュレートするクラスを。
public class TranslationDatabase
{
private static Dictionary<string, Dictionary<string, string>> Translations
= new Dictionary<string, Dictionary<string, string>>
{
{
"en", new Dictionary<string, string>
{
{ "orders", "orders" },
{ "list", "list" }
}
},
{
"de", new Dictionary<string, string>
{
{ "bestellungen", "orders" },
{ "liste", "list" }
}
},
{
"pl", new Dictionary<string, string>
{
{ "zamowienia", "order" },
{ "lista", "list" }
}
},
};
public async Task<string> Resolve(string lang, string value)
{
var normalizedLang = lang.ToLowerInvariant();
var normalizedValue = value.ToLowerInvariant();
if (Translations.ContainsKey(normalizedLang)
&& Translations[normalizedLang]
.ContainsKey(normalizedValue))
{
return Translations[normalizedLang][normalizedValue];
}
return null;
}
}
これまでのところ、我々はこの問題に良い解決策を持っています。MVCアプリケーションで、ここでこの設定を有効にすることにより、我々は、要求を送信するために3つのルートを定義して確保することができます。
- 英語- / EN /受注/一覧
- ドイツ語- /デ/ bestellungen / LISTE
- ポーランド- / PL / zamowienia /リスタ
各要求はヒットするOrderController
コントローラおよびList
方法を。現在のあなたは、さらに他のコントローラに拡張、このメソッドを使用することができます。新しい言語を既存の言語コントローラ/アクションにマップされた新しいルートやエイリアスを追加する場合でも、最も重要なことは、ある、あなたは、任意のコードを変更する、あるいはプロジェクトを再起動する必要はありません。
単にASP.NETコア3.0の動的ルーティング機能を発揮するために、ここで、この記事では、我々は唯一のルートの翻訳を集中することに注意してください。アプリケーションでのローカライズを実現したいと考えていた場合、あなたはまた、ASP.NETコア3.0読みたいと思うかもしれローカリゼーションガイドを使用すると、値の言語に基づいて正しいルーティングを設定する必要があるかもしれませんので、CurrentCulture
。
最後に、私は私達の前の例では、それを追加したい、我々は明示的にルーティングテンプレートで使用{controller}
し、{action}
プレースホルダ。これは、他のシーンでは、あなたが使用することもでき、必要ではない"catch-all"
ワイルドカードをルーティング、およびコントローラ/アクションのルート値に変換します。
"catch-all"
ワイルドカードをルーティングCMSシステムは、一般的なソリューションでは、さまざまなダイナミックな「ページ」のルートを処理するためにそれを使用することができます。
それは次のようになります。
endpoints.MapDynamicControllerRoute<PageTransformer>("pages/{**slug}");
次に、あなたが必要になりますpages
既存の実行可能なコンテンツのコントローラに変換した後、全体のURLパラメータを-通常URL /ルートマップがデータベースに格納されています。
私はあなたがこの記事が役立つことを願っています-すべてのデモのソースコードを入手できGithubのが上の発見しました。