Filter过滤器

ASP.Net Core中,Filter(过滤器)实现了一种简化的AOP面向切面编程机制,它能在请求被控制器处理的前后统一执行自定义逻辑,从而实现诸如日志记录、权限检查、错误处理等功能。

Filter和Middleware的区别

Filter(过滤器)和Middleware(中间件)都是ASP.Net Core中用于拦截请求被控制器处理的机制,但它们的执行时机和作用范围有所不同。

执行时机:中间件是在HTTP请求管道中按顺序执行的组件,在处理请求时中间件首先被执行,响应回传给客户端时,执行顺序会反向进行,而过滤器则是在具体控制器和操作方法执行之前或之后运行的,从全局来看,在HTTP请求的处理管道中,中间件位于过滤器的“外层”。

作用范围:中间件是作用于整个应用的HTTP处理管道上的,它通常用于执行全局性的业务逻辑,过滤器则是特定于控制器或控制器方法的。认证和授权就是一个说明这种差异的例子,认证是全局性的,特别适合使用中间件实现,而授权的业务逻辑对不同的功能来说可能是差异化的,它就适合使用过滤器实现。

总而言之,过滤器和中间件功能存在重合,它们能实现同样的需求,但我们习惯于将全局性的业务逻辑写入中间件,而针对特定一组控制器的切面逻辑则更倾向于使用过滤器封装。

几种内置Filter类型

ASP.Net Core内置了5种Filter类型:

  • AuthorizationFilter:用于处理授权逻辑,检查请求是否合法,通常第一个执行
  • ResourceFilter:用户处理缓存和模型绑定等逻辑
  • ActionFilter:所谓的Action其实就是控制器方法,ActionFilter会在控制器方法执行之前和之后执行
  • ExceptionFilter:用于处理异常
  • ResultFilter:控制器方法执行完成后会执行ResultFilter,其中可以插入特定逻辑统一处理返回结果

我们可以基于这些内置Filter类型编写自定义过滤器。

自定义ActionFilter

自定义ActionFilter可以实现IActionFilterIAsyncActionFilter接口,前者是同步方式写法而后者是异步方式写法,这里我们采用异步实现编写一个例子。

using Microsoft.AspNetCore.Http.Extensions;
using Microsoft.AspNetCore.Mvc.Filters;

namespace DemoWebAPI.Filters;

public class MyActionFilter : Attribute, IAsyncActionFilter
{
    public async Task OnActionExecutionAsync(ActionExecutingContext context, ActionExecutionDelegate next)
    {
        Console.WriteLine($"收到请求 {context.HttpContext.Request.GetDisplayUrl()}");
        await next();
        Console.WriteLine("请求处理完成");
    }
}

代码中,我们的过滤器实现了IAsyncActionFilter接口,它拦截了控制器方法的执行逻辑,在控制器方法执行前后输出了一些信息。此外,MyActionFilter同时还是一个注解,能够标注到控制器类或控制器方法上。

下面例子控制器中,我们将自定义的过滤器注解标注在了控制器类上,这样控制器内的所有控制器方法执行前后都会执行过滤器逻辑。

using DemoWebAPI.Filters;
using DemoWebAPI.Model;
using Microsoft.AspNetCore.Mvc;

namespace DemoWebAPI.Controllers;

[ApiController]
[Route("api/[controller]")]
[MyActionFilter]
public class DemoController : ControllerBase
{
    [HttpGet("[action]")]
    public ActionResult<ApiResult> Hello()
    {
        return ApiResult.Success();
    }
}

此外,我们也可以将过滤器注解标注在控制器方法上,这样只有标注注解的方法才会执行过滤器逻辑。

[HttpGet("[action]")]
[MyActionFilter]
public ActionResult<ApiResult> Hello()
{
    // ...
}

有关其它Filter类型

除了泛用性最强的ActionFilter,其余几种Filter类型都有其特定的使用场景,我们将在后续章节涉及相关功能时详细介绍。

作者:Gacfox
版权声明:本网站为非盈利性质,文章如非特殊说明均为原创,版权遵循知识共享协议CC BY-NC-ND 4.0进行授权,转载必须署名,禁止用于商业目的或演绎修改后转载。