Middleware

Middleware运行方式

ASP.NET Core 每个 request 都会经过注册的 Middleware,Response也会经过先进后出的方式逐一回传
Middleware&Filter - 图1

1.建立 Middleware

Middleware 取代了 ASP.NET MVC 的 HTTP Modules 及 HTTP Handlers,使用方式更为简单。

  1. public class FirstMiddleware
  2. {
  3. private readonly RequestDelegate _next;
  4. public FirstMiddleware(RequestDelegate next)
  5. {
  6. _next = next;
  7. }
  8. public async Task Invoke(HttpContext context)
  9. {
  10. await context.Response.WriteAsync($"{nameof(FirstMiddleware)} in. \r\n");
  11. await _next(context);
  12. await context.Response.WriteAsync($"{nameof(FirstMiddleware)} out. \r\n");
  13. }
  14. }

2.注册 Middleware

public class Startup
{
    public void Configure(IApplicationBuilder app)
    {
        app.UseMiddleware<FirstMiddleware>();
        app.UseMiddleware<SecondMiddleware>();
        app.UseMiddleware<ThirdMiddleware>();

        app.Run(async (context) =>
        {
            await context.Response.WriteAsync("Hello World! \r\n");
        });
    }
}

Filters

Filter 是延续 ASP.NET MVC 的产物,同样保留了五种的 Filter,分別是 Authorization FilterResource FilterAction FilterException FilterResult Filter

Filter 介绍

Filter 的作用是在 Action 执行前执行后做一些加工处理。
某种程度来看,会跟 Middleware 很像,但执行的順序略有不同,用对 Filter 不仅可以減少代码,还可以提供执行效率。

ASP.NET Core 有以下5种 Filter 可以使用:

  • Authorization Filter
    Authorization 是5种 Filter 中优先序最高的,通常用于认证 Requert 合不合法,不合法后面就直接跳过。

  • Resource Filter
    Resource 是第二优先,会在 Authorization 之后,Model Binding 之前执行。通常会是需要对 Model 加工处理才用。

  • Action Filter
    最容易使用的 Filter,请求数据包进出都会遇到。跟 Resource Filter 很类似,但不会经过 Model Binding。

  • Exception Filter
    异常处理的 Exception。

  • Result Filter
    当 Action 完成后,最终会经过的 Filter。

Filter 运行方式

ASP.NET Core 的每个 Request 都会先经过已注册的 Middleware 接著才会执行 Filter,除了会依照上述的順序外,同类型的 Filter 都会以先进后出的方式处理数据请求。
Response 在某些 Filter 并不会做处理,会值接 Bypass。Request 及 Response 的运行流程如下图
Middleware&Filter - 图2

黄色箭头是正常情况的流程
灰色箭头异常情况下处理流程

注册 Filter

Filter 有两种注册方式,第一种是全局注册,另一种是用 Attribute 区域注册的方式,只套用在特定的 Action。

全局注册

在 Startup.cs 注册 Filter,这样就可以套用到所有的 Request。如下:

public class Startup
{
    public void ConfigureServices(IServiceCollection services)
    {
        services.AddMvc(config =>
        {
            config.Filters.Add(new ResultFilter());
            config.Filters.Add(new ExceptionFilter());
            config.Filters.Add(new ResourceFilter());
        });
    }
}

区域注册

ASP.NET Core 在 Attribute 注册 Filter 的方式跟 ASP.NET MVC 有一点不一样,要透过 [TypeFilter(type)]
在 Controller 或 Action 上面加上 [TypeFilter(type)] 就可以区域注册 Filter。如下

namespace MyWebsite.Controllers
{
    [TypeFilter(typeof(AuthorizationFilter))]
    public class HomeController : Controller
    {
        [TypeFilter(typeof(ActionFilter))]
        public void Index()
        {
            Response.WriteAsync("Hello World! \r\n");
        }

        [TypeFilter(typeof(ActionFilter))]
        public void Error()
        {
            throw new System.Exception("Error");
        }
    }
}

[TypeFilter(type)] 用起来有点麻烦,想要像通过 ASP.NET MVC 用 [Attribute] 注册 Filter ,只要将 Filter 继承 Attribute 即可。如下

public class AuthorizationFilter : Attribute, IAuthorizationFilter
{
    // ...
}
public class ActionFilter : Attribute, IActionFilter
{
    // ...
}

申明

文章收集与博客 John Wu’s Blog,由于访问网速慢,故作整理
https://blog.johnwu.cc/article/ironman-day14-asp-net-core-filters.html