首页 > 其他分享 >.NET CORE 终端路由中间件 app.UseEndpoints

.NET CORE 终端路由中间件 app.UseEndpoints

时间:2023-08-28 10:58:48浏览次数:44  
标签:CORE nameof UseEndpoints builder endpointRouteBuilder 中间件 UseRouting 路由


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

public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
        app.UseRouting();
        app.UseAuthorization();
        app.UseEndpoints(endpoints =>
        {
              endpoints.MapControllers();
        });
}

一、app.UseRouting()

该中间件会检查应用中定义的终结点列表,然后通过匹配 URL 和 HTTP 方法来选择最佳的终结点简单说,该中间件的作用是根据一定规则来选择出终结点
1、源码分析
            public static IApplicationBuilder UseRouting(this IApplicationBuilder builder)
            {
                //判空
                ArgumentNullException.ThrowIfNull(builder);

                //判断RoutingMarkerService 确保是否添加了所有服务
                VerifyRoutingServicesAreRegistered(builder);

                //VerifyRoutingServicesAreRegistered 内部
                //// 必须先执行了 AddRouting
                //if (app.ApplicationServices.GetService(typeof(RoutingMarkerService)) == null)
                //{
                //    throw new InvalidOperationException(Resources.FormatUnableToFindServices(
                //        nameof(IServiceCollection),
                //        nameof(RoutingServiceCollectionExtensions.AddRouting),
                //        "ConfigureServices(...)"));
                //}

                //初始化数据源
                if (builder.Properties.TryGetValue(GlobalEndpointRouteBuilderKey, out var obj))
                {
                    endpointRouteBuilder = (IEndpointRouteBuilder)obj!;
                    //知道在设置全局路由构建器时是否调用UseRouting()
                    builder.Properties[EndpointRouteBuilder] = endpointRouteBuilder;
                }
                else
                {
                    endpointRouteBuilder = new DefaultEndpointRouteBuilder(builder);

                    //EndpointRouteBuilder为字符串常量 __EndpointRouteBuilder
                    //// builder.Properties["__EndpointRouteBuilder"] = endpointRouteBuilder;
                    //// 将 endpointRouteBuilder 放入共享字典中
                    builder.Properties[EndpointRouteBuilder] = endpointRouteBuilder;
                }

                //DefaultEndpointRouteBuilder构造类内部
                //public DefaultEndpointRouteBuilder(IApplicationBuilder applicationBuilder)
                //{
                //    ApplicationBuilder = applicationBuilder ?? throw new ArgumentNullException(nameof(applicationBuilder));
                //    DataSources = new List<EndpointDataSource>();
                //}

                // Add UseRouting function to properties so that middleware that can't reference UseRouting directly can call UseRouting via this property
                // This is part of the global endpoint route builder concept


                builder.Properties.TryAdd(UseRoutingKey, (object)UseRouting);

                //操作完成后对此实例引用
                return builder.UseMiddleware<EndpointRoutingMiddleware>(endpointRouteBuilder);
            }
2、EndpointRoutingMiddleware 中间件
EndpointRoutingMiddleware中间件先是创建matcher,然后调用matcher.MatchAsync(httpContext)去寻找Endpoint,最后通过httpContext.GetEndpoint()验证了是否已经匹配到了正确的Endpoint并交个下个中间件继续执行!

核心就是将_endpointDataSource传递给_matcherFactory,创建matcher,然后进行匹配matcher.MatchAsync(httpContext)。ASP.NET Core默认使用的 matcher 类型是DfaMatcher,DFA(Deterministic Finite Automaton)是一种被称为“确定有限状态自动机”的算法,可以从候选终结点列表中查找到匹配度最高的那个终结点。


二、app.UseAuthorization()

暂时不看

三、app.UseEndpoints()

