<一>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>();

 

posted @ 2022-04-26 00:22  许轩霖  阅读(205)  评论(0编辑  收藏  举报