swaggerswagger-uiasp.net-core-8

Swagger UI Paths Not Displaying Full String When Version 1.0


So I've been trying to get the new versioning stuff working in my .NET 8 API and have got 95% of the way there. There's one hiccup in SwaggerUI.

As background, I want to use the route to do the versioning.

So, examples would be:

/v1.0/temporal/timezones
/v1.1/temporal/timezones

I've installed the following 2 Nuget packages:

Asp.Versioning.Mvc 
Asp.Versioning.Mvc.ApiExplorer

In my controllers, the code is:

[ApiVersion("1.0")]
[Route("v{version:apiVersion}/[controller]")]

In my setup, I have:

builder.Services.AddApiVersioning(options =>
    {
        options.AssumeDefaultVersionWhenUnspecified = true;
        options.DefaultApiVersion = new ApiVersion(1, 0); //same as ApiVersion.Default
        options.ReportApiVersions = true;
        options.ApiVersionReader = new UrlSegmentApiVersionReader();
    })
    .AddMvc()
    .AddApiExplorer(options =>
    {
        options.GroupNameFormat = "'v'VVVV";
        options.SubstituteApiVersionInUrl = true;
    });;

    builder.Services.AddSwaggerGen(swaggerGenOptions =>
    {
        foreach (var openApiInfo in applicationSettings.OpenApiInfoList)
        {
            // iteration 1, name = "v1.0" 
            // iteration 2, name = "v1.1"
            var name = string.Concat(Swagger.Versions.VersionPrefix, openApiInfo.Version);
            swaggerGenOptions.SwaggerDoc(name, openApiInfo);
        }
    }
    

Then in the middleware pipeline:

    app.UseSwagger();

    app.MapControllers();

    app.UseSwaggerUI(swaggerUiOptions =>
    {
        var provider = app.Services.GetRequiredService<IApiVersionDescriptionProvider>();
        
        foreach (var description in provider.ApiVersionDescriptions)
        {
            // iteration 1, description.GroupName = "v1.0" 
            // iteration 2, description.GroupName = "v1.1"              
            swaggerUiOptions.SwaggerEndpoint($"/swagger/{description.GroupName}/swagger.json", description.GroupName.ToUpperInvariant());          
            swaggerUiOptions.DocExpansion(DocExpansion.List);
            swaggerUiOptions.DefaultModelExpandDepth(3);
            swaggerUiOptions.DefaultModelsExpandDepth(0);
        }
    });
    
    

Everything is as I expect except for 1 thing.

When v1.0 is chosen from the version selector dropdownlist at the top right, the urls displayed for each of the endpoints is v1 (not "v1.0") - like this:

/v1/temporal/timezones

enter image description here

I realise that I could probably add a class that implements IDocumentFilter and manually force it to take on the format which I am after. But surely this is a common enough scenario where this not required. I'd be stunned if there was not a setting somewhere which tells the version to behave like a string rather than a number.

The endpoints do work and are reachable by a REST client. This is just a SwaggerUI issue.

Anyone got any ideas?


Solution

  • Try set SubstitutionFormat as below:

    builder.Services.AddApiVersioning(options =>
    {
        options.AssumeDefaultVersionWhenUnspecified = true;
        options.DefaultApiVersion = new ApiVersion(1,1); //same as ApiVersion.Default
        options.ReportApiVersions = true;
        options.ApiVersionReader = new UrlSegmentApiVersionReader();
        
    })
        .AddMvc()
        .AddApiExplorer(options =>
        {
            options.GroupNameFormat = "'v'VVVV";
            options.SubstituteApiVersionInUrl = true;
            options.SubstitutionFormat= "VV";
        }); 
    

    Result: enter image description here