ASP.NET5の準備、問題番号4-ルーティングの詳細

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プロジェクトに接続してみましょう。



  1. 空のASP.NET 5プロジェクトを作成し(空のテンプレートを選択)、「AspNet5Routing」という名前を付けます。
  2. 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" },
          
          





  3. Startup.csファイルで、Microsoft.AspNet.Routing名前空間の使用を追加します。



     using Microsoft.AspNet.Routing;
          
          





  4. Startup.csファイルのConfigureServices()メソッドに必要なサービス(ルーティングシステムがその作業で使用するサービス)を追加します。



     public void ConfigureServices(IServiceCollection services) { services.AddRouting(); }
          
          





  5. 最後に、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, //     "default" template, //     "{controller}/{action}/{id}" ObjectToDictionary(defaults), ObjectToDictionary(constraints), ObjectToDictionary(dataTokens), inlineConstraintResolver));
      
      





興味深いことに、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プロジェクトを作成します。



  1. 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" },
          
          





  2. Startup.csファイルで、 Microsoft.AspNet.Builder名前空間の使用を追加します。



     using Microsoft.AspNet.Builder;
          
          





MVCを接続するために必要な拡張メソッドが含まれています。



  1. MVCフレームワークがその作業で使用するサービスを追加します。Startup.csファイルのConfigureServices()メソッドで:



     public void ConfigureServices(IServiceCollection services) { services.AddMvc(); }
          
          





  2. 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); // Adding the attribute route comes after running the user-code because // we want to respect any changes to the DefaultHandler. routes.Routes.Insert(0, AttributeRouting.CreateAttributeMegaRoute( routes.DefaultHandler, app.ApplicationServices)); return app.UseRouter(routes.Build()); }
      
      





ハンドラーのルートを登録するときに前のセクションと同じことを行い、 MvcRouteHandlerのインスタンスを最終ハンドラーとしてセットアップし、 CreateAttributeMegaRouteメソッドを呼び出します。これは、コントローラーおよびアクションメソッドの属性を使用して設定されたルートを追加する役割を果たします(属性ベースのルーティング)



したがって、3つのメソッドはすべて属性ベースのアプリケーションでルーティングを含みますが、さらに、2番目のメソッドを呼び出すとデフォルトルートが追加され、3番目のメソッドではそれらを委任することで必要なルートを設定できます(慣習ベースのルーティング)。



コンベンションベースのルーティング



上で書いたように、それはMapRoute()メソッドを呼び出すことで設定されます-そして、このメソッドを使用するプロセスはMVC 5以降変更されていません-ルート名、そのテンプレート、デフォルト値、制限をMapRoute()メソッドに転送できます。



 routeBuilder.MapRoute("regexStringRoute", //name "api/rconstraint/{controller}", //template new { foo = "Bar" }, //defaults new { controller = new RegexRouteConstraint("^(my.*)$") }); //constraints
      
      





属性ベースのルーティング



属性ベースのルーティングを特に有効にする必要があった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; //  url    routeOptions.AppendTrailingSlash = true; //     url }); }
      
      





「舞台裏」で、彼は単に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の場合と同じままです。





しかし、ASP.NET 5では、ルートパターンにいくつかの追加機能が追加されました。



  1. ルートの変数部分のデフォルト値を直接設定する機能: {controller = Home} / {action = Index}
  2. シンボルでセグメントの可変部分のオプションを指定しますか?: {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プログラマー

masterL



4年の経験を持つ.NETプログラマー。 彼は企業のWebシステムの開発に従事しています。 専門分野:ASP.NET MVC。

ブログ: boyarincev.net



All Articles