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
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?
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";
});