-
Notifications
You must be signed in to change notification settings - Fork 714
[Swagger] FormatGroupName generates an extra ApiVersionDescription #1036
-
I am using the latest version of the ApiExplorer (v7.1) and I am currently attempting to have different swagger documents for different controllers but also have versioning in addition to that.
I have these two controllers:
[ApiVersion("1")]
[Route("api/v{version:apiVersion}/accounts/")]
[ApiExplorerSettings(GroupName = "account")]
public class AccountController : Controller {
...
[ApiVersion("1")]
[Route("api/v{version:apiVersion}/accounts/admin")]
[ApiExplorerSettings(GroupName = "admin")]
public class AdminController : Controller {
...
I define my ApiExplorer as such:
services
.AddApiVersioning(o => { o.AssumeDefaultVersionWhenUnspecified = true; })
.AddMvc()
.AddApiExplorer(options =>
{
options.GroupNameFormat = "'v'V";
options.SubstituteApiVersionInUrl = true;
options.FormatGroupName = (group, version) => $"{group}-{version}";
});
But then, inside of the my Startup.cs
's ConfigureServices
function, I loop through the api versions:
foreach (ApiVersionDescription description in _provider.ApiVersionDescriptions)
{
options.SwaggerDoc(description.GroupName,
new OpenApiInfo
{
Title = _settings.Title,
Version = description.ApiVersion.ToString(),
Description = _settings.Description,
...
And end up with three Swagger documents with group names: account-v1
, admin-v1
and v1
The weird part is that, after that in the Configure
method of the Startup.cs
file, I call UseSwaggerUI
and define my endpoints like the following:
foreach (ApiVersionDescription description in provider.ApiVersionDescriptions.OrderByDescending(x => x.ApiVersion))
{
opt.SwaggerEndpoint($"{description.GroupName}/swagger.json", description.GroupName.ToUpperInvariant());
}
But only my two documents show up in the loop, i.e. account-v1
and admin-v1
.
So in other words, three swagger documents are created but only two of them are linked to endpoints in the UI.
Is this expected behavior?
Beta Was this translation helpful? Give feedback.
All reactions
Replies: 1 comment
-
Your configuration looks correct to me. I configured a similar setup using the OpenAPI example with the following changes:
Added:
[ApiVersion(1.0)] [Route( "api/[controller]" )] public class ValuesController : ControllerBase { [HttpGet] public IActionResult Get() => Ok(); }
Changed:
[ApiVersion( 1.0 )] [ApiVersion( 0.9, Deprecated = true )] [ApiExplorerSettings( GroupName = "Orders" )] [Route( "api/[controller]" )] public class OrdersController : ControllerBase { // omitted for brevity }
[ApiVersion( 1.0 )] [ApiVersion( 0.9, Deprecated = true )] [ApiExplorerSettings( GroupName = "People" )] [Route( "api/v{version:apiVersion}/[controller]" )] public class PeopleController : ControllerBase { // omitted for brevity }
.AddApiExplorer( options => { options.GroupNameFormat = "'v'VVV"; options.SubstituteApiVersionInUrl = true; options.FormatGroupName = ( group, version ) => $"{group}-{version}"; } );
which produces the following:
imageORDERS-V1
only contains the1.0
version of theOrdersController
PEOPLE-V1
only contains the1.0
version of thePeopleController
V1
only contains the1.0
version of theValuesController
Everything else is unchanged. That is what I would expect.
I see that you're still using the older Startup.cs
approach, but I don't think it should matter in this case. You will have gone through the full DI cycle at this point and IApiVersionDescriptionProvider
should produce the correct results. Are you sure there are any APIs in v1
? In theory, it shouldn't be possible for that to happen. I may need a little more context or the world's simplest repro will help. Perhaps the repro steps I used will be helpful to you.
Sidebar
ApiVersioningOptions.AssumeDefaultVersionWhenUnspecified = true
will not what you think it will unless you have more configuration that I'm not seeing. This is a highly abused feature that is only meant for backward compatibility. When you chose to version by URL segment, it virtually has no effect. The only way it can work is if you use Double Route Registration (ex: api/v{ver:apiVersion}/accounts
and api/accounts
). In this case, there is no API version derived from the URL so it will be assumed since it has been configured as allowable. The only other exception would be if you have mixed styles and are moving away from versioning by URL segment (🤞🏽). I'd recommend explicit versions should that be the case. This is the same problem as order/{id}/items
. There is no way to assume or otherwise route to that path without {id}
. The ASP.NET routing system doesn't support that.
Beta Was this translation helpful? Give feedback.