.NET 7中使用ProducesResponseType时Swagger抛出重复schemaId异常
.NET 7 Swagger 中 ProducesResponseType 引发 SchemaId 冲突问题解决
问题场景
使用.NET 7和Swagger构建API并生成文档时,控制器中同时使用两个ProducesResponseType特性指定200状态码的返回类型,但两个返回类型中的Result类重名(分别属于GetBackEndUsers和Login两个不同的静态类),导致Swagger生成文档时抛出SchemaId冲突异常。
冲突的控制器代码
// 存在冲突的代码 [ProducesResponseType(typeof(PaginationResponse<GetBackEndUsers.Result>), 200)] // 与之冲突的代码,二者为不同类且属性不同 [ProducesResponseType(typeof(Login.Result), 200)]
相关类定义
public class PaginationResponse<T> where T : class { public int PageNumber { get; set; } = 1; public int ItemCount { get; set; } = 10; public int TotalRecords { get; set; } public IList<T> Data { get; set; } public PaginationResponse() { Data = new List<T>(); } } public static class GetBackEndUsers { public class Result { public string FirstName { get; set; } = string.Empty; public string LastName { get; set; } = string.Empty; public string? Email { get; set; } = string.Empty; public DateTime CreatedAt { get; set; } } }
抛出的异常信息
InvalidOperationException: Can't use schemaId "$Result" for type "$OctuFit.Application.Features.GetBackEndUsers+Result". The same schemaId is already used for type "$OctuFit.Application.Features.Login+Result"
尝试过的无效方案
以下两种配置会导致请求和响应中的Schema完全消失:
options.CustomSchemaIds(type => type.ToString());
options.CustomSchemaIds( type => type.FullName );
控制器方法示例
[HttpGet] [ProducesResponseType(typeof(PaginationResponse<GetBackEndUsers.Result>), 200)] public async Task<IActionResult> GetBackendUsers([FromQuery] PaginationRequest pagination) { var query = new GetBackEndUsers.Query { PageNumber = pagination.PageNumber, ItemCount = pagination.ItemCount }; var response = await mediator.Send(query); return HandleResponse(response); }
有效解决方案
方案1:全局自定义SchemaId生成规则
通过自定义SchemaId生成逻辑,针对嵌套类拼接外层类名与内层类名,确保每个类型的SchemaId唯一,同时避免Schema消失:
services.AddSwaggerGen(options => { options.CustomSchemaIds(type => { // 处理嵌套类,拼接外层类名+内层类名 if (type.IsNested && type.DeclaringType != null) { return $"{type.DeclaringType.Name}.{type.Name}"; } // 非嵌套类直接使用类型全名,或根据需求简化 return type.FullName ?? type.Name; }); });
方案2:为冲突类单独指定SchemaId
通过SwaggerSchema特性直接给重名的Result类指定唯一的SchemaId,无需全局修改配置:
- 修改
GetBackEndUsers.Result类:
public static class GetBackEndUsers { [SwaggerSchema(SchemaId = "GetBackEndUsersResult")] public class Result { public string FirstName { get; set; } = string.Empty; public string LastName { get; set; } = string.Empty; public string? Email { get; set; } = string.Empty; public DateTime CreatedAt { get; set; } } }
- 修改
Login.Result类:
public static class Login { [SwaggerSchema(SchemaId = "LoginResult")] public class Result { // 类属性定义 } }
内容的提问来源于stack exchange,提问作者DrXSsive
相关产品推荐
相关产品推荐

