Swagger UI不显示多API版本但JSON端点正常(ASP.NET Core 8)
ASP.NET Core 8 API版本控制:Swagger UI仅显示v1版本,v2 JSON端点正常
问题现象
已基于Asp.Versioning.Mvc和Asp.Versioning.Mvc.ApiExplorer(v8.1.0)配置API版本控制,v1和v2的JSON端点直接访问均可正常响应,但Swagger UI仅展示v1的API接口,版本选择下拉框未出现v2选项。



相关代码
控制器1(版本1)
[ApiVersion("1.0")] [Route("api/v{version:apiVersion}/[controller]")] [ApiController] public class PostController : Controller { [HttpGet] [MapToApiVersion("1.0")] [Route("{id}")] public IActionResult GetById(int id) { var post = new Post { Id = id, Text = "Hello, world" }; return Ok(post); } }
控制器2(版本2)
[ApiVersion("2.0")] [Route("api/v{version:apiVersion}/[controller]")] [ApiController] public class PostController : Controller { [HttpGet] [MapToApiVersion("2.0")] [Route("{id}")] public IActionResult GetById(int id) { var post = new Post { Id = id, Text = "Hello, universe" }; return Ok(post); } }
Program.cs
public class Program { public static void Main(string[] args) { var builder = WebApplication.CreateBuilder(args); builder.Services.AddControllers(); builder.Services.AddApiVersioning(config => { config.DefaultApiVersion = new ApiVersion(1, 0); config.AssumeDefaultVersionWhenUnspecified = true; config.ReportApiVersions = true; // 响应头添加支持的API版本信息 config.ApiVersionReader = new UrlSegmentApiVersionReader(); // 从URL路径读取版本号 }) .AddApiExplorer(config => { config.GroupNameFormat = "'v'VVV"; // 版本格式 config.SubstituteApiVersionInUrl = true; }); builder.Services.AddSwaggerGen(); builder.Services.ConfigureOptions<ConfigureSwaggerOptions>(); builder.Services.AddEndpointsApiExplorer(); var app = builder.Build(); app.UseHttpsRedirection(); app.UseAuthorization(); if(app.Environment.IsDevelopment()) { app.UseSwagger(); app.UseSwaggerUI(options => { var provider = app.Services.GetRequiredService<IApiVersionDescriptionProvider>(); foreach (var description in provider.ApiVersionDescriptions) { options.SwaggerEndpoint($"/swagger/{description.GroupName}/swagger.json", description.GroupName.ToUpperInvariant()); } }); } app.MapControllers(); app.Run(); } }
ConfigureSwaggerOptions
public class ConfigureSwaggerOptions : IConfigureNamedOptions<SwaggerGenOptions> { private readonly IApiVersionDescriptionProvider _provider; public ConfigureSwaggerOptions(IApiVersionDescriptionProvider provider) { _provider = provider; } public void Configure(SwaggerGenOptions options) { foreach (var description in _provider.ApiVersionDescriptions) { options.SwaggerDoc(description.GroupName, CreateVersionInfo(description)); } } public void Configure(string? name, SwaggerGenOptions options) { Configure(options); } private OpenApiInfo CreateVersionInfo(ApiVersionDescription description) { var info = new OpenApiInfo { Title = "CwkSocial", Version = description.ApiVersion.ToString(), }; if (description.IsDeprecated) { info.Description = "This API version has been deprecated."; } return info; } }
解决方案
1. 修复同名控制器冲突
C#不允许同一命名空间下存在两个同名类,此处两个PostController导致框架仅加载v1版本的控制器,API版本探测组件无法识别到v2的存在。
解决方式二选一:
- 按命名空间拆分:将两个控制器放在不同的子命名空间下,保持类名不变,路由自动匹配正确路径:
// v1控制器命名空间 namespace YourApp.Controllers.V1; [ApiVersion("1.0")] [Route("api/v{version:apiVersion}/[controller]")] [ApiController] public class PostController : Controller { /* ... */ }// v2控制器命名空间 namespace YourApp.Controllers.V2; [ApiVersion("2.0")] [Route("api/v{version:apiVersion}/[controller]")] [ApiController] public class PostController : Controller { /* ... */ } - 显式指定路由:重命名v2控制器,同时手动指定路由中的控制器名称,避免路由变化:
[ApiVersion("2.0")] [Route("api/v{version:apiVersion}/post")] // 显式写死路由中的post,替代[controller] [ApiController] public class PostV2Controller : Controller { /* ... */ }
2. 调整服务注册顺序
将AddEndpointsApiExplorer移到AddApiVersioning之后、AddSwaggerGen之前,确保API版本探测组件先完成初始化,避免配置覆盖:
builder.Services.AddControllers(); // 先配置API版本控制及API探测 builder.Services.AddApiVersioning(config => { config.DefaultApiVersion = new ApiVersion(1, 0); config.AssumeDefaultVersionWhenUnspecified = true; config.ReportApiVersions = true; config.ApiVersionReader = new UrlSegmentApiVersionReader(); }) .AddApiExplorer(config => { config.GroupNameFormat = "'v'VVV"; config.SubstituteApiVersionInUrl = true; }); // 移到此处,确保API版本探测完成后再初始化端点探测 builder.Services.AddEndpointsApiExplorer(); builder.Services.AddSwaggerGen(); builder.Services.ConfigureOptions<ConfigureSwaggerOptions>();
3. 验证效果
重启应用后,Swagger UI的版本下拉框会同时显示v1和v2选项,两个版本的API文档均可正常访问。
内容的提问来源于stack exchange,提问作者Cristian Quesada
相关产品推荐
相关产品推荐

