在 .NET Core Web API 开发中,过滤器(Filter)是实现横切关注点解耦的核心组件。它能在请求处理的不同阶段拦截逻辑,统一处理权限验证、日志记录、异常捕获等通用需求,避免重复代码。本文将详细拆解 .NET Core Web API 内置的 5 类过滤器,分析其执行机制、核心用途,并提供可直接复用的实战示例。

一、过滤器核心概念:什么是过滤器?

过滤器是 .NET Core 提供的请求拦截机制,本质是一套 “钩子(Hook)” 系统,能嵌入请求处理生命周期的关键节点。其核心价值在于:

  • 解耦横切关注点:将日志、权限、异常处理等通用逻辑与业务逻辑分离;

  • 统一管控:对所有接口或指定接口批量应用通用规则;

  • 可扩展性:支持自定义过滤器,满足复杂业务场景。

所有过滤器遵循固定的执行顺序,从请求进入到响应返回,完整流程如下:

授权过滤器 → 资源过滤器 → 模型绑定 → Action 过滤器 → 执行 Action → Action 过滤器 → 结果过滤器 → 执行结果 → 结果过滤器 → 资源过滤器 → 响应返回

若任意阶段抛出异常,将直接触发异常过滤器处理。

二、5 类内置过滤器详解:用途 + 执行时机

1. 授权过滤器(AuthorizationFilter):请求的 “第一道关卡”

核心作用

验证请求是否有权限访问接口,是所有过滤器中执行最早的组件。若验证失败,直接终止请求并返回 401(未授权)或 403(禁止访问),不执行后续逻辑。

内置实现

  • [Authorize]:标记需要授权的 Action/Controller,依赖 IAuthorizationService 校验身份(配合 JWT、Cookie 等认证方案)。支持角色、策略等精细化授权,示例:
// 仅 Admin 角色可访问

[Authorize(Roles = "Admin")]

[HttpGet("admin/data")]

public IActionResult GetAdminData() => Ok("管理员数据");
  • [AllowAnonymous]:允许匿名访问,用于公开接口(如登录、注册),会跳过授权校验:
[AllowAnonymous]

[HttpPost("login")]

public IActionResult Login(string username, string password) => Ok("登录成功");

关键特点

  • 仅关注 “是否允许访问”,不处理业务逻辑;

  • 无 “执行后” 阶段,验证通过则进入下一个过滤器,失败直接返回;

  • 常用场景:登录状态校验、角色权限控制、接口访问白名单。

2. 资源过滤器(ResourceFilter):性能优化与资源管理

核心作用

在授权验证后、模型绑定前执行,主要用于性能优化(如响应缓存)或资源管理(创建 / 释放非线程安全资源)。可直接跳过模型绑定和 Action 执行(如返回缓存结果),大幅提升接口性能。

内置实现

  • [ResponseCache]:最常用的资源过滤器,设置 HTTP 响应缓存(通过 Cache-Control 头),减少重复请求开销:
// 缓存响应 30 秒,所有客户端共享缓存

[ResponseCache(Duration = 30, Location = ResponseCacheLocation.Any)]

[HttpGet("public/data")]

public IActionResult GetPublicData() => Ok("公开缓存数据");
  • 自定义扩展:通过 IAsyncResourceFilter 实现复杂缓存逻辑(如分布式缓存)。

关键特点

  • 执行时机早于 Action 过滤器,可干预模型绑定流程;

  • 支持 “执行前” 和 “执行后” 两个阶段(资源创建 / 释放);

  • 常用场景:接口响应缓存、请求频率限制、非线程安全资源管理。

3. Action 过滤器(ActionFilter):业务逻辑的 “前后置处理器”

核心作用

拦截 Action 方法的执行前后,是最常用的过滤器。依赖模型绑定(执行时参数已绑定完成),可访问和修改 Action 的输入参数与返回值,适用于业务相关的通用逻辑。

内置实现

  • [ValidateModel]:自动校验模型绑定后的对象(如 [Required][MaxLength] 等数据注解),校验失败返回 400 Bad Request。Web API 已默认启用,无需手动添加;

  • 自定义扩展:通过 IAsyncActionFilter 实现日志记录、参数校验扩展等。

