ASP.NET Core : 十六.扒一扒新的Endpoint路由方案(上)

简介: ASP.NET Core 从2.2版本开始,采用了一个新的名为Endpoint的路由方案,与原来的方案在使用上差别不大,但从内部运行方式上来说,差别还是很大的。上一篇详细介绍了原版路由方案的运行机制,本文仍然通过一幅图来了解一下新版的运行机制,最后再总结一下二者的异同点。
+关注继续查看

一、概述

       此方案从2.2版本开始,被称作终结点路由(下文以“新版”称呼),它是默认开启的,若想采用原来的方案(<=2.1,下文以原版称呼),可以在AddMvc的时候进行设置

services.AddMvc(option=>option.EnableEndpointRouting = false).SetCompatibilityVersion(CompatibilityVersion.Version_2_2);

EnableEndpointRouting 默认为true,也就是启用新的Endpoint方案,设置为false则采用旧版(<=2.1)的路由方案。


       在配置方法上来说,系统仍然采用在Startup中的use.Mvc()中配置,而实际上内部的处理中间件已由原来的RouterMiddleware改为EndpointMiddleware和EndpointRoutingMiddleware两个中间件处理,下面依旧通过一幅图来详细看一下:


二、流程及解析

2.png

     图一


为了方便查看,依然对几个“重点对象”做了颜色标识(点击图片可以看大图):


     1. 路由的初始化配置(图的前两个泳道)


①  一切依然是从Startup开始,而且和旧版一样,是通过UseMvc方法进行配置,传入routes.MapRoute(...)这样的一个或多个配置, 不做赘述。

下面着重说一下后面的流程,看一下MvcApplicationBuilderExtensions中的UseMvc方法:

 1 public static IApplicationBuilder UseMvc(
 2     this IApplicationBuilder app,
 3     Action<IRouteBuilder> configureRoutes)
 4 {
 5 //此处各种验证,略。。
 6     var options = app.ApplicationServices.GetRequiredService<IOptions<MvcOptions>>();
 7     if (options.Value.EnableEndpointRouting)
 8     {
 9         var mvcEndpointDataSource = app.ApplicationServices
10             .GetRequiredService<IEnumerable<EndpointDataSource>>()
11             .OfType<MvcEndpointDataSource>()
12             .First();
13         var parameterPolicyFactory = app.ApplicationServices
14             .GetRequiredService<ParameterPolicyFactory>();
15 
16         var endpointRouteBuilder = new EndpointRouteBuilder(app);
17 
18         configureRoutes(endpointRouteBuilder);
19 
20         foreach (var router in endpointRouteBuilder.Routes)
21         {
22             // Only accept Microsoft.AspNetCore.Routing.Route when converting to endpoint
23             // Sub-types could have additional customization that we can't knowingly convert
24             if (router is Route route && router.GetType() == typeof(Route))
25             {
26                 var endpointInfo = new MvcEndpointInfo(
27                     route.Name,
28                     route.RouteTemplate,
29                     route.Defaults,
30                     route.Constraints.ToDictionary(kvp => kvp.Key, kvp => (object)kvp.Value),
31                     route.DataTokens,
32                     parameterPolicyFactory);
33              mvcEndpointDataSource.ConventionalEndpointInfos.Add(endpointInfo);
34             }
35             else
36             {
37                 throw new InvalidOperationException($"Cannot use '{router.GetType().FullName}' with Endpoint Routing.");
38             }
39         }
40         if (!app.Properties.TryGetValue(EndpointRoutingRegisteredKey, out _))
41         {
42             // Matching middleware has not been registered yet
43             // For back-compat register middleware so an endpoint is matched and then immediately used
44             app.UseEndpointRouting();
45         }
46         return app.UseEndpoint();
47     }
48     else
49     {
50        //旧版路由方案
51     }
52 }

