Skip to content

OpenAPI not working with version interleaving within single controller #1025

Closed
@AnnejanBarelds

Description

@AnnejanBarelds

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

  1. 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.
  2. 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(IEnumerable1 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

Metadata

Metadata

Labels

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions