一、什么是中间件

中间件是汇集到以处理请求和响应的一个应用程序管道的软件。 每个组件:

  • 可以选择是否要将请求传递到管道中的下一个组件。
  • 可以在请求管道的下一个组件调用之前和之后执行相关业务操作。

二、使用 IApplicationBuilder 创建中间件管道

ASP.NET Core请求管道由一系列请求委托组成,这些请求委托按序一个接一个被调用,如图所示的顺序组成(按照黑色箭头的顺序执行):

.net core中间件和请求管道 .net core 中间件顺序_Core

 

每个委托可以执行相关操作在下一个委托的之前和之后。 委托还可以决定不将请求传递给委托链的下一个委托(我们称作短路)。

短路是通常需要的,因为它避免了不必要的工作。

例如:静态文件中间件可以返回静态文件的请求和短路管道的其余部分。

          异常处理委托应该尽早在管道中被调用,这样它们可以捕获请求管道后续阶段中发生的异常。

最简单的 ASP.NET Core 应用程序设置了处理所有请求的单个请求委托。 这种情况下不包括实际请求管道。 相反,单个的匿名函数中称为到每个 HTTP 请求的响应。

using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Http;

public class Startup
{
    public void Configure(IApplicationBuilder app)
    {
        app.Run(async context =>
        {
            await context.Response.WriteAsync("Hello, World!");
        });
    }
}

二、订购

二、Use, Run, and Map

三、Use,Run and Map

四、内置的中间件

五、自定义中间件

通常,中间件是封装在一个类,并且通过扩展方法公开。 如下的中间件,它根据查询字符串设置当前请求的区域性:

public class Startup
{
    public void Configure(IApplicationBuilder app)
    {
        app.Use((context, next) =>
        {
            var cultureQuery = context.Request.Query["culture"];
            if (!string.IsNullOrWhiteSpace(cultureQuery))
            {
                var culture = new CultureInfo(cultureQuery);

                CultureInfo.CurrentCulture = culture;
                CultureInfo.CurrentUICulture = culture;
            }

            // Call the next delegate/middleware in the pipeline
           //调用应用程序管道中下一委托/中间件

            return next();
        });

        app.Run(async (context) =>
        {
            await context.Response.WriteAsync(
                $"Hello {CultureInfo.CurrentCulture.DisplayName}");
        });

    }
}

 

测试该中间件http://localhost:7997/?culture=no

下面的代码将中间件委托移动到一个类中:

using Microsoft.AspNetCore.Http;
using System.Globalization;
using System.Threading.Tasks;

namespace Culture
{
    public class RequestCultureMiddleware
    {
        private readonly RequestDelegate _next;

        public RequestCultureMiddleware(RequestDelegate next)
        {
            _next = next;
        }

        public Task Invoke(HttpContext context)
        {
            var cultureQuery = context.Request.Query["culture"];
            if (!string.IsNullOrWhiteSpace(cultureQuery))
            {
                var culture = new CultureInfo(cultureQuery);

                CultureInfo.CurrentCulture = culture;
                CultureInfo.CurrentUICulture = culture;

            }

            // Call the next delegate/middleware in the pipeline
            return this._next(context);
        }
    }
}

通过如下的扩展方法在IApplicationBuilder中公开中间件

using Microsoft.AspNetCore.Builder;

namespace Culture
{
    public static class RequestCultureMiddlewareExtensions
    {
        public static IApplicationBuilder UseRequestCulture(
            this IApplicationBuilder builder)
        {
            return builder.UseMiddleware<RequestCultureMiddleware>();
        }
    }
}

 

public class Startup
{
    public void Configure(IApplicationBuilder app)
    {
        app.UseRequestCulture();

        app.Run(async (context) =>
        {
            await context.Response.WriteAsync(
                $"Hello {CultureInfo.CurrentCulture.DisplayName}");
        });

    }
}

中间件组件可以通过构造函数参数的依赖关系注入达到控制反转的目的。 UseMiddleware<T>也可以直接接受其他参数。

总结

本文详细介绍了 ASP.NET Core 请求管道的构建过程,以及一些帮助我们更加方便的来配置请求管道的扩展方法。在 ASP.NET Core 中,至少要有一个中间件来响应请求,而我们的应用程序实际上只是中间件的集合,MVC 也只是其中的一个中间件而已。简单来说,中间件就是一个处理http请求和响应的组件,多个中间件构成了请求处理管道,每个中间件都可以选择处理结束,还是继续传递给管道中的下一个中间件,以此串联形成请求管道。通常,我们注册的每个中间件,每次请求和响应均会被调用,但也可以使用 Map , MapWhen ,UseWhen 等扩展方法对中间件进行过滤。