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

ActionFilterAttribute搭配Swashbuckle IOperationFilter后失效问题求助

问题原因

你的MandatoryHeaderOperationFilter中使用GetCustomAttributes(true)实例化了MandatoryHeaderAttribute的实例,Swagger启动时的文档生成流程会遍历所有Action并多次实例化该Attribute,这干扰了ASP.NET Core过滤器系统对原Action上标记的Attribute实例的执行逻辑,导致ActionFilter失效。

解决方案

方案1:修改OperationFilter,避免实例化Attribute

调整OperationFilter获取头信息的方式,通过CustomAttributeData读取属性配置,不直接实例化MandatoryHeaderAttribute,彻底规避冲突:

using Microsoft.AspNetCore.Mvc.Controllers;
using Microsoft.OpenApi.Models;
using Swashbuckle.AspNetCore.SwaggerGen;
using System.Reflection;

namespace MyProject.Filters;

public class MandatoryHeaderOperationFilter : IOperationFilter
{
    public void Apply(OpenApiOperation operation, OperationFilterContext context)
    {
        var actionDescriptor = context.ApiDescription.ActionDescriptor as ControllerActionDescriptor;
        if (actionDescriptor == null)
        {
            return;
        }

        operation.Parameters ??= new List<OpenApiParameter>();

        // 通过属性元数据获取配置,不实例化Attribute
        var mandatoryHeaderAttrs = actionDescriptor.MethodInfo.GetCustomAttributesData()
            .Where(attr => attr.AttributeType == typeof(MandatoryHeaderAttribute));

        foreach (var attrData in mandatoryHeaderAttrs)
        {
            if (attrData.ConstructorArguments.FirstOrDefault().Value is string headerName)
            {
                operation.Parameters.Add(new OpenApiParameter
                {
                    Name = headerName,
                    In = ParameterLocation.Header,
                    Required = true,
                    Description = $"必填请求头:{headerName}"
                });
            }
        }
    }
}

方案2:优化ActionFilter的错误处理(推荐)

原代码抛出Exception会返回500服务器错误,不符合REST规范,改为返回400 Bad Request更合理:

using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Filters;

namespace MyProject.Filters;

public class MandatoryHeaderAttribute : ActionFilterAttribute
{
    private readonly string _headerName;

    public MandatoryHeaderAttribute(string headerName)
    {
        _headerName = headerName;
    }

    public string HeaderName => _headerName;

    public override void OnActionExecuting(ActionExecutingContext context)
    {
        if (!context.HttpContext.Request.Headers.TryGetValue(HeaderName, out var headerValue) || string.IsNullOrEmpty(headerValue))
        {
            context.Result = new BadRequestObjectResult(new
            {
                Message = $"缺少必填请求头:{HeaderName}",
                RequiredHeader = HeaderName
            });
            return; // 终止后续流程,直接返回错误
        }

        base.OnActionExecuting(context);
    }
}
验证步骤
  1. 替换代码后重启项目
  2. Swagger UI会自动显示对应必填头字段
  3. 发送缺少头的请求,会触发校验并返回400错误
  4. 携带正确头的请求可正常执行接口逻辑

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.14 09:43:09