You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

.NET 6 WebAPI:如何让Action过滤器在[ApiController]返回400前执行

确保自定义过滤器在[ApiController]之前执行的两种方案

在.NET 6中,[ApiController]属性会自动注入一个ModelStateInvalidFilter(负责验证失败时返回HTTP 400的过滤器),它的默认执行顺序(Order)为-2000,且属于ActionFilter类型。要让你的日志过滤器优先执行,有两种直接可行的方案:

方案一:利用ResourceFilter的天然优先级

过滤器的执行顺序规则是:ResourceFilter > ActionFilter > ExceptionFilter,而[ApiController]的验证逻辑是通过ActionFilter实现的。因此只需将日志过滤器改为实现IAsyncResourceFilter(异步)或IResourceFilter(同步),就能天然在ApiController的验证逻辑之前执行,无需调整Order数值。

代码示例

自定义日志过滤器:

public class ValidationLoggingFilter : IAsyncResourceFilter
{
    private readonly ILogger<ValidationLoggingFilter> _logger;

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

    public async Task OnResourceExecutionAsync(ResourceExecutingContext context, ResourceExecutionDelegate next)
    {
        // 提前检查模型验证状态并记录日志
        if (!context.ModelState.IsValid)
        {
            var errorMessages = context.ModelState.Values
                .SelectMany(v => v.Errors)
                .Select(e => e.ErrorMessage);
            
            _logger.LogWarning("用户请求验证失败:{Errors}", string.Join("; ", errorMessages));
        }

        // 继续执行后续流程(包括ApiController的验证逻辑)
        await next();
    }
}

在Program.cs中注册过滤器:

var builder = WebApplication.CreateBuilder(args);

// 添加控制器并注册自定义过滤器
builder.Services.AddControllers(options =>
{
    options.Filters.Add<ValidationLoggingFilter>();
});

var app = builder.Build();

// 中间件配置...
app.MapControllers();

app.Run();

方案二:调整ActionFilter的Order值

如果坚持使用ActionFilter类型的过滤器,可以通过实现IOrderedFilter接口,设置一个比-2000更小的Order值(比如-2001),让它的优先级高于ApiController的内置验证过滤器。

代码示例

自定义日志过滤器:

public class ValidationLoggingFilter : IAsyncActionFilter, IOrderedFilter
{
    private readonly ILogger<ValidationLoggingFilter> _logger;

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

    // 设置Order为-2001,比ApiController内置过滤器的-2000更早执行
    public int Order => -2001;

    public async Task OnActionExecutionAsync(ActionExecutingContext context, ActionExecutionDelegate next)
    {
        if (!context.ModelState.IsValid)
        {
            var errorMessages = context.ModelState.Values
                .SelectMany(v => v.Errors)
                .Select(e => e.ErrorMessage);
            
            _logger.LogWarning("用户请求验证失败:{Errors}", string.Join("; ", errorMessages));
        }

        await next();
    }
}

注册方式与方案一一致,全局注册到控制器选项中即可。

额外说明

如果要在单个控制器或Action上添加过滤器,需使用[ServiceFilter(typeof(ValidationLoggingFilter))]代替直接标记[ValidationLoggingFilter]——因为过滤器依赖了ILogger,需要从DI容器中获取实例。

内容的提问来源于stack exchange,提问作者verbalxd

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.15 06:15:37