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

ASP.NET Core控制器SwaggerResponse特性优化方案咨询

ASP.NET Core 精简Swagger响应特性的可行方案

一、自定义通用错误响应特性

将重复的4xx错误响应封装为自定义特性,配合Swagger的IOperationFilter批量注入响应配置,控制器方法只需保留特定的成功响应+自定义特性即可。

实现代码

  1. 定义自定义特性:
[AttributeUsage(AttributeTargets.Method | AttributeTargets.Class, Inherited = true, AllowMultiple = false)]
public class CommonSwaggerErrorResponsesAttribute : Attribute { }
  1. 编写配套的OperationFilter:
public class CommonErrorResponsesFilter : IOperationFilter
{
    public void Apply(OpenApiOperation operation, OperationFilterContext context)
    {
        var hasCommonErrorsAttr = context.MethodInfo.GetCustomAttributes(typeof(CommonSwaggerErrorResponsesAttribute), true).Any()
                               || context.ControllerType.GetCustomAttributes(typeof(CommonSwaggerErrorResponsesAttribute), true).Any();

        if (!hasCommonErrorsAttr) return;

        // 添加400响应
        operation.Responses.Add("400", new OpenApiResponse
        {
            Description = "InvalidationError",
            Content = new Dictionary<string, OpenApiMediaType>
            {
                ["application/json"] = new OpenApiMediaType
                {
                    Schema = context.SchemaGenerator.GenerateSchema(typeof(OperationResult<ValidationError>), context.SchemaRepository)
                }
            }
        });

        // 批量添加其他通用错误响应
        var commonErrors = new Dictionary<string, (string Desc, Type ResultType)>
        {
            ["401"] = ("Not Authorised", typeof(OperationResult<Error>)),
            ["403"] = ("No access to execute action", typeof(OperationResult<Error>)),
            ["404"] = ("Not found", typeof(OperationResult<Error>)),
            ["405"] = ("Method not allowed", typeof(OperationResult<Error>)),
            ["415"] = ("Medias type not allowed", typeof(OperationResult<Error>))
        };

        foreach (var (code, errorInfo) in commonErrors)
        {
            if (!operation.Responses.ContainsKey(code))
            {
                operation.Responses.Add(code, new OpenApiResponse
                {
                    Description = errorInfo.Desc,
                    Content = new Dictionary<string, OpenApiMediaType>
                    {
                        ["application/json"] = new OpenApiMediaType
                        {
                            Schema = context.SchemaGenerator.GenerateSchema(errorInfo.ResultType, context.SchemaRepository)
                        }
                    }
                });
            }
        }
    }
}
  1. 注册过滤器并在控制器中使用:
// Program.cs中注册过滤器
builder.Services.AddSwaggerGen(c =>
{
    c.OperationFilter<CommonErrorResponsesFilter>();
});

// 控制器方法简化写法
[SwaggerResponse(200, "Successful", typeof(OperationResult<List<GetAllEventDTO>>))]
[CommonSwaggerErrorResponses]
public async Task<IActionResult> AllEvent()
{
    // 方法实现
}

二、使用API约定(ApiConvention)

定义包含通用响应的API约定,控制器或方法应用约定后自动继承所有配置的响应特性,无需逐个添加。

实现代码

  1. 定义API约定:
public static class DefaultApiConventions
{
    [ProducesResponseType(StatusCodes.Status200OK)]
    [ProducesResponseType(StatusCodes.Status400BadRequest, Type = typeof(OperationResult<ValidationError>))]
    [ProducesResponseType(StatusCodes.Status401Unauthorized, Type = typeof(OperationResult<Error>))]
    [ProducesResponseType(StatusCodes.Status403Forbidden, Type = typeof(OperationResult<Error>))]
    [ProducesResponseType(StatusCodes.Status404NotFound, Type = typeof(OperationResult<Error>))]
    [ProducesResponseType(StatusCodes.Status405MethodNotAllowed, Type = typeof(OperationResult<Error>))]
    [ProducesResponseType(StatusCodes.Status415UnsupportedMediaType, Type = typeof(OperationResult<Error>))]
    public static void Get() { }
}
  1. 在控制器或方法上应用约定:
// 全局应用到控制器
[ApiConventionType(typeof(DefaultApiConventions))]
public class EventController : ControllerBase
{
    // 仅需补充特定的响应描述和DTO类型
    [SwaggerResponse(200, "Successful", typeof(OperationResult<List<GetAllEventDTO>>))]
    public async Task<IActionResult> AllEvent()
    {
        // 方法实现
    }
}

// 或仅在单个方法上应用
[ApiConventionMethod(typeof(DefaultApiConventions), nameof(DefaultApiConventions.Get))]
[SwaggerResponse(200, "Successful", typeof(OperationResult<List<GetAllEventDTO>>))]
public async Task<IActionResult> AllEvent()
{
    // 方法实现
}

三、全局OperationFilter自动注入通用响应

如果所有接口都需要这些通用错误响应,可直接编写全局过滤器,无需在控制器添加任何额外特性,自动为所有接口注入通用4xx响应。

实现代码

public class GlobalErrorResponsesFilter : IOperationFilter
{
    public void Apply(OpenApiOperation operation, OperationFilterContext context)
    {
        var commonErrors = new Dictionary<string, (string Desc, Type ResultType)>
        {
            ["400"] = ("InvalidationError", typeof(OperationResult<ValidationError>)),
            ["401"] = ("Not Authorised", typeof(OperationResult<Error>)),
            ["403"] = ("No access to execute action", typeof(OperationResult<Error>)),
            ["404"] = ("Not found", typeof(OperationResult<Error>)),
            ["405"] = ("Method not allowed", typeof(OperationResult<Error>)),
            ["415"] = ("Medias type not allowed", typeof(OperationResult<Error>))
        };

        foreach (var (code, errorInfo) in commonErrors)
        {
            if (!operation.Responses.ContainsKey(code))
            {
                operation.Responses.Add(code, new OpenApiResponse
                {
                    Description = errorInfo.Desc,
                    Content = new Dictionary<string, OpenApiMediaType>
                    {
                        ["application/json"] = new OpenApiMediaType
                        {
                            Schema = context.SchemaGenerator.GenerateSchema(errorInfo.ResultType, context.SchemaRepository)
                        }
                    }
                });
            }
        }
    }
}

注册过滤器后,控制器方法仅需保留成功响应配置:

[SwaggerResponse(200, "Successful", typeof(OperationResult<List<GetAllEventDTO>>))]
public async Task<IActionResult> AllEvent()
{
    // 方法实现
}

四、封装泛型响应特性(辅助精简)

针对OperationResult<T>的统一格式,封装泛型响应特性,减少重复的typeof声明:

public class SwaggerTypedResponseAttribute : SwaggerResponseAttribute
{
    public SwaggerTypedResponseAttribute(int statusCode, string description, Type dataType) 
        : base(statusCode, description, typeof(OperationResult<>).MakeGenericType(dataType))
    {
    }
}

用法示例:

[SwaggerTypedResponse(200, "Successful", typeof(List<GetAllEventDTO>))]
[SwaggerTypedResponse(400, "InvalidationError", typeof(ValidationError))]
public async Task<IActionResult> AllEvent()
{
    // 方法实现
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.08 15:01:16