I recently upgraded my webapi to .NET 8. As I test my controller, the ApiVersion attribute is not working in the swagger page.
[ApiVersion("1.0")]
[Route("v{version:apiVersion}/api/[controller]")]
[ApiController]
[Authorize]
public class SubscriptionController(ISubscriptionDataService subscriptionDataService,
IConfigurationService configurationService) : ControllerBase
In the swagger page, the version is not being filled in by default as it was in .NET 7.
Previously, with the default template weatherforecast controller, the behavior was filled in by default.
The code for that controller was as shown.
[ApiVersion("1.0")]
[Route("v{version:apiVersion}/api/[controller]")]
[ApiController]
[Authorize]
public class WeatherForecastController : ControllerBase
In the Program.cs, the following is added to perform the versioning.
private static void AddApiVersioning(IServiceCollection services)
{
services.AddApiVersioning(options =>
{
options.AssumeDefaultVersionWhenUnspecified = false;
options.ReportApiVersions = false;
});
services.AddVersionedApiExplorer(options =>
{
options.GroupNameFormat = "'v'VVV";
options.SubstituteApiVersionInUrl = true;
});
}
Edit 1
As a result of the following deprecations below, the way this was done needs to change.
Microsoft.AspNetCore.Mvc.Versioning -> Asp.Versioning.Mvc Microsoft.AspNetCore.Mvc.Versioning.ApiExplorer -> Asp.Versioning.Mvc.ApiExplore
In Program.cs, the following needs to be done:
builder.Services.AddEndpointsApiExplorer();
builder.Services.AddSwaggerGen();
builder.Services.AddApiVersioning(options =>
{
options.DefaultApiVersion = new ApiVersion(1, 0);
options.AssumeDefaultVersionWhenUnspecified = false;
options.ReportApiVersions = false;
}).AddApiExplorer(options =>
{
options.GroupNameFormat = "'v'VVV";
options.SubstituteApiVersionInUrl=true;
});
var app = builder.build();
app.UseSwagger();
app.UseSwaggerUI(options =>
{
var descriptions = app.DescribeApiVersions();
foreach (var description in descriptions)
{
var url = $"/swagger/{description.GroupName}/swagger.json";
var name = description.GroupName.ToUpperInvariant();
options.SwaggerEndpoint(url, name);
}
});
In the controller, the [ApiVersion("1.0")] attribute should be replaced with [Asp.Versioning.ApiVersion("1.0")].
This works in the generated Microsoft webapi template, but still fails (i.e. having to enter the version) if using other swagger attributes and having other middlewares.
Edit 2
After much experimentation, it seems like multiple routes at both the class level and method level no longer work, even in the Microsoft Test Project.
Not Working in Swagger
using Microsoft.AspNetCore.Mvc;
namespace webapitest.Controllers;
[Asp.Versioning.ApiVersion("1.0")]
[Route("v{version:apiVersion}/api/[controller]")]
[ApiController]
public class WeatherForecastController : ControllerBase
{
private static readonly string[] Summaries = new[]
{
"Freezing", "Bracing", "Chilly", "Cool", "Mild", "Warm", "Balmy", "Hot", "Sweltering", "Scorching"
};
[HttpGet]
[Route(("/Weather"))]
public IEnumerable<WeatherForecast> Get()
{
return Enumerable.Range(1, 5).Select(index => new WeatherForecast
{
Date = DateOnly.FromDateTime(DateTime.Now.AddDays(index)),
TemperatureC = Random.Shared.Next(-20, 55),
Summary = Summaries[Random.Shared.Next(Summaries.Length)]
})
.ToArray();
}
}
Working in Swagger
using Microsoft.AspNetCore.Mvc;
namespace webapitest.Controllers;
[Asp.Versioning.ApiVersion("1.0")]
[ApiController]
public class WeatherForecastController : ControllerBase
{
private static readonly string[] Summaries = new[]
{
"Freezing", "Bracing", "Chilly", "Cool", "Mild", "Warm", "Balmy", "Hot", "Sweltering", "Scorching"
};
[HttpGet]
[Route(("v{version:apiVersion}/api/[controller]/Weather"))]
public IEnumerable<WeatherForecast> Get()
{
return Enumerable.Range(1, 5).Select(index => new WeatherForecast
{
Date = DateOnly.FromDateTime(DateTime.Now.AddDays(index)),
TemperatureC = Random.Shared.Next(-20, 55),
Summary = Summaries[Random.Shared.Next(Summaries.Length)]
})
.ToArray();
}
}
Would anyone understand why these do not work anymore?