ASP.Net Core 中间件

ASP.Net Core 中间件

中间件是处理HTTP请求和响应的组件,本质是一段代码。多个中间件通过链式关系使之形成了管道。

ASP.Net Core内置了许多中间件,主要包括了MVC、认证、错误、静态文件、HTTPS重定向、跨域资源共享等,ASP.Net Core也允许自定义中间件。

1.添加中间件

Startup类的Configure方法就是添加中间件的地方。
在Configure方法中,通过调用IApplicationBuilder接口中以Use开头的拓展方法,即可添加系统内置的中间件。

public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
    app.UseStaticFiles();
    app.UseRouting();
    app.UseEndpoints(endpoints =>
    {
        endpoints.MapControllerRoute(
            name: "default",
            pattern: "{controller=Home}/{action=Index}/{id?}");
    });
}

中间件的方法会逐一顺序的向管道添加相应的中间件,这里需要注意添加中间件的顺序。

2.中间件执行顺序

HTTP请求从管道的一端进入,并按照顺序由每一个中间件处理,响应会遍历进来时经过的中间件,顺序与进来时正好相反。
在这里插入图片描述
中间件执行顺序验证程序

public void Configure(IApplicationBuilder app, IWebHostEnvironment env, ILogger<Startup> logger)
{
    app.Use(async (context, next) =>
    {
        logger.LogInformation("Middleware 1 Start");
        await next();
        logger.LogInformation("Middleware 1 End");
    });

    app.Use(async (context, next) =>
    {
        logger.LogInformation("Middleware 2 Start");
        await next();
        logger.LogInformation("Middleware 2 End");
    });

    app.Run(async (context) =>
    {
        logger.LogInformation("Middleware 3");
        await context.Response.WriteAsync("This is a test");
    });
}

中间件执行顺序验证结果
在这里插入图片描述

3.添加请求管道 Run、Use、Map

3.1 Run 终端中间件

namespace Microsoft.AspNetCore.Builder
{
    public static class RunExtensions
    {
        public static void Run(this IApplicationBuilder app, RequestDelegate handler);
    }
}

Run方法接受一个RequestDelegate类型的参数委托,用来处理传入的HTTP的请求。

namespace Microsoft.AspNetCore.Http
{
    public delegate Task RequestDelegate(HttpContext context);
}

Run方法实例

public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
    app.Run(async (context) =>
    {
        await context.Response.WriteAsync("This is a test");
    });
}

3.2 Use 传入下一个中间件

namespace Microsoft.AspNetCore.Builder
{
    public static class UseExtensions
    {
        public static IApplicationBuilder Use(this IApplicationBuilder app, Func<HttpContext, Func<Task>, Task> middleware);
    }
}

Use方法实例

public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
    app.Use(async (context, next) =>
    {
        await next();
    });

    app.Run(async (context) =>
    {
        await context.Response.WriteAsync("This is a test");
    });
}

3.3 Map 传入新分支,不再回原管道

namespace Microsoft.AspNetCore.Builder
{   
    public static class MapExtensions
    {       
        public static IApplicationBuilder Map(this IApplicationBuilder app, PathString pathMatch, Action<IApplicationBuilder> configuration);        
        public static IApplicationBuilder Map(this IApplicationBuilder app, PathString pathMatch, bool preserveMatchedPathSegment, Action<IApplicationBuilder> configuration);
    }
}

Map方法实例

public void Configure(IApplicationBuilder app, IWebHostEnvironment env, ILogger<Startup> logger)
{
    app.Use(async (context, next) =>
    {
        logger.LogInformation("Middleware 1 Start");
        await next();
        logger.LogInformation("Middleware 1 End");
    });

    app.Map(new PathString("/map"),
        o => o.Run(async (context) =>
        {
            logger.LogInformation("Middleware 5");
            await context.Response.WriteAsync("This is a test");
        }));

    app.Run(async (context) =>
    {
        logger.LogInformation("Middleware 4");
        await context.Response.WriteAsync("This is a test");
    });
}

4.添加请求管道复杂控制 UseWhen、MapWhen

UseWhen、MapWhen可以满足更复杂的添加管道条件,对HttpContext对象进行更细致的判断,然后决定是否进入新的分支继续执行中间件。
UseWhen执行完分支,会继续回到原来的管道。
MapWhen执行完分支,不在回到原来的管道。

namespace Microsoft.AspNetCore.Builder
{
    public static class UseWhenExtensions
    {
        public static IApplicationBuilder UseWhen(this IApplicationBuilder app, Func<HttpContext, bool> predicate, Action<IApplicationBuilder> configuration);
    }
    
    public static class MapWhenExtensions
    {
        public static IApplicationBuilder MapWhen(this IApplicationBuilder app, Func<HttpContext, bool> predicate, Action<IApplicationBuilder> configuration);
    }
}

MapWhen、UseWhen方法实例

public void Configure(IApplicationBuilder app, IWebHostEnvironment env, ILogger<Startup> logger)
{
    app.Use(async (context, next) =>
    {
        logger.LogInformation("Middleware 1 Start");
        await next();
        logger.LogInformation("Middleware 1 End");
    });

    app.UseWhen(context => context.Request.Path.Value == "/use",
        o => o.Use(async (context, next) =>
        {
            logger.LogInformation("Middleware 2 Start");
            await next();
            logger.LogInformation("Middleware 2 End");
        }));

    app.MapWhen(context => context.Request.Path.Value == "/map",
        o => o.Run(async (context) =>
        {
            logger.LogInformation("Middleware 5");
            await context.Response.WriteAsync("This is a test");
        }));

    app.Run(async (context) =>
    {
        logger.LogInformation("Middleware 4");
        await context.Response.WriteAsync("This is a test");
    });
}

Log结果:
1.当输入地址为localhost:端口号
在这里插入图片描述
2.当输入地址为localhost:端口号/use
在这里插入图片描述
3.当输入地址为localhost:端口号/map
在这里插入图片描述

5.自定义中间件

创建自定义中间件非常简单,需要至少一个特定的构造函数和一个Invoke方法。
对于构造函数,应包括一个RequestDelegate类型的参数,该参数表示在管道中的下一个中间件。
对于Invoke方法,应包含HTTPContext类型的参数,并返回Task类型。

1.自定义中间件

namespace WebCore1.Middleware
{
    public class HttpMethodCheckMiddleware
    {
        private readonly RequestDelegate _next;
        public HttpMethodCheckMiddleware(RequestDelegate requestDelegate,IHostEnvironment hostEnvironment)
        {
            _next = requestDelegate;
        }

        public Task Invoke(HttpContext context)
        {
            var requestMethod = context.Request.Method.ToUpper();
            if (requestMethod == HttpMethods.Get)
            {
                return _next(context);
            }
            else
            {
                context.Response.StatusCode = 400;
                context.Response.ContentType = "text/plain;charset=utf-8";
                context.Response.WriteAsync("只支持GET");
                return Task.CompletedTask;
            }
        }
    }
}

2.创建扩展方法,方便中间件调用

namespace WebCore1.Middleware
{
    public static class CustomMiddlewareExtensions
    {
        public static IApplicationBuilder UseHttpMethodCheckMiddleware(this IApplicationBuilder app)
        {
            return app.UseMiddleware<HttpMethodCheckMiddleware>();
        }
    }
}

3.中间件调用

public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
    app.UseHttpMethodCheckMiddleware();

    app.Run(async (context) =>
    {
        await context.Response.WriteAsync("This is a test");
    });
}

Happy Ending…

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值