凡科网做网站,网站编辑知识,网站访问速度优化工具,免费购物网站ASP.NET Core 从2.2版本开始#xff0c;采用了一个新的名为Endpoint的路由方案#xff0c;与原来的方案在使用上差别不大#xff0c;但从内部运行方式上来说#xff0c;差别还是很大的。上一篇ASP.NET Core;图解路由(2.1 earler)详细介绍了原版路由方案的运行机制#xff… ASP.NET Core 从2.2版本开始采用了一个新的名为Endpoint的路由方案与原来的方案在使用上差别不大但从内部运行方式上来说差别还是很大的。上一篇ASP.NET Core;图解路由(2.1 earler)详细介绍了原版路由方案的运行机制本文仍然通过一幅图来了解一下新版的运行机制最后再总结一下二者的异同点。一、概述 此方案从2.2版本开始被称作终结点路由下文以“新版”称呼它是默认开启的若想采用原来的方案2.1,下文以原版称呼可以在AddMvc的时候进行设置services.AddMvc(optionoption.EnableEndpointRouting false).SetCompatibilityVersion(CompatibilityVersion.Version_2_2);EnableEndpointRouting 默认为true也就是启用新的Endpoint方案设置为false则采用旧版2.1的路由方案。 在配置方法上来说系统仍然采用在Startup中的use.Mvc()中配置而实际上内部的处理中间件已由原来的RouterMiddleware改为EndpointMiddleware和EndpointRoutingMiddleware两个中间件处理下面依旧通过一幅图来详细看一下 二、流程及解析 图一为了方便查看依然对几个“重点对象”做了颜色标识点击图片可以看大图 1. 路由的初始化配置图的前两个泳道 ① 一切依然是从Startup开始而且和旧版一样是通过UseMvc方法进行配置传入routes.MapRoute(...)这样的一个或多个配置, 不做赘述。下面着重说一下后面的流程看一下MvcApplicationBuilderExtensions中的UseMvc方法② 第6行这里会获取并判断设置的EnableEndpointRouting的值若为false则采用旧版路由详见上一篇文章该值默认为true即采用新版路由。 ③ 对应第9行MvcEndpointDataSource在新版路由中是个非常非常重要的角色在启动初始化阶段它完成了路由表存储和转换此处先用颜色重点标记一下大家记住它在后面的流程中详细介绍。 ④ 对应第16行同旧版的RouteBuilder一样这里会new一个 endpointRouteBuilder二者都是一个IRouteBuilder所以也同样调用configureRoutes(endpointRouteBuilder)方法也就是startup中的配置获取了一个Route的集合IListIRouter赋值给endpointRouteBuilder.Routes这里有个特别该注意的地方if (router is Route route router.GetType() typeof(Route)) 也就是这里只接受route类型终结点路由系统不支持基于 IRouter的可扩展性包括从 Route继承。⑤ 对应第20行这里对刚获取到的endpointRouteBuilder.Routes进行遍历转换成了一个MvcEndpointInfo的集和赋值给mvcEndpointDataSource.ConventionalEndpointInfos。⑥ 之后就是向管道塞中间件了这里的处理中间件由原来的RouterMiddleware改为EndpointMiddleware和EndpointRoutingMiddleware。 2.请求的处理图的后两个泳道 请求的处理大部分功能在中间件EndpointRoutingMiddleware他有个重要的属性_endpointDataSource保存了上文中初始化阶段生成的MvcEndpointDataSource而中间件EndpointMiddleware的功能比较简单主要是在EndpointRoutingMiddleware筛选出endpoint之后调用该endpoint的endpoint.RequestDelegate(httpContext)进行请求处理。 ⑦ InitializeAsync()方法主要是用于调用InitializeCoreAsync()创建一个matcher而通过这个方法的代码可以看出它只是在第一次请求的时候执行一次。 ⑧ MvcEndpointDataSource一个重要的方法UpdateEndpoints()作用是读取所有action并将这个action列表与它的ConventionalEndpointInfos列表见⑤进行匹配最终生成一个新的列表。如下图我们默认情况下只配置了一个{controllerHome}/{actionIndex}/{id?}这样的路由默认的HomeController有三个action添加了一个名为FlyLoloController的controller并添加了一个带属性路由的action最终生成了7个Endpoint这有点像路由与action的“乘积”。当然这里只是用默认程序举了个简单的例子实际项目中可能会有更多的路由模板注册、会有更多的Controller和Action以及属性路由等。 图二具体代码如下本质就是计算出一个个可能被请求的请求终结点也就是Endpoint。由此可见如上一篇文章那样想自定义一个handler来处理特殊模板的方式如 routes.MapRoute(flylolo/{code}/{name}, MyRouteHandler.Handler);将被忽略掉因其无法生成 Endpoint且此种方式完全可以自定义一个中间件来实现没必要混在路由中。 ⑨ 就是用上面生成的Matcher携带Endpoint列表与请求URL做匹配并将匹配到的Endpoint赋值给feature.Endpoint。 ⑩ 获取feature.Endpoint若存在则调用其RequestDelegate处理请求httpContext。 三、新版与旧版的异同点总结简要从应用系统启动和请求处理两个阶段对比说一下两个版本的区别1.启动阶段这个阶段大部分都差不多都是通过Startup的app.UseMvc()方法配置一个路由表一个Route的集合RoutesIListIRouter然后将其简单转换一下2.1: 将Routes转换为RouteCollection2.2 : 将Routes转换为ListMvcEndpointInfo二者区别不大虽然名字不同但本质上还是差不多都仍可理解为Route的集合的包装。2.请求处理阶段2.1: 1. 将请求的URL与RouteCollection中记录的路由模板进行匹配。 2. 找到匹配的Route之后再根据这个请求的URL判断是否存在对应的Controlled和Action。 3. 若以上均通过则调用Route的Handler对HttpContext进行处理。2.2 : 1. 第一次处理请求时首先根据启动阶段所配置的路由集合ListMvcEndpointInfo和_actions.ActionDescriptors.Items所有的action的信息做匹配生成一个列表这个列表存储了所有可能被匹配的URL模板如图二这个列表同样是ListMvcEndpointInfo记录了所有可能的URL模式实际上是列出了一个个可以被访问的详细地址已经算是最终地址了即终结点或许就是为什么叫Endpoint路由的原因。 2.请求的Url和这个生成的表做匹配找到对应的MvcEndpointInfo。 3. 调用被匹配的MvcEndpointInfo的RequestDelegate方法对请求进行处理。二者区别就是对于_actions.ActionDescriptors.Items所有的action的信息的匹配上原版是先根据路由模板匹配后再根据ActionDescriptors判断是否存在对应的Controller和action而新版是先利用了action信息与路由模板匹配然后再用请求的URL进行匹配由于这样的工作只在第一次请求的时候执行所以虽然没有做执行效率上的测试但感觉应该是比之前快的。 原文链接https://www.cnblogs.com/FlyLolo/p/ASPNETCore2_16.html.NET社区新闻深度好文欢迎访问公众号文章汇总 http://www.csharpkit.com