② 第6行,这里会获取并判断设置的EnableEndpointRouting的值,若为false,则采用旧版路由,详见上一篇文章;该值默认为true,即采用新版路由。

           ③ 对应第9行,MvcEndpointDataSource在新版路由中是个非常非常重要的角色,在启动初始化阶段,它完成了路由表存储和转换,此处先用颜色重点标记一下,大家记住它,在后面的流程中详细介绍。

           ④ 对应第16行,同旧版的RouteBuilder一样,这里会new一个 endpointRouteBuilder,二者都是一个IRouteBuilder,所以也同样调用configureRoutes(endpointRouteBuilder)方法(也就是startup中的配置)获取了一个Route的集合(IList<IRouter>)赋值给endpointRouteBuilder.Routes,这里有个特别该注意的地方if (router is Route route && router.GetType() == typeof(Route)) ,也就是这里只接受route类型,终结点路由系统不支持基于 IRouter的可扩展性,包括从 Route继承。

           ⑤ 对应第20行,这里对刚获取到的endpointRouteBuilder.Routes进行遍历,转换成了一个MvcEndpointInfo的集和,赋值给mvcEndpointDataSource.ConventionalEndpointInfos。

           ⑥ 之后就是向管道塞中间件了,这里的处理中间件由原来的RouterMiddleware改为EndpointMiddleware和EndpointRoutingMiddleware。


目录
相关文章
|
1月前
|
开发框架 NoSQL .NET
ASP.NET Core开发者指南(2022版路线图)
ASP.NET Core开发者指南(2022版路线图)
35 0
ASP.NET Core开发者指南(2022版路线图)
|
2月前
|
开发框架 移动开发 网络协议
ASP.NET Core 使用 Web Socket
ASP.NET Core 使用 Web Socket
25 0
|
2月前
|
开发框架 中间件 .NET
ASP.NET CORE 自定义中间件
ASP.NET CORE 自定义中间件
22 0
|
2月前
|
开发框架 前端开发 .NET
ASP.NET Core 使用Autofac
ASP.NET Core 使用Autofac
31 0
ASP.NET Core 使用Autofac
|
2月前
|
开发框架 .NET Linux
ASP.NET Core部署到linux(CentOS)
ASP.NET Core部署到linux(CentOS)
60 0
ASP.NET Core部署到linux(CentOS)
|
2月前
|
开发框架 .NET API
ASP.NET Core 部署到docker
ASP.NET Core 部署到docker
38 0
|
2月前
|
开发框架 .NET 数据安全/隐私保护
ASP.NET Core Kestrel部署HTTPS
ASP.NET Core Kestrel部署HTTPS1,在program.cs中CreateHostBuilder 替换成如下内容:public static IHostBuilder CreateHostBuilder(string[] args) => Host.CreateDefaultBuilder(args) .UseServ...
18 0
|
2月前
|
XML 开发框架 .NET
ASP.NET Core 使用记录3
解决Visual Studio报错 NETSDK1152: 找到了多个具有相同相对路径的发布输出文件原因:是项目多层引用(a引用了b、c,d引用了a、b、c),且被引用的项目生成了xml文件,发布时导致xml文件重复 ,但.net 6.0下会触发报错。解决:被引用项目不要生成xml文件【根本原因】;发布时,将C:\Program Files\dotnet\sdk\6.x的sdk移出C:\P...
18 0
|
2月前
|
开发框架 .NET API
ASP.NET Core 使用记录2
.net sdk 版本的切换版本更改命令:dotnet new globaljson --sdk-version 版本 --force CultureInfoSystem.Globalization 程序集下的类它提供有关特定区域性(对于非托管代码开发,则称为“区域设置”)的信息。 这些信息包括区域性的名称、书写系统、使用的日历、字符串的排序顺序以及对日期和数字的格式化设置。
19 0
 ASP.NET Core 使用记录2
|
2月前
|
开发框架 .NET Linux
ASP.NET Core 使用记录1
ASP.NET 项目启动 提示 ID为XXX的进程未启动原因:暂时不能明确。 解决方案:删除项目的 csproj 文件的WebProjectProperties节点内容。 <WebProjectProperties> <UseIIS>True</UseIIS> <AutoAssignPort>True</AutoAssignPort> ...
22 0
ASP.NET Core 使用记录1
相关产品
云迁移中心
推荐文章
更多