附上demo实例 可以看到中间件的执行顺序如下 层层嵌套

next.Invoke(context)和 next(context)写法没区别

第一个next.Invoke(context)表示执行它下面的第二个context方法
第二个next.Invoke(context)表示执行它下面的第三个context方法
直到调用到最后一个context方法 它才会返回自己下面没执行的方法 执行完自己的方法 以此类推到调用的那个母方法 直到最开始调用context的方法
middleware中间件_自定义

可以看到输出结果是这样的

middleware中间件_应用程序_02

视图展示

middleware中间件_方法调用_03

自定义中间件搭建

继续在上面的demo中添加一个自定义的中间件 附代码

 public void Configure(IApplicationBuilder app, IWebHostEnvironment env)//应用程序的建造者
        {
            Func<RequestDelegate, RequestDelegate> middleware1 = next =>
            {
                return async context =>
                {
                    await context.Response.WriteAsync("<p>this is middleware 1 start");
                    await next(context);
                    await context.Response.WriteAsync("<p>this is middleware 1 end");

                };
            };
            app.Use(middleware1);
            Func<RequestDelegate, RequestDelegate> middleware2 = next =>
            {
                return async context =>
                {
                    await context.Response.WriteAsync("<p>this is middleware 2 start");
                    await next(context);
                    await context.Response.WriteAsync("<p>this is middleware 2 end");

                };
            };
            app.Use(middleware2);
            Func<RequestDelegate, RequestDelegate> middleware3 = next =>
            {
                return async context =>
                {
                    await context.Response.WriteAsync("<p>this is middleware 3 start");
                    await next(context);//注意这里上面的图是没有的 这里有 是为了测试自定义中间件的加入
                    await context.Response.WriteAsync("<p>this is middleware 3 end");

                };
            };
            app.Use(middleware3);
             //自定义中间件
            app.UseMiddleware<RequestIPMiddleware>();
        }

定义一个RequestIPMiddleware类

 public class RequestIPMiddleware
    {
        // 私有字段
        private readonly RequestDelegate _next;

        /// <summary>
        /// 公共构造函数,参数是RequestDelegate类型
        /// 通过构造函数进行注入,依赖注入服务会自动完成注入
        /// </summary>
        /// <param name="next"></param>
        public RequestIPMiddleware(RequestDelegate next)
        {
            _next = next;
        }

        /// <summary>
        /// Invoke方法
        /// 返回值是Task,参数类型是HttpContext 这个方法必须有
        /// </summary>
        /// <param name="context">Http上下文</param>
        /// <returns></returns>
        public async Task Invoke(HttpContext context)
        {
            await context.Response.WriteAsync($"<p>User IP:{context.Connection.RemoteIpAddress.ToString()}\r\n");
            // 调用管道中的下一个委托 这里注释掉是为了回调之前的中间件中的方法 最后的一个中间件是不允许有next.Invoke的 否则不回回调之前的中间件就结束了 因为它找不到下一个context
            //await _next.Invoke(context);
        }
    }

实现效果
middleware中间件_应用程序_04

小扩展 同时也可以使用扩展中间件的方法调用中间件

再建一个类 用于扩展RequestIPMiddleware方法

 public static class RequestIPExtensions
    {
        /// <summary>
        /// 扩展方法,对IApplicationBuilder进行扩展
        /// </summary>
        /// <param name="builder"></param>
        /// <returns></returns>
        public static IApplicationBuilder UseRequestIP(this IApplicationBuilder builder)
        {
            return builder.UseMiddleware<RequestIPMiddleware>();
        }
    }

在startup中修改代码

      app.UseRequestIP();//替换成这个
      //app.UseMiddleware<RequestIPMiddleware>();
自定义中间件总结:

自定义中间件类
第一,它包含一个带有RequestDelegate类型参数的构造函数,这个RequestDelegate类型的参数表示在请求管道中的下一个中间件;

第二,它包含一个Invoke方法,该方法接受一个HttpContext类型的参数,并且这个方法的返回值为Task,这个HttpContext类型的参数即表示传入的HTTP请求。以下是一个典型自定义中间件:
第三,注册启用中间件IApplicationBuilder.UseMiddleware()