可以向该中间件的终结点列表中添加终结点,并配置这些终结点要执行的委托,该中间件会负责运行由EndpointRoutingMiddleware中间件选择的终结点所关联的委托。简单说,该中间件用来执行所选择的终结点委托
1、源码分析

            public static IApplicationBuilder UseEndpoints(this IApplicationBuilder builder, Action<IEndpointRouteBuilder> configure)
            {
                ArgumentNullException.ThrowIfNull(builder);
                ArgumentNullException.ThrowIfNull(configure);

                //所以在调用UseEndpoint之前 必须要先调用UseRouting,否则报错。
                //验证路由服务是否注册了
                VerifyRoutingServicesAreRegistered(builder);

                //验证端点路由中间件是否已注册
                // 将 endpointRouteBuilder 从共享字典中取出来,如果没有,则说明之前没有调用 UseRouting
                VerifyEndpointRoutingMiddlewareIsRegistered(builder, out var endpointRouteBuilder);

                //VerifyEndpointRoutingMiddlewareIsRegistered方法内部
                //private static void VerifyEndpointRoutingMiddlewareIsRegistered(IApplicationBuilder app, out DefaultEndpointRouteBuilder endpointRouteBuilder)
                //{
                //    if (!app.Properties.TryGetValue(EndpointRouteBuilder, out var obj))
                //    {
                //        var message =
                //            $"{nameof(EndpointRoutingMiddleware)} matches endpoints setup by {nameof(EndpointMiddleware)} and so must be added to the request " +
                //            $"execution pipeline before {nameof(EndpointMiddleware)}. " +
                //            $"Please add {nameof(EndpointRoutingMiddleware)} by calling '{nameof(IApplicationBuilder)}.{nameof(UseRouting)}' inside the call " +
                //            $"to 'Configure(...)' in the application startup code.";
                //        throw new InvalidOperationException(message);
                //    }

                //    //如果此处转换失败,程序会出错。
                //    endpointRouteBuilder = (DefaultEndpointRouteBuilder)obj;

                //    
                //    //此检查处理在两者之间调用Map或其他分叉管道的情况
                //    if (!object.ReferenceEquals(app, endpointRouteBuilder.ApplicationBuilder))
                //    {
                //        var message =
                //            $"The {nameof(EndpointRoutingMiddleware)} and {nameof(EndpointMiddleware)} must be added to the same {nameof(IApplicationBuilder)} instance. " +
                //            $"To use Endpoint Routing with 'Map(...)', make sure to call '{nameof(IApplicationBuilder)}.{nameof(UseRouting)}' before " +
                //            $"'{nameof(IApplicationBuilder)}.{nameof(UseEndpoints)}' for each branch of the middleware pipeline.";
                //        throw new InvalidOperationException(message);
                //    }
                //}


                configure(endpointRouteBuilder);


                //我们正在将数据源注册到一个全局集合中
                //可用于发现端点或生成URL。
                //每个中间件都有自己的数据源集合,所有这些数据源也
                //被添加到全局集合中。
                //这里就是填充RouteOptions的EndpointDataSources了。
                //UseRouting 和 UseEndpoints 必须添加到同一个 IApplicationBuilder 实例上
                var routeOptions = builder.ApplicationServices.GetRequiredService<IOptions<RouteOptions>>();
                foreach (var dataSource in endpointRouteBuilder.DataSources)
                {
                    if (!routeOptions.Value.EndpointDataSources.Contains(dataSource))
                    {
                        routeOptions.Value.EndpointDataSources.Add(dataSource);
                    }
                }

                //操作完成后对此实例引用
                return builder.UseMiddleware<EndpointMiddleware>();
            }
2、EndpointMiddleware中间件    
不理解 就是执行由EndpointRoutingMiddleware中间件附加到当前HttpContext上下文中的终结点。EndpointRoutingMiddleware中间件针对终结点的执行涉及如下所示的RouteOptions类型标识的配置选项。1、EndpointMiddleware 初始化的时候注入了routeOptions。2、当路由匹配到了终结点时,EndpointMiddleware则是该路由的终端中间件

四、三者关系

UseRouing 中间件主要是路由匹配,找到匹配的终结者路由Endpoint ;UseEndpoints 中间件主要针对UseRouting 中间件匹配到的路由进行 委托方法的执行等操作。 UseAuthorization 中间件主要针对 UseRouting 中间件中匹配到的路由进行拦截 做授权验证操作等,通过则执行下一个中间件UseEndpoints(),具体的关系可以看下面的流程图:在调用UseRouting之前,你可以注册一些用于修改路由操作的数据,比如UseRewriterUseHttpMethodOverrideUsePathBase等。在调用UseRoutingUseEndpoints之间,可以注册一些用于提前处理路由结果的中间件,如UseAuthenticationUseAuthorizationUseCors等。


五、UseEndpoints 配置

MapControllers              添加了对属性路由的控制器支持
MapAreaControllerRoute  将控制器的传统路由添加区域
MapControllerRoute         添加控制器的常规路由
                endpoints.MapAreaControllerRoute(
                    name: "ApiArea", "API",
                    pattern: "API/{controller=Test}/{action=Index}/{id?}"
                    );
                endpoints.MapAreaControllerRoute(
                    name: "UapiArea", "UAPI",
                    pattern: "UAPI/{controller=Test}/{action=Index}/{id?}"
                    );
                endpoints.MapAreaControllerRoute(
                    name: "WebArea", "Web",
                    pattern: "Web/{controller=Test}/{action=Index}/{id?}"
                    );

                endpoints.MapControllerRoute("default", "{controller=Home}/{action=Index}/{id?}");
区域的需要在控制器上加
    [Area("API")]
    [Route("/API/[controller]/[action]")]




