How to support multiple swagger files per version/group?

See original GitHub issue

This is a question about best practices to achieve the multi swagger generation per version rather than specific issue with library. Hope someone can help or suggest a work around.

Background:

We have existing Asp.net core service that was using hard coded url versioning such as [Route("api/v1/app")]. We also have certain controller actions separated into groups to generate two different swagger files for Azure APIM. These different operations needed to be billed and managed differently (throttling, quota, etc). We did this by using the group name:

[ApiExplorerSettings(GroupName = "authoring")]
Controller1

[ApiExplorerSettings(GroupName = "session")]
Controller2

and then manually generating matching swagger files

c.SwaggerEndpoint("/swagger/authoring/swagger.json", ... )
c.SwaggerEndpoint("/swagger/session/swagger.json", ... )

Intention

We wanted to add a new version (2.0) to the app to change the urls to more closely align with the Microsoft REST guidelines and wanted to set it up in a scalable way based on the sample https://github.com/microsoft/aspnet-api-versioning/tree/master/samples/aspnetcore/SwaggerSample this is involved changes to AddApiVersioning, AddVersionedApiExplorer, and most notably how the swagger files are generated.

We wanted to preserve the separate of authoring and session operates and hoped to be able to generate two files per version descriptor such as:

foreach (var description in provider.ApiVersionDescriptions)
{
    c.SwaggerEndpoint($"/swagger/authoring-{description.GroupName}/swagger.json", description.GroupName.ToUpperInvariant());
    c.SwaggerEndpoint($"/swagger/session-{description.GroupName}/swagger.json", description.GroupName.ToUpperInvariant());
}

to achieve something like this:

/v1
  /authoring/swagger.json
  /sesssion/swagger.json
/v2
  /authoring/swagger.json
  /session/swagger.json

However there seems to be catch-22 situation. It seems Swagger/Swashbuckle was using group name to associate operations and generate files. If we change group name to be generic ''v'VVV" it means we can no longer use the split the actions/operations between the groups using the [ApiExplorerSettings(GroupName = "session")] attribute since it is one group per version. If we keep the specific groups then we can’t generate them dynamically from the version descriptors because the group names (“authoring” and “session” won’t map to the versions “v1” and “v2” etc.

Our thought was maybe there is some hack like making the version name include a slash such as v{version}/authoring and v{version}/session but that would increase complexity and put us off standard sample for people to help us.

Our only current idea is to go to generic versioning with single swagger per version and sepearate the authoring vs session groups by moving it to a new .net core project. That is a much larger work than we thought as we have to re-architect to share resources across them and thus creating this issue asking for help.

Issue Analytics

  • State:closed
  • Created 4 years ago
  • Reactions:7
  • Comments:43

github_iconTop GitHub Comments

9reactions
tjmcnaboecommented, Dec 3, 2019

I had a similar intent. This will not get you exactly what you want but might be close enough for your needs with a very minimal amount of effort. In Startup.cs change options group format to this if it is not already. : options.GroupNameFormat = “'v’VVV”; The Api Version attribute forces you to use a int for the 1st and 2nd values however for the 3rd you can use alphanumeric so then you can do this: [ApiVersion( “3.0.session” )] [ApiVersion( “3.0.authoring” )] [Route(“api/v{version:apiVersion}/[controller]”)]

which will produce a swagger document for each api per version and routes like this: /api/v3-authoring/Orders/5
/api/v3-session/Orders/{id}

which is very close to what you prob want which is this api/session-v3

Hope that helps

3reactions
borotacommented, Mar 17, 2021

@commonsensesoftware, following on your pointers, I created this IApiDescriptionProvider implementation. It combines [ApiExplorerSettings(GroupName = "GroupName")] with version grouping to achieve the desired result. I am guessing you meant IApiDescriptionProvider not <del>IActionDescriptionProvider</del> above. Things seem to work nicely. I’d appreciate your feedback, if any concerns, etc.

   public class SubgroupDescriptionProvider : IApiDescriptionProvider {
       private readonly ApiExplorerOptions _options;
       public SubgroupDescriptionProvider(IOptions<ApiExplorerOptions> options) => _options = options.Value;
       public int Order => -1; // Execute after DefaultApiVersionDescriptionProvider.OnProvidersExecuted
       public void OnProvidersExecuting(ApiDescriptionProviderContext context) { }
       public void OnProvidersExecuted(ApiDescriptionProviderContext context) {
           var newResults = new List<ApiDescription>();
           foreach (var result in context.Results) {
               var apiVersion = result.GetApiVersion();
               var versionGroupName = apiVersion.ToString(_options.GroupNameFormat, CurrentCulture);
               if (result.GroupName == versionGroupName) {
                   continue; // This is a version grouping, nothing else to do
               }
               // Change [ApiExplorerSettings] group to show as subgroup of version grouping
               result.GroupName = $"{versionGroupName}{SubgroupSeparator}{result.GroupName}";
               // Add the missing version grouping as well
               var newResult = result.Clone();
               newResult.GroupName = versionGroupName;
               newResults.Add(newResult);
           }
           newResults.ForEach(newResult => context.Results.Add(newResult));
       }
   }
services.TryAddEnumerable(Transient<IApiDescriptionProvider, SubgroupDescriptionProvider >());
Read more comments on GitHub >

github_iconTop Results From Across the Web

Generate Multiple Swagger UI for an API Controller in ASP ...
We can simultaneously generate multiple Swagger UI from the same controller and expose one of them publicly for foreign users without ...
Read more >
Managing Multiple Versions of Your API with .NET and ...
After creating this class, you can add the following code to your Program.cs file to use it for configuring Swagger: // Configure the...
Read more >
C# .net core swagger trying to use Multiple API Versions ...
We are trying to separate our API versions into different Swagger documents. We have configured everything as described in ...
Read more >
Building a Documentation Portal For Multiple APIs
The Swagger UI component supports a number of different parameters depending on how we want it to render but for our initial use...
Read more >
API version - SwaggerHub Documentation
All the versions are listed in the dropdown next to the API (domain) name, so you can switch between the versions with just...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found