ASP.NET Coreのルーティング[4]:ルーティングを実現するRouterMiddlewareミドルウェアを認識する

11021 ワード

ASP.NET CoreアプリケーションのルーティングはRouterMiddlewareというミドルウェアによって行われるが,具体的なルーティング解析機能は指定されたRouterオブジェクトに落ちているが,コード実装の観点からこのミドルウェアを紹介する必要がある.その前に、私たちはまず特殊な特性を認識します.[本文は『ASP.NET Coreフレームワークの秘密を明らかにする』に同期した]
RouterMiddlewareミドルウェアがRouterにルーティング全体の完全な作業を依頼すると、解析されたルーティングパラメータはRouteDataオブジェクトとしてRouteContextコンテキストに格納されます.しかし、RouteContextはRouterの実行のために確立されたコンテキストであり、ルーティング作業が完了すると、このコンテキストのライフサイクルも終了し、RouteContextコンテキスト全体が存在しない以上、リクエスト処理の後続ステップはどのようにしてこのRouteDataオブジェクトを取得しますか?
「登録URLモードとHttpHandlerのマッピング関係」の実例実証により、HttpContextの拡張メソッドGetRouteDataを呼び出して、この素のすべてのルーティングパラメータを含むRouteDataオブジェクトを取得できることが分かった.これは、RouteContextコンテキストに依存していたRouteDataが、現在のリクエストコンテキストを表すHttpContextに最終的に付加されることを意味する.このRouteDataを具体的に搭載しているのが、このRoutingFeatureという特性です.RoutingFeatureは、IroutingFeatureインタフェースを実装したすべてのタイプと対応するオブジェクトの総称です.次のコードフラグメントに示すように、このインタフェースは、属性RouteDataによって、最終的にHttpContextに付加されたRouteDataを保存する.RoutingFeatureクラスはこのインタフェースのデフォルトインプリメンテーションであり、私たちのRouterMiddlewareはデフォルトでこのオブジェクトを使用しています.
   1: public interface IRoutingFeature
   2: {
   3:     RouteData RouteData { get; set; }
   4: }
   5:  
   6: public class RoutingFeature : IRoutingFeature
   7: {
   8:     public RouteData RouteData { get; set; }
   9: }

以下に示すコードフラグメントは、RouterMiddlewareが要求を処理する完全な論理を表す.RouterMiddlewareオブジェクトを作成するには、Routerオブジェクトとロガーを作成するロガーファクトリを指定する必要があります.このミドルウェアが要求の処理を開始すると、現在のHttpContextに基づいてRouteContextコンテキストオブジェクトが作成され、パラメータとしてRouterを呼び出すRotueAsyncメソッドがルーティングされます.ルーティング解析が終了した後にRouteContextのHandler属性で返されるリクエスト処理が存在する場合、現在のリクエストは登録されたルーティングと一致することを意味し、この場合、現在のリクエストはこのプロセッサに渡されて後続の処理を行う.その前にRouteContextコンテキストからRouteDataが提案され、それに基づいてRoutingFeatureオブジェクトが作成され、HttpContextに添付されます.
   1: public class RouterMiddleware
   2: {
   3:     private ILogger             _logger;
   4:     private RequestDelegate     _next;
   5:     private IRouter             _router;
   6:  
   7:     public RouterMiddleware(RequestDelegate next, ILoggerFactory loggerFactory, IRouter router)
   8:     {
   9:         _next       = next;
  10:         _logger     = loggerFactory.CreateLogger<RouterMiddleware>();
  11:         _router     = router;
  12:     }
  13:  
  14:     public async Task Invoke(HttpContext context)
  15:     {
  16:         RouteContext routeContext = new RouteContext(context);
  17:         routeContext.RouteData.Routers.Add(_router);
  18:         await _router.RouteAsync(routeContext);
  19:         if (null == routeContext.Handler)
  20:         {
  21:             _logger.LogDebug(1, "Request did not match any routes.");
  22:             await _next(context);
  23:         }
  24:         else
  25:         {
  26:             context.Features.Set<IRoutingFeature>(new RoutingFeature {  RouteData = routeContext.RouteData})
  27:             await routeContext.Handler(context);
  28:         }
  29:     }
  30: }

HttpContextの拡張メソッドGetRouteDataを呼び出してルーティングパラメータをカプセル化したRouteDataオブジェクトを得る前に、GetRouteValue発という別の拡張メソッドを呼び出してルーティングパラメータの値を直接取得することもできます.以下に示すコードフラグメントでは,比較的単純なコードを用いて,この2つの拡張再生の実装を示した.
   1: public static class RoutingHttpContextExtensions
   2: {
   3:     public static RouteData GetRouteData(this HttpContext context)
   4:     {
   5:         return context.Features.Get<IRoutingFeature>()?.RouteData;
   6:     }
   7:  
   8:     public static object GetRouteValue(this HttpContext context, string key)
   9:     {
  10:         return context.GetRouteData()?.Values[key];
  11:     }
  12: }

一般的には、RouterMiddlewareミドルウェアを登録するためにApplicationBuilderの拡張メソッドUseRouterを呼び出す傾向があります.具体的には、次の2つのUseRouterメソッドのリロードを選択できます.最初のリロードを呼び出す場合は、登録されたRouterMiddlewareミドルウェアに特定のRouterオブジェクトを指定する必要があります.2番目のリロードでは、このRouterオブジェクトは実際にRouteBuilderを使用して作成されます.このメソッドを呼び出すときに、このRouteBuilderを利用して必要なルーティングをActionオブジェクトとして登録する必要があります.
   1: public static class RoutingBuilderExtensions
   2: {
   3:     public static IApplicationBuilder UseRouter(this IApplicationBuilder builder, IRouter router)
   4:     {
   5:         return builder.UseMiddleware<RouterMiddleware>(new object[] { router });
   6:     }
   7:  
   8:     public static IApplicationBuilder UseRouter(this IApplicationBuilder builder, Action<IRouteBuilder> action)
   9:     {       
  10:         RouteBuilder routeBuilder = new RouteBuilder(builder);
  11:         action(routeBuilder);
  12:         return builder.UseRouter(routeBuilder.Build());
  13:     }
  14: }

  ASP.NET Coreのルーティング[1]:登録URLモードとHttpHandlerのマッピング関係
ASP.NET Coreのルーティング[2]:ルーティングシステムのコアオブジェクトであるRouter
ASP.NET Coreのルーティング[3]:Routerの作成者であるRouteBuilder
ASP.NET Coreのルーティング[4]:ルーティングを実現するRouterMiddlewareミドルウェアを認識する
ASP.NET Coreのルーティング[5]:インラインルーティング制約の検証