如何为同一200OK状态码配置多个响应类型并在Swagger UI正常展示
同一状态码多响应类型展示方案
原生[ProducesResponseType]特性针对同一状态码重复声明时,Swagger默认只会保留最后一个配置的返回类型。要实现多返回类型展示需要用到OpenAPI 3.0提供的oneOf语法,两种常见实现方案如下:
方案1:自定义特性 + Swagger过滤器(无第三方依赖)
该方案不需要引入额外NuGet包,适配所有支持OpenAPI 3.0的Swashbuckle版本。
步骤1:定义支持重复声明的多响应特性
[AttributeUsage(AttributeTargets.Method, AllowMultiple = true)] public class MultipleProducesResponseTypeAttribute : Attribute { public Type ResponseType { get; } public int StatusCode { get; } public MultipleProducesResponseTypeAttribute(Type responseType, int statusCode) { ResponseType = responseType; StatusCode = statusCode; } }
步骤2:实现Swagger操作过滤器
过滤器负责读取自定义特性,将多个返回类型注入到对应状态码的oneOf配置中:
using Microsoft.OpenApi.Models; using Swashbuckle.AspNetCore.SwaggerGen; using System.Reflection; public class MultipleResponseTypesFilter : IOperationFilter { public void Apply(OpenApiOperation operation, OperationFilterContext context) { var multiRespAttrs = context.MethodInfo .GetCustomAttributes<MultipleProducesResponseTypeAttribute>() .GroupBy(attr => attr.StatusCode); foreach (var statusGroup in multiRespAttrs) { var statusCode = statusGroup.Key.ToString(); if (!operation.Responses.TryGetValue(statusCode, out var response)) { response = new OpenApiResponse(); operation.Responses.Add(statusCode, response); } var jsonContent = response.Content.TryGetValue("application/json", out var content) ? content : new OpenApiMediaType(); jsonContent.Schema = new OpenApiSchema { OneOf = statusGroup.Select(attr => context.SchemaRepository.TryLookupByType(attr.ResponseType, out var schema) ? schema : context.SchemaGenerator.GenerateSchema(attr.ResponseType, context.SchemaRepository) ).ToList() }; response.Content["application/json"] = jsonContent; } } }
步骤3:注册过滤器到Swagger配置
在Program.cs(或Startup.cs)的Swagger服务注册逻辑中添加过滤器:
builder.Services.AddSwaggerGen(options => { // 你原有Swagger配置 options.OperationFilter<MultipleResponseTypesFilter>(); });
步骤4:修改Action的特性声明
将原有重复的200状态码ProducesResponseType替换为自定义特性:
[HttpGet("{id}")] [AllowAnonymous] [MultipleProducesResponseType(typeof(PublicDto), StatusCodes.Status200OK)] [MultipleProducesResponseType(typeof(PrivateDto), StatusCodes.Status200OK)] [ProducesResponseType(typeof(string), StatusCodes.Status403Forbidden)] [ProducesResponseType(typeof(string), StatusCodes.Status404NotFound)] public async Task<IActionResult> GetUser(string id) { // 原有业务逻辑保持不变 }
方案2:使用OneOf泛型类型(代码更简洁)
如果接受引入轻量级第三方包,Swashbuckle.AspNetCore 6.0+ 原生支持识别OneOf类型,自动生成oneOf配置。
步骤1:安装OneOf NuGet包
Install-Package OneOf
步骤2:修改Action的响应类型声明
直接将200状态码的返回类型设置为OneOf<PublicDto, PrivateDto>即可:
[HttpGet("{id}")] [AllowAnonymous] [ProducesResponseType(typeof(OneOf<PublicDto, PrivateDto>), StatusCodes.Status200OK)] [ProducesResponseType(typeof(string), StatusCodes.Status403Forbidden)] [ProducesResponseType(typeof(string), StatusCodes.Status404NotFound)] public async Task<IActionResult> GetUser(string id) { // 原有业务逻辑保持不变 }
两种方案配置完成后,Swagger UI的200响应区域会出现下拉选择框,可切换查看PublicDto和PrivateDto的完整Schema定义。
内容的提问来源于stack exchange,提问作者Mateech
相关产品推荐
相关产品推荐

