前几天. NET Core3.1 发布, 于是我把公司一个基础通用系统升级了, 同时删除了几个基础模块当然这几个基础模块与. NET Core3.1 无关, 其中包括了支付模块, 升级完后静文 (同事) 问我你把支付删除了啊? 我说是啊, 没考虑好怎么加上(感觉目前不太好, 我需要重新设计一下).
故事从这开始
考虑支付的时候我考虑的是将支付 sdk 如何直接引入到系统, 以及可以有一系列支付的路由, 我需要考虑的是如果创建响应给指定的地址, so 我开始想如何达到我的目的自定义个中间件, Use,Run,Map???
路由的进阶
路由负责将请求 URI 映射到终结点并向这些终结点调度传入的请求. 路由在应用中定义, 并在应用启动时进行配置. 路由可以选择从请求包含的 URL 中提取值, 然后这些值便可用于处理请求. 通过使用应用中的路由信息, 路由还能生成映射到终结点的 URL.
在 ASP.NET Core 2.1 和更低版本中, 路由是通过实现将 IRouter 传入的 URL 映射到处理程序的接口来处理的. 通常, 将直接依赖 MvcMiddleware 添加到中间件管道末端的实现, 而不是直接实现该接口. 一旦请求到达 MvcMiddleware, 便会应用路由来确定传入请求 URL 路径所对应的控制器和操作.
然后, 该请求在执行处理程序之前经过了各种 MVC 筛选器. 这些过滤器形成了另一条 "管道", 让人联想到中间件管道, 并且在某些情况下必须复制某些中间件的行为. 一个典型的例子就是 CORS 政策. 为了对每个 MVC 操作以及中间件管道的其他 "分支" 实施不同的 CORS 策略, 内部需要进行一定程度的重复.
"分支" 中间件管道通常用于 "伪路由". 如 Map()在中间件管道中的扩展方法, 将允许您在传入路径具有给定前缀时有条件地执行某些中间件.
如下所示:
- App.Map("/order", App => App.Run(async context =>
- {
- await context.Response.WriteAsync("Order");
- })
- );
在这种情况下, 该 Run()方法是 "终端" 中间件, 因为它返回响应. 但是从某种意义上说, 整个 Map 分支对应于应用程序的 "端点".
在 ASP.NET Core 2.2 中, 引入了终结点路由作为 MVC 控制器的新路由机制. 此实现本质上是的内部实现 MvcMiddleware .
在 ASP.NET Core 2.x 中使用 Map()
下面我们自定义一个中间件, 该中间件返回直接返回一个相应而不是继续往下执行调用_next 委托, 一个很基本的中间件.
- public class ApiEndpointMiddleware
- {
- private readonly RequestDelegate _next;
- public ApiEndpointMiddleware(RequestDelegate next)
- {
- _next = next;
- }
- public async Task InvokeAsync(HttpContext context)
- {
- context.Response.StatusCode = 200;
- await context.Response.WriteAsync("Order");
- }
- }
在 ASP.NET Core 2.x 中, 可以通过使用扩展方法指定路由访问该中间件, 从而将其包含在 Startup.cs 的中间件管道中
- public void Configure(IApplicationBuilder App)
- {
- App.UseStaticFiles();
- App.Map("/order", App => App.UseMiddleware<ApiEndpointMiddleware>()); versionApp.UseMiddleware<VersionMiddleware>());
- App.UseMvcWithDefaultRoute();
- }
当我们访问 /order 或者 /order/1 路由都会得到自定义中间件返回的相应.
将中间件转换为端点路由
在 ASP.NET Core 3.0 中, 我们使用端点路由, 因此路由步骤与端点的调用是分开的. 实际上, 这意味着我们有两个中间件:
EndpointRoutingMiddleware 实际的路由, 即计算将为指定的请求 URL 路径调用哪个端点.
EndpointMiddleware 所有调用的端点.
它们在中间件管道中的两个不同点处添加, 因为它们起着两个不同的作用. 一般而言, 我们想的是路由中间件提前在管道中, 以便后续的中间件可以访问有关将执行的端点的信息. 端点的调用应在管道的末端进行.
如下所示:
- public void Configure(IApplicationBuilder App, IwebHostEnvironment env)
- {
- if (env.IsDevelopment())
- {
- App.UseDeveloperExceptionPage();
- }
- App.UseHttpsRedirection();
- App.UseRouting();
- App.UseAuthorization();
- App.UseEndpoints(endpoints =>
- {
- endpoints.MapControllers();
- });
- }
该 UseRouting()扩展方法添加 EndpointRoutingMiddleware 到管道, 同时将 UseEndpoints()扩展方法添加 EndpointMiddleware 到管道. UseEndpoints()实际上为应用程序注册所有端点的位置.
那么如何将我们自定义中间件使用端点路由来映射呢?
从概念上讲, 我们 UseEndpoints()使用 / OrderURL 作为匹配的路径, 将 "order" 端点的注册移动到调用中:
- endpoints.MapControllers();
- endpoints.Map("/order",endpoints.CreateApplicationBuilder()
- .UseMiddleware<ApiEndpointMiddleware>().Build()).WithDisplayName("order-api");
在我们上面针对 ASP.NET Core 2.x 的实现中, 我们将匹配 / order,/order/123 等端点路由
例如:
endpoints.Map("/order/{action}",null);
这将同时匹配 /order /order/1, 但不匹配 / order/status/1. 它比以前的版本功能强大得多.
在上一个示例中, 我们提供了一个显示名称(主要用于调试目的), 但是我们可以附加其他的信息, 例如授权策略或 CORS 策略, 其他中间件可以查询这些信息. 例如:
- App.UseEndpoints(endpoints =>
- {
- endpoints.MapControllers();
- endpoints.Map("/order/{action}",endpoints.CreateApplicationBuilder()
- .UseMiddleware<ApiEndpointMiddleware>().Build()).WithDisplayName("order-api").RequireCors("AllowAllHosts")
- .RequireAuthorization("AdminOnly");
- });
我们向端点添加了 CORS 策略 (AllowAllHosts) 和授权策略(AdminOnly). 当到达端点的请求到达时, 并在执行端点之前采取相应的措施.
参考
来源: https://www.cnblogs.com/yyfh/p/12010232.html