实战示例:接口请求 / 响应日志过滤器

public class LogActionFilter : IAsyncActionFilter
{
    private readonly ILogger<LogActionFilter> _logger;

    // 支持依赖注入(如 ILogger)
    public LogActionFilter(ILogger<LogActionFilter> logger)
    {
        _logger = logger;
    }

    public async Task OnActionExecutionAsync(ActionExecutingContext context, ActionExecutionDelegate next)
    {
        // Action 执行前:记录请求信息
        var actionName = context.ActionDescriptor.DisplayName;
        var parameters = JsonSerializer.Serialize(context.Arguments);
        _logger.LogInformation($"【请求】接口:{actionName},参数:{parameters}");

        // 执行 Action 方法
        var resultContext = await next();

        // Action 执行后:记录响应信息
        if (resultContext.Result is ObjectResult objectResult)
        {
            var response = JsonSerializer.Serialize(objectResult.Value);
            _logger.LogInformation($"【响应】接口:{actionName},结果:{response}");
        }
    }
}

关键特点

  • 可修改 Action 输入(context.Arguments)和输出(resultContext.Result);

  • 执行时机:模型绑定后(前)、Action 执行后(后);

  • 常用场景:接口日志、参数校验、业务逻辑增强(如数据脱敏)。

4. 异常过滤器(ExceptionFilter):统一异常处理中心

核心作用

捕获请求处理过程中(Action、过滤器、模型绑定等阶段)抛出的未处理异常,统一格式化错误响应(避免返回默认 HTML 错误页),同时记录异常日志。

内置实现

  • 自定义扩展:通过 IAsyncExceptionFilter 实现全局异常处理,.NET 6+ 推荐全局注册。

实战示例:全局异常过滤器(统一 JSON 错误响应)

public class GlobalExceptionFilter : IAsyncExceptionFilter
{
    private readonly ILogger<GlobalExceptionFilter> _logger;

    public GlobalExceptionFilter(ILogger<GlobalExceptionFilter> logger)
    {
        _logger = logger;
    }

    public Task OnExceptionAsync(ExceptionContext context)
    {
        // 记录异常详情(含堆栈信息)
        _logger.LogError(context.Exception, "接口执行异常:{Message}", context.Exception.Message);

        // 统一返回 RFC 7807 标准格式错误响应
        var problemDetails = new ProblemDetails
        {
            Status = StatusCodes.Status500InternalServerError,
            Title = "服务器内部错误",
            Detail = context.Exception.Message,
            Instance = context.HttpContext.Request.Path
        };

        // 区分业务异常和系统异常(可选)
        if (context.Exception is BusinessException businessEx)
        {
            problemDetails.Status = businessEx.StatusCode;
            problemDetails.Title = "业务异常";
        }

        context.Result = new ObjectResult(problemDetails)
        {
            StatusCode = problemDetails.Status
        };

        // 标记异常已处理,避免框架默认处理
        context.ExceptionHandled = true;

        return Task.CompletedTask;
    }
}

// 自定义业务异常(示例)
public class BusinessException : Exception
{
    public int StatusCode { get; }
    public BusinessException(string message, int statusCode = 400) : base(message)
    {
        StatusCode = statusCode;
    }
}

关键特点

  • 仅捕获未处理异常,若已被其他组件处理则不触发;

  • 可自定义错误响应格式,提升接口友好性;

  • 常用场景:全局异常捕获、错误日志记录、业务异常统一处理。

5. 结果过滤器(ResultFilter):响应的 “最后加工器”

核心作用

拦截 Action 结果的执行前后(仅当 Action 成功执行且返回 IActionResult 时触发),用于格式化响应数据、添加响应头、统一包装结果等。

内置实现

  • [Produces]:指定响应格式(如 application/json),本质是通过结果过滤器设置 Content-Type 头:
[Produces("application/json")]

[ApiController]

[Route("api/[controller]")]

public class UserController : ControllerBase { ... }
  • 自定义扩展:通过 IAsyncResultFilter 实现响应统一包装。

实战示例:接口响应统一包装(全局启用)