ASP.NET Core路由中间件[4]: EndpointRoutingMiddleware和EndpointMiddleware - Artech - 博客园 (cnblogs.com)
https://www.cnblogs.com/artech/p/endpoint-middleware-04.html
重新整理 .net core 实践篇——— UseEndpoints中间件[四十八] - 敖毛毛 - 博客园 (cnblogs.com)
https://www.cnblogs.com/aoximin/p/15649807.html
理解ASP.NET Core - 路由(Routing) - xiaoxiaotank - 博客园 (cnblogs.com)https://www.cnblogs.com/xiaoxiaotank/p/15468491.html
ASP.NET Core框架揭秘[博文汇总-持续更新] - Artech - 博客园 (cnblogs.com)https://www.cnblogs.com/artech/p/inside-asp-net-core-3.html

标签:CORE,nameof,UseEndpoints,builder,endpointRouteBuilder,中间件,UseRouting,路由
From: https://www.cnblogs.com/buzheng11/p/17661680.html

相关文章

  • .NET ASP.NET CORE 中间件 管道
    一、管道路由、认证、会话、缓存等等,他们都是通过管道来实现的ASP.NETCore应用一般都是使用某个框架来开发,MVC、WebAPI,建立在某个特殊的中间件之上。通过编写中间件,扩展请求管道,在ASP.NETCore上创建我们自己的WEB框架,API网关Ocelot,API网关框架。Middleware两个职责:1、选择是......
  • .NET|--.Net Core 6 |--Swagger显示注释信息
    1.输出xml文件选中API项目,鼠标右击,选中"属性",勾选"生成>>输出>>文档文件"修改Program.cs中配置//varbuilder=WebApplication.CreateBuilder(args);builder.Services.AddSwaggerGen(options=>{options.SwaggerDoc("v1",newO......
  • [回馈]ASP.NET Core MVC开发实战之商城系统(六)
    经过一段时间的准备,新的一期【ASP.NETCoreMVC开发实战之商城系统】已经开始,在之前的文章中,讲解了商城系统的整体功能设计,页面布局设计,环境搭建,系统配置,及首页【商品类型,banner条,友情链接,降价促销,新品爆款】,商品列表页面,商品详情,购物车等功能的开发,今天继续讲解订单管理功能开发,......
  • 开源.NetCore通用工具库Xmtool使用连载 - XML操作篇
    【Github源码】《上一篇》介绍了Xmtool工具库中的发送短信类库,今天我们继续为大家介绍其中的XML操作类库。XML操作是软件开发过程中经常会遇到的情况;包括XML内容的遍历解析,或者特定值内容的查询获取等等。Xmtool工具库提供了一种更方便的方式对Xml进行遍历解析或者对特定节点内......
  • 测试也要了解的中间件知识
    公众号后台有同学私信问了一个问题:中间件服务,如何做好质量保障工作?日常我们的测试工作范畴,大多都是业务强相关的,比如:电商业务大多是商品、订单、库存、支付;金融业务则是存取款、清结算等。而中间件服务很多时候会被我们下意识忽略,或者说测试过程中都会涉及到这些服务组件,但不会......
  • 开源.NetCore通用工具库Xmtool使用连载 - 发送短信篇
    【Github源码】《上一篇》介绍了Xmtool工具库中的发送邮件类库,今天我们继续为大家介绍其中的发送短信类库。发送短信就像发送邮件一样,在软件系统中使用非常普遍,甚至比发送邮件还要常见,有些甚至是软件标配功能;例如现在的短信验证码登录、通过短信找回密码等等。发送短信需要通过......
  • .NetCore WebAPI 导入、导出Excel文件 导入
    先下载一个NuGet包 在接口写方法//导入[HttpPost][Route("Import")]publicIActionResultImportExcel()//IFormFileformFile{try{varformFile=HttpContext.Request.Form.Files[0];//......
  • NET Core 6 .0 配置 SqlSugar
     选中项目NuGet包管理安装SqlSugarCore   安装好后>在配置文件中创建数据库连接字符串创建一个SqlSugarContext  usingRBACHS_Domain;usingSqlSugar;usingSystem;usingSystem.Collections.Generic;usingSystem.Linq;usingSystem.Text;usingSystem.Threading.......
  • .net Core中AutoFac的使用
    一、安装NuGet包 二、创建项目名称+Module的类三、继承AutoFac.Modeule四、重写Load方法,完成自动注入protectedoverridevoidLoad(ContainerBuilderbuilder){//1、动态加载程序集varassembly=Assembly.Load("NewRBAC.Repositor......
  • ASP.NET Core实时库SignalR简单应用
    一、什么是SignalR:SignalR是用于构建需要实时用户交互或实时数据更新的Web应用程序的一个开放源代码.NET库。不仅仅用在Web应用中,后面会讲到它的应用范围。它简化了简化了构建实时应用程序的过程,包括ASP.NETServer库和JavaScriptClient库,以便管理Client与Server连接并将内容......