ASP.NET5コラムの続きとして、ItWebNetのエンタープライズWebシステムの開発者であるStanislav Boyarintsev( masterL )の出版物を紹介します。 この記事では、StanislavがASP.NET5のルーティングメカニズムについて非常に詳細かつ興味深い話をしています。 このコラムの以前の記事は、 #aspnetcolumn -Vladimir Yunevでいつでも読むことができます。
ASP.NET 5へのルーティングシステムの構成方法
ASP.NET 5へのルーティングは、ASP.NETモジュール
UrlRoutingModuleを使用して行われ
ました 。 モジュールは、
RouteTableクラスの静的Routesプロパティに格納されたルート(通常は
Routeクラスのオブジェクト)の
コレクションを通過し、現在の要求に一致するルートを選択し、RouteクラスのRouteHandlerプロパティに格納されたルートハンドラーを呼び出しました。登録された各ルートには独自のハンドラーがあります。 MVCアプリケーションでは、このハンドラーは
MvcRouteHandlerであり、リクエストのさらなる処理を引き継ぎました。
アプリケーション構成プロセスでRouteTable.Routesコレクションにルートを追加しました。
MVCアプリケーションの典型的なルーティングシステム構成コード:
RouteTable.Routes.MapRoute( name: "Default", url: "{controller}/{action}/{id}", defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional } );
ここで、
MapRouteはSystem.Web.Mvc名前空間で宣言された拡張メソッドで、MvcRouteHandlerをハンドラーとして使用して、Routesプロパティのルートコレクションに新しいルートを追加しました。
これは自分で行うことができます:
RouteTable.Routes.Add(new Route( url: "{controller}/{action}/{id}", defaults: new RouteValueDictionary(new { controller = "Home", action = "Index", id = UrlParameter.Optional }), routeHandler: new MvcRouteHandler()) );
ASP.NET 5でのルーティングシステムの構成方法:ショートバージョン
ASP.NET 5はモジュールを使用しなくなりました。リクエストの処理には、
OWINへの移行の一環として導入された「ミドルウェア」
-IISサーバー上だけでなくASP.NET 5アプリケーションの実行を可能にする「Open Web Interface」が使用されます。
したがって、
RouterMiddlewareを使用してルーティングが行われます。 ルーティングプロジェクト全体
はgithubからダウンロードできます 。 この概念の一部として、要求は、アプリケーションの起動時に登録された順に、あるミドルウェアから別のミドルウェアに転送されます。 要求がRouterMiddlewareに到達すると、要求されたURLアドレスが登録されたルートに適しているかどうかを比較し、適切であれば、このルートのハンドラーを呼び出します。
ASP.NET 5でのルーティングシステムの構成方法:ロングバージョン
ルーティングシステムの仕組みを理解するために、空のASP.NET 5プロジェクトに接続してみましょう。
- 空のASP.NET 5プロジェクトを作成し(空のテンプレートを選択)、「AspNet5Routing」という名前を付けます。
- project.jsonファイル「Microsoft.AspNet.Routing」にプロジェクトの「依存関係」を追加します。
"dependencies": { "Microsoft.AspNet.Server.IIS": "1.0.0-beta5", "Microsoft.AspNet.Server.WebListener": "1.0.0-beta5", "Microsoft.AspNet.Routing": "1.0.0-beta5" },
- Startup.csファイルで、Microsoft.AspNet.Routing名前空間の使用を追加します。
using Microsoft.AspNet.Routing;
- Startup.csファイルのConfigureServices()メソッドに必要なサービス(ルーティングシステムがその作業で使用するサービス)を追加します。
public void ConfigureServices(IServiceCollection services) { services.AddRouting(); }
- 最後に、Startup.csファイルのConfigure()メソッドでルーティングシステムを構成します。
public void Configure(IApplicationBuilder app) { var routeBuilder = new RouteBuilder(); routeBuilder.DefaultHandler = new ASPNET5RoutingHandler(); routeBuilder.ServiceProvider = app.ApplicationServices; routeBuilder.MapRoute("default", "{controller}/{action}/{id}"); app.UseRouter(routeBuilder.Build()); }
ルーティングプロジェクトの例から引用。
最後のステップをより詳細に分析します。
var routeBuilder = new RouteBuilder(); routeBuilder.DefaultHandler = new ASPNET5RoutingHandler(); routeBuilder.ServiceProvider = app.ApplicationServices;
RouteBuilderのインスタンスを作成し、そのプロパティを入力します。 興味深いのは、タイプ
IRouterの DefaultHandlerプロパティです。名前から判断すると、リクエストハンドラが含まれている必要があります。 ASPNET5RoutingHandlerのインスタンスを配置します-私が発明したリクエストハンドラです。作成しましょう:
using Microsoft.AspNet.Routing; using System; using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; using Microsoft.AspNet.Http; namespace AspNet5Routing { public class ASPNET5RoutingHandler : IRouter { public VirtualPathData GetVirtualPath(VirtualPathContext context) { } public async Task RouteAsync(RouteContext context) { await context.HttpContext.Response.WriteAsync("ASPNET5RoutingHandler work"); context.IsHandled = true; } } }
IRouterインターフェイスでは、GetVirtualPathとRouteAsyncの2つのメソッドのみが必要です。
GetVirtualPathメソッド-ASP.NETの以前のバージョンからよく知られています;これは、ルートを表す
Routeクラスが継承される
RouteBaseクラスのインターフェイスにありました。 このメソッドは、Urlの構築を担当しました(たとえば、ActionLinkメソッドを呼び出した場合:
Html .ActionLink(「リンク」、「インデックス」))。
RouteAsyncメソッドでは、リクエストを処理し、処理の結果をResponseに書き込みます。
Configureメソッドの次の行:
routeBuilder.MapRoute("default", "{controller}/{action}/{id}");
2滴の水と同様に、MVC 5でMapRouteメソッドを使用するのと似ています。そのパラメーターは、追加されたルートの名前と、要求されたUrlがマップされるテンプレートです。
MapRoute()自体は、MVC 5と同様に
拡張メソッドであり、その呼び出しは最終的には
TemplateRouteクラスのインスタンスを作成し、RouteBuilderオブジェクトのRoutesコレクションに追加することになります。
routeBuilder.Routes.Add(new TemplateRoute(routeCollectionBuilder.DefaultHandler, name,
興味深いことに、RoutesプロパティはIRouterコレクションです。つまり、TemplateRouteは、作成したASPNET5RoutingHandlerのようなIRouterインターフェイスも実装しますが、これはTemplateRouteコンストラクターに渡されます。
そして最後に、最後の行:
app.UseRouter(routeBuilder.Build());
routeBuilder.Buildの呼び出し()
-RouteCollectionクラスのインスタンスを作成し、
RouteBuilderクラスのRouteプロパティのすべての要素を追加します。
そしてapp.UseRouter()
は 、要求を処理するために実際に
RouterMiddlewareをパイプラインに接続し、Build()メソッドで作成されて入力されたRouteCollectionオブジェクトに渡す拡張メソッドである
ことが判明しました 。
public static IApplicationBuilder UseRouter([NotNull] this IApplicationBuilder builder, [NotNull] IRouter router) { return builder.UseMiddleware<RouterMiddleware>(router); }
そして、RouterMiddlewareのコンストラクターによる判断:
public RouterMiddleware( RequestDelegate next, ILoggerFactory loggerFactory, IRouter router)
RouteCollectionオブジェクトは、TemplateRouteを使用したASPNET5RoutingHandlerと同様に、IRouterインターフェイスも実装します。
合計で、次の入れ子人形が得られました。
ASPNET5RoutingHandlerリクエストハンドラーは
TemplateRouteにパッケージ化され、
TemplateRoute自体または
TemplateRouteのいくつかのインスタンス(MapRoute()メソッドを複数回呼び出した場合)は
RouteCollectionにパッケージ化され、
RouteCollectionは RouterMiddlewareコンストラクターに渡されて保存されます。
これでルーティングシステムの設定プロセスが完了し、プロジェクトを開始し、アドレス「/ Home / Index / 1」に移動して、結果を確認できます:「ASPNET5RoutingHandler work」。
さて、着信リクエスト中にルーティングシステムで何が起こるかを簡単に見てみましょう。
キューが
RouterMiddlewareに到達すると、起動されたミドルウェアのリストで、保存されたIRouterインスタンスで
RouteAsync()メソッドを呼び出します-これは
RouteCollectionクラスのオブジェクトです。
次に、RouteCollectionは 、
そこに格納されている
IRouterインスタンスを通過します。この例では、
TemplateRouteであり、
それらのRouteAsync()メソッドを呼び出します。
TemplateRouteは、要求されたUrlがそのテンプレート(TemplateRouteコンストラクターに渡される:「{controller} / {action} / {id}」)に一致するかどうかを確認し、一致する場合、その
中に格納されている
IRouterインスタンスを呼び出します-これは
ASPNET5RoutingHandlerです。
ルーティングシステムをMVCアプリケーションに接続します
ここで、MVCフレームワークがルーティングシステムと通信する方法を見てみましょう。
繰り返しますが、空のテンプレートを使用して空のASP.NET 5プロジェクトを作成します。
- project.jsonファイル「Microsoft.AspNet.Mvc」にプロジェクトの「依存関係」を追加します。
"dependencies": { "Microsoft.AspNet.Server.IIS": "1.0.0-beta5", "Microsoft.AspNet.Server.WebListener": "1.0.0-beta5", "Microsoft.AspNet.Mvc": "6.0.0-beta5" },
- Startup.csファイルで、 Microsoft.AspNet.Builder名前空間の使用を追加します。
using Microsoft.AspNet.Builder;
MVCを接続するために必要な拡張メソッドが含まれています。
- MVCフレームワークがその作業で使用するサービスを追加します。Startup.csファイルのConfigureServices()メソッドで:
public void ConfigureServices(IServiceCollection services) { services.AddMvc(); }
- Startup.csファイルのConfigure()メソッドでMVCアプリケーションを構成します。
3つの異なる方法を使用できます。
1。
public void Configure(IApplicationBuilder app) { app.UseMvc() }
2。
public void Configure(IApplicationBuilder app) { app.UseMvcWithDefaultRoute() }
3。
public void Configure(IApplicationBuilder app) { return app.UseMvc(routes => { routes.MapRoute( name: "default", template: "{controller=Home}/{action=Index}/{id?}"); }); }
これらのメソッドの
実装をすぐに見てみましょう。
最初の方法:
public static IApplicationBuilder UseMvc(this IApplicationBuilder app) { return app.UseMvc(routes => { }); }
3番目のメソッドを呼び出し、デリゲートアクション<IRouteBuilder>を渡しますが、これは何も行いません。
2番目の方法:
public static IApplicationBuilder UseMvcWithDefaultRoute(this IApplicationBuilder app) { return app.UseMvc(routes => { routes.MapRoute( name: "default", template: "{controller=Home}/{action=Index}/{id?}"); }); }
また、3番目のメソッドも呼び出します。アクション<IRouteBuilder>デリゲートでのみデフォルトルートが追加されます。
3番目の方法:
public static IApplicationBuilder UseMvc( this IApplicationBuilder app, Action<IRouteBuilder> configureRoutes) { MvcServicesHelper.ThrowIfMvcNotRegistered(app.ApplicationServices); var routes = new RouteBuilder { DefaultHandler = new MvcRouteHandler(), ServiceProvider = app.ApplicationServices }; configureRoutes(routes);
ハンドラーのルートを登録するときに前のセクションと同じことを行い、
MvcRouteHandlerのインスタンスを最終ハンドラーとして
セットアップし、
CreateAttributeMegaRouteメソッドを呼び出します。これは、コントローラーおよびアクションメソッドの属性を使用して設定されたルートを追加する役割を果たします(属性ベースのルーティング)
したがって、3つのメソッドはすべて属性ベースのアプリケーションでルーティングを含みますが、さらに、2番目のメソッドを呼び出すとデフォルトルートが追加され、3番目のメソッドではそれらを委任することで必要なルートを設定できます(慣習ベースのルーティング)。
コンベンションベースのルーティング
上で書いたように、それは
MapRoute()メソッドを呼び出すことで設定されます-そして、このメソッドを使用するプロセスはMVC 5以降変更されていません-ルート名、そのテンプレート、デフォルト値、制限を
MapRoute()メソッドに転送できます。
routeBuilder.MapRoute("regexStringRoute",
属性ベースのルーティング
属性ベースのルーティングを特に有効にする必要があったMVC 5とは異なり、MVC 6ではデフォルトで有効にされていました。
また、属性を使用して定義されたルートは、一致を検出して適切なルートを選択する際に優先されることを覚えておく必要があります(規則ベースのルートと比較して)。
ルートを指定するには、アクションメソッドとコントローラーの両方に
Route属性を使用する必要があります(MVC 5では、ルートを指定するためにコントローラーに
RoutePrefix属性が使用されました)。
[Route("appointments")] public class Appointments : ApplicationBaseController { [Route("check")] public IActionResult Index() { return new ContentResult { Content = "2 appointments available." }; } }
その結果、このアクションメソッドは「/アポイントメント/チェック」で利用可能になります。
ルーティングシステムのセットアップ
ASP.NET 5は、
Options -
GitHubプロジェクトと呼ばれる新しいサービス構成メカニズムを導入しました。 これにより、ルーティングシステムの設定を行うことができます。
その動作の意味は、
Startup.csファイル
でアプリケーションを構成すると、特定の方法で定義されたプロパティを持つオブジェクトを依存関係登録システムに転送し、アプリケーションの実行中に、このオブジェクトを取得し、公開されたプロパティの値に応じて、アプリケーションがビルドすることです仕事。
RouteOptionsクラスは、ルーティングシステムの構成に使用されます。
便宜上、
ConfigureRouting拡張メソッドを使用できます。
public void ConfigureServices(IServiceCollection services) { services.ConfigureRouting( routeOptions => { routeOptions.LowercaseUrls = true;
「舞台裏」で、彼は単に
Configureメソッドを呼び出して、
アクション<RouteOptions>デリゲートを
渡します。
public static void ConfigureRouting( this IServiceCollection services, Action<RouteOptions> setupAction) { if (setupAction == null) { throw new ArgumentNullException(nameof(setupAction)); } services.Configure(setupAction); }
ルートパターン
ルートパターンの操作の原則は、MVC 5の場合と同じままです。
- アドレスセグメントは、スラッシュで区切られます: firstSegment / secondSegment 。
- 中括弧で囲まれていない場合、セグメントの定数部分が考慮されます。要求されたUrlへのそのようなルートの対応は、アドレスにまったく同じ値が含まれる場合にのみ発生します。firstSegment / secondSegment-
- セグメントの可変部分は中括弧で囲まれます: firstSegment / {secondSegment} -パターンは任意の2つのセグメントアドレスに対応します。最初のセグメントは「firstSegment」で、2番目のセグメントは任意の文字セットです(スラッシュを除く-これは3番目のセグメントの開始を示します) ):
「/ firstSegment / index」
「/ firstSegment / index-2」
- 名前が示すように、セグメントの可変部分の制限は、可変セグメントの許容値を制限し、「:」記号の後に設定されます。 1つの変数部分にいくつかの制限を課すことができます;パラメーターは括弧を使用して渡されます: firstSegment / {secondSegment:minlength(1):maxlength(3)} 。 制限の文字列指定は、RouteOptionsクラスのGetDefaultConstraintMap()メソッドで見つけることができます。
- アドレスの残りの行全体を吸収するように最後のセグメントを「貪欲」にするには、*文字を使用する必要があります: {controller} / {action} / {* allRest} -アドレスに対応します: "/ home / index / 2 "、およびアドレス:" / home / index / 2/4/5 "。
しかし、ASP.NET 5では、ルートパターンにいくつかの追加機能が追加されました。
- ルートの変数部分のデフォルト値を直接設定する機能: {controller = Home} / {action = Index}
- シンボルでセグメントの可変部分のオプションを指定しますか?: {Controller = Home} / {action = Index} / {id?}
また、属性でルートテンプレートを使用すると、次の変更が発生しました。
属性を介したルーティングを構成する場合、コントローラーとアクションメソッドを示すパラメーターは、角括弧で「コントローラー」と「アクション」という単語を使用してアドレス指定する必要があります。「[コントローラー] / [アクション]」 form-デフォルト値も制限もオプション性も欲も許されません。
つまり、許可されています:
Route("[controller]/[action]/{id?}") Route("[controller]/[action]")
これらは個別に使用できます。
Route("[controller]") Route("[action]")
許可されていません:
Route("{controller}/{action}") Route("[controller=Home]/[action]") Route("[controller?]/[action]") Route("[controller]/[*action]")
ルートパターンの一般的なスキームは次のようになります。
constantPart-{variablePart}/{paramName:constraint1:constraint2=DefaultValue?}/{*lastGreedySegment}
おわりに
この記事では、ASP.NET 5ルーティングシステムを調べ、どのように構成されているかを調べ、ルートハンドラーを使用して空のASP.NET 5プロジェクトに接続しました。 MVCアプリケーションに接続し、オプションエンジンを使用して構成する方法を検討しました。 属性ベースのルーティングとルートパターンの使用で発生した変更について説明します。
著者向け
ご友人、ご自身の資料でコラムをサポートすることに興味がある場合は、すべての詳細を議論するために
vyunev@microsoft.comまでご
連絡ください。 ASP.NETおよびその他のトピックについて興味深い話ができる著者を探しています。

著者について
ボヤリンツェフスタニスラフ・アレクサンドロヴィッチキーロフ市のItWebNetの主要な.NETプログラマー
masterL4年の経験を持つ.NETプログラマー。 彼は企業のWebシステムの開発に従事しています。 専門分野:ASP.NET MVC。
ブログ:
boyarincev.net