public class WrapResponseFilter : IAsyncResultFilter
{
    public async Task OnResultExecutionAsync(ResultExecutingContext context, ResultExecutionDelegate next)
    {
        // 仅处理 ObjectResult 类型(Web API 默认返回类型)
        if (context.Result is ObjectResult objectResult)
        {
            // 统一包装格式:{ "code": 200, "message": "success", "data": ... }
            var response = new
            {
                Code = context.HttpContext.Response.StatusCode,
                Message = "success",
                Data = objectResult.Value
            };

            // 覆盖原始结果
            objectResult.Value = response;
            objectResult.DeclaredType = response.GetType();
        }

        // 执行后续逻辑(返回响应)
        await next();
    }
}

关键特点

  • 仅关注 IActionResult 的执行,不处理异常;

  • 可修改响应内容和响应头;

  • 常用场景:统一响应格式、响应数据脱敏、添加自定义响应头(如接口版本号)。

三、过滤器注册方式:3 种范围选择

过滤器的注册优先级为:局部(Action/Controller)> 全局,可根据需求选择合适的注册范围。

1. 局部注册(仅作用于单个 Action/Controller)

直接在 Action 或 Controller 上添加过滤器特性,适用于局部特殊需求:

// 作用于单个 Action
[LogActionFilter]
[HttpGet("detail/{id}")]
public IActionResult GetDetail(int id) => Ok($"详情:{id}");

// 作用于整个 Controller(所有 Action 生效)
[WrapResponseFilter]
public class ProductController : ControllerBase { ... }

2. 全局注册(作用于所有 Action)

Program.cs 中通过 AddControllers 全局注册,适用于通用规则(如全局异常处理、统一响应包装):

var builder = WebApplication.CreateBuilder(args);

// 添加控制器并注册全局过滤器
builder.Services.AddControllers(options =>
{
    options.Filters.Add<GlobalExceptionFilter>(); // 全局异常处理
    options.Filters.Add<WrapResponseFilter>();    // 统一响应包装
    options.Filters.Add<LogActionFilter>();       // 全局请求日志
});

3. 依赖注入注册(推荐)

若过滤器需要依赖其他服务(如 ILogger、数据库上下文),需先注册过滤器为服务,再全局添加:

// 1. 注册过滤器为作用域服务(Scoped:每个请求创建一个实例)
builder.Services.AddScoped<LogActionFilter>();
builder.Services.AddScoped<GlobalExceptionFilter>();

// 2. 全局添加过滤器(通过类型引用,支持依赖注入)
builder.Services.AddControllers(options =>
{
    options.Filters.Add<LogActionFilter>();
    options.Filters.Add<GlobalExceptionFilter>();
});

四、过滤器选型指南:按需选择不踩坑

过滤器类型 核心用途 关键场景 注意事项
AuthorizationFilter 权限验证 登录校验、角色 / 权限控制、接口白名单 执行最早,失败直接终止请求
ResourceFilter 性能优化、资源管理 响应缓存、请求限流、非线程安全资源管理 模型绑定前执行,可跳过 Action 执行
ActionFilter 业务逻辑增强、日志记录 接口日志、参数校验、数据预处理 依赖模型绑定,可修改 Action 输入输出
ExceptionFilter 异常捕获与统一处理 全局异常日志、错误响应格式化 仅处理未捕获异常,需标记 ExceptionHandled = true
ResultFilter 响应格式化、结果包装 统一响应格式、响应头添加、数据脱敏 仅处理成功的 IActionResult,不处理异常

五、总结

.NET Core Web API 的过滤器体系覆盖了请求处理的全生命周期,通过内置过滤器(如 [Authorize][ResponseCache])可快速实现通用需求,通过自定义过滤器可满足复杂业务场景。合理使用过滤器能显著提升代码复用性和可维护性,让开发者更专注于核心业务逻辑。

建议在实际项目中:

  1. 全局注册 GlobalExceptionFilterWrapResponseFilter,统一异常处理和响应格式;

  2. 对敏感接口使用 [Authorize] 进行权限控制;

  3. 对高频访问的公开接口使用 [ResponseCache] 提升性能;

  4. 通过自定义 ActionFilter 处理接口日志、参数校验等通用逻辑。