Description
Is there an existing issue for this?
- I have searched the existing issues
Describe the bug
Hi,
Starting note: this issue describes 2 bugs (or at least unexpected behaviors) because I can imagine that they are related. If I need to split them up into separate issues, just let me know.
It appears that generating OpenAPI specifications breaks when doing version interleaving within a single controller, where not all actions are explicitly mapped. So a controller decorated with multiple ApiVersion attributes, and two actions on the same path where only one of these actions is decorated with MapToApiVersion, will break the OpenAPI spec for the explicitly mapped version. Actually calling the actions works as expected; it's just the OpenAPI generation that breaks.
Also, is it expected that the OpenAPI specs do no respect the ApiVersionSelector? If I use LowestImplementedApiVersionSelector, I can omit the api-version (which is expected), but the generated OpenAPI spec indicates that api-version is required.
Expected Behavior
With regards to the breaking API spec: I would expect that interleaving versions within a single controller, when done according to the wiki, does not break OpenAPI. A valid outcome would be that the wiki needs to be updated to reflect that implicit version interleaving is not compatible with OpenAPI.
With regards to OpenAPI and the ApiVersionSelector: I would expect that OpenAPI does not require a parameter that is not, in fact, required.
Steps To Reproduce
With regards to the breaking API spec: adding the controller from the samples (see below) to the OpenApiExample, breaks the OpenAPI spec for version 3.0.
[ApiVersion( 2.0 )]
[ApiVersion( 3.0 )]
[ApiController]
[Route( "api/helloworld" )]
public class HelloWorld2Controller : ControllerBase
{
[HttpGet]
public string Get() => "Hello world v2.0!";
[HttpGet, MapToApiVersion( 3.0 )]
public string GetV3() => "Hello world v3.0!";
}
With regards to OpenAPI and the ApiVersionSelector: given a project where the DefaultApiVersion is not touched (so is 1.0); AssumeDefaultVersionWhenUnspecified = true; and the ApiVersionSelector is set to LowestImplementedApiVersionSelector , what I observe is
- A controller that implements 1.0 and 2.0, and has two actions on the same path, where one of them is mapped to 1.0 and the other to 2.0, the OpenAPI spec correctly does not mark the api-version parameter as required for 1.0.
- However, when the same controller implements 2.0 and 3.0, and the two actions are mapped accordingly, api-version is required for both versions in the OpenAPI spec - even though an actual call to the path without a version specified correctly maps to 2.0.
Exceptions (if any)
Exception for the broken OpenAPI spec:
Swashbuckle.AspNetCore.SwaggerGen.SwaggerGeneratorException: Conflicting method/path combination "GET api/helloworld" for actions - ApiVersioning.Examples.HelloWorld2Controller.Get (OpenApiExample),ApiVersioning.Examples.HelloWorld2Controller.GetV3 (OpenApiExample). Actions require a unique method/path combination for Swagger/OpenAPI 3.0. Use ConflictingActionsResolver as a workaround
at Swashbuckle.AspNetCore.SwaggerGen.SwaggerGenerator.GenerateOperations(IEnumerable1 apiDescriptions, SchemaRepository schemaRepository) at Swashbuckle.AspNetCore.SwaggerGen.SwaggerGenerator.GeneratePaths(IEnumerable
1 apiDescriptions, SchemaRepository schemaRepository)
at Swashbuckle.AspNetCore.SwaggerGen.SwaggerGenerator.GetSwaggerDocumentWithoutFilters(String documentName, String host, String basePath)
at Swashbuckle.AspNetCore.SwaggerGen.SwaggerGenerator.GetSwaggerAsync(String documentName, String host, String basePath)
at Swashbuckle.AspNetCore.Swagger.SwaggerMiddleware.Invoke(HttpContext httpContext, ISwaggerProvider swaggerProvider)
at Microsoft.AspNetCore.Authentication.AuthenticationMiddleware.Invoke(HttpContext context)
at Microsoft.AspNetCore.Diagnostics.DeveloperExceptionPageMiddlewareImpl.Invoke(HttpContext context)
.NET Version
7.0.400
Anything else?
No response