Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

[Swagger] FormatGroupName generates an extra ApiVersionDescription #1036

Unanswered
MalekIhdene asked this question in Q&A
Discussion options

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?

You must be logged in to vote

Replies: 1 comment

Comment options

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:

image
  • ORDERS-V1 only contains the 1.0 version of the OrdersController
  • PEOPLE-V1 only contains the 1.0 version of the PeopleController
  • V1 only contains the 1.0 version of the ValuesController

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.

You must be logged in to vote
0 replies
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Category
🙏
Q&A
Labels
None yet
2 participants
Morty Proxy This is a proxified and sanitized view of the page, visit original site.