详解ASP.NET Core MVC 源码学习:Routing 路由

2019-05-25 21:51:50丽君
snapshot.Restore() 重新初始化快照状态。

接下来就要看具体的路由处理对象了,我们从 RouteBase 开始。

1、RouteBase 的构造函数会初始化 RouteTemplate, Name, DataTokens, Defaults.
 Defaults 是默认配置的路由参数。

2、RouteAsync 中会进行一系列检查,如果没有匹配到URL对应的路由就会直接返回。

3、使用路由参数匹配器 RouteConstraintMatcher 进行匹配,如果没有匹配到,同样直接返回。

4、如果匹配成功,会触发 OnRouteMatched(RouteContext context)函数,它是一个抽象函数,具体实现位于 Route.cs 中。

然后,我们再继续跟踪到 Route.cs 中的 OnRouteMatch,一起来看一下:

protected override Task OnRouteMatched(RouteContext context)
{
  
  context.RouteData.Routers.Add(_target);
  return _target.RouteAsync(context);
}

_target 值得当前路由的处理程序,那么具体是哪个路由处理程序呢? 我们一起探索一下。

我们知道,我们创建路由一共有MapRoute,MapGet,MapPost,MapPut,MapDelete,MapVerb... 等等这写方式,我们分别对应说一下每一种它的路由处理程序是怎么样的,下面是一个示例:

app.UseRouter(routes =>{
  routes.DefaultHandler = new RouteHandler((httpContext) =>
  {
    var request = httpContext.Request;
    return httpContext.Response.WriteAsync($"");
  });
          
  routes
  .MapGet("api/get/{id}", (request, response, routeData) => {})
  .MapMiddlewareRoute("api/middleware", (appBuilder) => 
             appBuilder.Use((httpContext, next) => httpContext.Response.WriteAsync("Middleware!")
           ))
  .MapRoute(
     name: "AllVerbs",
     template: "api/all/{name}/{lastName?}",
     defaults: new { lastName = "Doe" },
     constraints: new { lastName = new RegexRouteConstraint(new Regex("[a-zA-Z]{3}",RegexOptions.CultureInvariant, RegexMatchTimeout)) });
});

按照上面的示例解释一下,

MapRoute:使用这种方式的话,必须要给 DefaultHandler 赋值处理程序,否则会抛出异常,通常情况下我们会使用RouteHandler类。

MapVerb: MapPost,MapPut 等等都和它类似,它将处理程序作为一个 RequestDelegate 委托提供了出来,也就是说我们实际上在自己处理HttpContext的东西,不会经过RouteHandler处理。

MapMiddlewareRoute:需要传入一个 IApplicationBuilder 委托,实际上 IApplicationBuilder Build之后也是一个 RequestDelegate,它会在内部 new 一个 RouteHandler 类,然后调用的 MapRoute。

这些所有的矛头都指向了 RouteHandler , 我们来看看 RouteHandler