<一>ASP.NET Core 管道

ASP.NET Core应用程序提供了处理每个请求的完整控制。在这个请求管道中,我们可以动态配置各种业务逻辑对应的中间件(middleware),从而达到服务端可以针对不同用户做出不同的请求响应。

一、管道

ASP.NET Core应用程序在创建程序宿主之前需要构建一个管道。而IApplicationBuilder 是用来构建请求管道的.而请求管道,本质上就是对 HttpContext 的一系列操作,即通过对 Request 的处理,来生成 Reponse

namespace Microsoft.AspNetCore.Builder {     //     // 摘要:     //     Defines a class that provides the mechanisms to configure an application's request     //     pipeline.     public interface IApplicationBuilder     {         //         // 摘要:         //     Gets or sets the System.IServiceProvider that provides access to the application's         //     service container.         IServiceProvider ApplicationServices         {             get;             set;         }          //         // 摘要:         //     Gets the set of HTTP features the application's server provides.         IFeatureCollection ServerFeatures         {             get;         }          //         // 摘要:         //     Gets a key/value collection that can be used to share data between middleware.         IDictionary<string, object?> Properties         {             get;         }          //         // 摘要:         //     Adds a middleware delegate to the application's request pipeline.         //         // 参数:         //   middleware:         //     The middleware delegate.         //         // 返回结果:         //     The Microsoft.AspNetCore.Builder.IApplicationBuilder.         IApplicationBuilder Use(Func<RequestDelegate, RequestDelegate> middleware);          //         // 摘要:         //     Creates a new Microsoft.AspNetCore.Builder.IApplicationBuilder that shares the         //     Microsoft.AspNetCore.Builder.IApplicationBuilder.Properties of this Microsoft.AspNetCore.Builder.IApplicationBuilder.         //         // 返回结果:         //     The new Microsoft.AspNetCore.Builder.IApplicationBuilder.         IApplicationBuilder New();          //         // 摘要:         //     Builds the delegate used by this application to process HTTP requests.         //         // 返回结果:         //     The request handling delegate.         RequestDelegate Build();     } }

从上面接口源代码中,IApplicationBuilder提供了几个管道构建的方法

1、Use  注册中间件

Use是我们非常熟悉的注册中间件的方法,就是将注册的中间件保存到其内部属性 _components 中。注册多个中间件的时候围绕着Next分别对RequestRespone做出相应的处理,B的执行会嵌套在A的里面,因此A是第一个处理Request,

并且最后一个收到Respone,这样就构成一个经典的的U型管道。

public IApplicationBuilder Use(Func<RequestDelegate, RequestDelegate> middleware) {     _components.Add(middleware);     return this; }
 app.Use(next =>     {         Console.WriteLine(A);         return async (context) =>         {             // 1. 对Request做一些处理             // TODO               // 2. 调用下一个中间件             Console.WriteLine(A-BeginNext);             await next(context);             Console.WriteLine(A-EndNext);               // 3. 生成 Response             //TODO         };     });
var app = builder.Build(); app.UseHttpsRedirection(); app.UseStaticFiles(); app.UseRouting();

2、Build  创建一个请求管道

 Build 方法创建一个 RequestDelegate 类型的委托。可以看到首先定义了一个 404 的中间件,然后使用了Reverse函数将注册的中间件列表进行反转,因此首先执行我们所注册的最后一个中间件,输入参数便是一个 404 ,

依次执行到第一个中间件,按我们的注册顺序从里到外,一层套一层。那么根据多中间件注册的u型管道模型,最后response的信息是第一个注册的中间件,即返回404。

public RequestDelegate Build() {     RequestDelegate app = context =>     {         context.Response.StatusCode = 404;         return Task.CompletedTask;     };      foreach (var component in _components.Reverse())     {         app = component(app);     }      return app;
var builder = WebApplication.CreateBuilder(args);  //创建程序宿主  // Add services to the container. builder.Services.AddRazorPages();  var app = builder.Build();    //创建管道

 3、Run 结束管道向下调用

在注册的中间件中,是通过 Next 委托串连起来的,如果在某一个中间件中没有调用 Next 委托,则该中间件将做为管道的终点。因此通过管道的串联调用,可以在管道中进行拦截,比如授权中间件,当授权成功后才进入Next,如果授权不成功则response。

如果流程正常走,那我们在最后一个中间件不应该再调用 Next 委托,而使用Run 扩展方法来注册最后一个中间件。

public static class RunExtensions {     public static void Run(this IApplicationBuilder app, RequestDelegate handler)     {         if (app == null)         {             throw new ArgumentNullException(nameof(app));         }           if (handler == null)         {             throw new ArgumentNullException(nameof(handler));         }         app.Use(_ => handler);     } }
app.UseRouting();  app.UseAuthorization();  app.MapRazorPages();  app.Run();

二、中间件

1、app.UseMiddleware()自定义中间件委托函数

从Use方法中可以看到所谓的中间件实际上就是个委托(Func<RequestDelegate, RequestDelegate>) 。 ASP.NET Core 提供了一个更加具体的中间件的概念,我们在大部分情况下都会将中间件定义成一个单独的类型,使代码更加清晰。

因此一般都使用自定义中间件委托函数注入中间件。自定义使用中间件有两种方式:

  • 通过继承IMiddleware实现(需要注入服务)
public class TestMiddleWare : IMiddleware     {         public Task InvokeAsync(HttpContext context, RequestDelegate next)         {             context.Response.WriteAsync(中间件类A);             return next(context);         }     }
services.AddSingleton<TestMiddleWare>();  
app.UseMiddleware<TestMiddleWare>();
  • 通过约定实现
public class TestMiddleWare     {         public readonly RequestDelegate _next;         public TestMiddleWare(RequestDelegate next)         {             _next = next;         }         public Task InvokeAsync(HttpContext context)         {             context.Response.WriteAsync(中间件类A);             return _next(context);         }     }
app.UseMiddleware<TestMiddleWare>();