我正在使用swagger生成我的API文档,现在我需要对一些终端点进行版本控制。
因此,我配置了swagger来识别我的版本并正确映射终端点。但是,swagger会失去追踪,因为我在不同的命名空间中使用了相同的类名,我收到这个错误:
Conflicting method/path combination "GET api/v1/A" for actions - TesteSwagger.Controllers.B.AController.x (TesteSwagger),TesteSwagger.Controllers.A.AController.x (TesteSwagger). Actions require a unique method/path combination for Swagger/OpenAPI 3.0. Use ConflictingActionsResolver as a workaround
以下是我制作的示例以复现它:
我所有的 swagger 包都是 6.0.2 版本。
我正在使用 .Net Core 3.1 WebApi 默认空模板。
Startup.cs:
public void ConfigureServices(IServiceCollection services)
{
services.AddControllers();
services.AddApiVersioning(
options =>
{
options.ReportApiVersions = true;
options.DefaultApiVersion = new ApiVersion(1, 0);
options.AssumeDefaultVersionWhenUnspecified = true;
});
services.AddVersionedApiExplorer(
options =>
{
options.GroupNameFormat = "'v'VVV";
options.SubstituteApiVersionInUrl = true;
});
services.AddTransient<IConfigureOptions<SwaggerGenOptions>, ConfigureSwaggerOptions>();
services.AddSwaggerGen(options =>
{
options.CustomSchemaIds(x => x.FullName);
options.DescribeAllParametersInCamelCase();
options.OperationFilter<SwaggerDefaultValues>();
options.ResolveConflictingActions(apiDescriptions => apiDescriptions.First());
});
}
public void Configure(IApplicationBuilder app, IWebHostEnvironment env, IApiVersionDescriptionProvider provider)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
app.UseSwagger()
.UseSwaggerUI(c =>
{
c.DisplayRequestDuration();
foreach (var description in provider.ApiVersionDescriptions)
{
c.SwaggerEndpoint($"/swagger/{description.GroupName}/swagger.json",
description.GroupName.ToUpperInvariant());
}
});
app.UseHttpsRedirection();
app.UseRouting();
app.UseAuthorization();
app.UseEndpoints(endpoints =>
{
endpoints.MapControllers();
});
}
Swagger 默认配置类:
public class SwaggerDefaultValues : IOperationFilter
{
public void Apply(OpenApiOperation operation, OperationFilterContext context)
{
}
}
public class ConfigureSwaggerOptions : IConfigureOptions<SwaggerGenOptions>
{
public void Configure(SwaggerGenOptions options)
{
}
}
控制器(v1):
namespace TesteSwagger.Controllers.A
{
[ApiController, ApiVersion("1.0")]
[Route("api/v{version:apiVersion}/[controller]")]
public class AController : ControllerBase
{
[HttpPost]
[ProducesResponseType(typeof(B), (int)HttpStatusCode.OK)]
public IActionResult x(A a) => Ok(new B());
}
public class A
{
public int Foo { get; set; }
}
public class B
{
public int Bar { get; set; }
}
}
B控制器(v2):
namespace TesteSwagger.Controllers.B
{
[ApiController, ApiVersion("2.0")]
[Route("api/v{version:apiVersion}/[controller]")]
public class AController : ControllerBase
{
[HttpPost]
[ProducesResponseType(typeof(B), (int)HttpStatusCode.OK)]
public IActionResult x(A a) => Ok(new B());
}
public class A
{
public int Foo { get; set; }
}
public class B
{
public int Bar { get; set; }
}
}
Swagger的v1 URL可以正常加载,只有当我将其更改为v2时,才会在屏幕上显示此错误:
Fetch error
undefined /swagger/v2/swagger.json
我使用在v1 URL生成的curl进行测试,一切都很顺利,只是swagger无法理解。
// works great
curl -X POST "https://localhost:44312/api/v1/A" -H "accept: text/plain" -H "Content-Type: application/json" -d "{\"foo\":0}"
// works great
curl -X POST "https://localhost:44312/api/v2/A" -H "accept: text/plain" -H "Content-Type: application/json" -d "{\"foo\":0}"
我真的不知道我做错了什么还是Swagger确实不支持这种类型的版本控制。
有什么想法吗?