-
Notifications
You must be signed in to change notification settings - Fork 707
Swashbuckle Integration
Although the API explorers for API versioning provide all of the necessary information, there is select information that OpenAPI (formerly Swagger) and Swashbuckle will not wire up for you. This includes iterating through all the available API versions so that they don't have to be imperatively declared and changed one at a time. Fortunately, bridging this gap is really easy to achieve using Swashbuckle's extensibility model. The following are simple IOperationFilter
implementations that leverage the metadata provided by the corresponding API explorer to fill in these gaps.
Remember to add the necessary references to one or both of the following:
public class SwaggerDefaultValues : IOperationFilter
{
public void Apply(
Operation operation,
SchemaRegistry schemaRegistry,
ApiDescription apiDescription )
{
operation.deprecated |= apiDescription.IsDeprecated();
if ( operation.parameters == null )
{
return;
}
foreach ( var parameter in operation.parameters )
{
var description = apiDescription.ParameterDescriptions
.First( p => p.Name == parameter.name );
parameter.description ??= description.Documentation;
parameter.@default ??= description.ParameterDescriptor?.DefaultValue;
}
}
}
Use MultipleApiVersions
to iterate over each ApiDescription
and collate them by their corresponding group. The default group name for each ApiDescription
is the formatted API version that is associated with it.
configuration.EnableSwagger(
"{apiVersion}/swagger",
swagger =>
{
swagger.MultipleApiVersions(
( apiDescription, version ) => apiDescription.GetGroupName() == version,
info =>
{
foreach ( var group in apiExplorer.ApiDescriptions )
{
info.Version( group.Name, $"Example API {group.ApiVersion}" )
.Description( "An example API" );
}
} );
swagger.OperationFilter<SwaggerDefaultValues>();
} )
.EnableSwaggerUi( swagger => swagger.EnableDiscoveryUrlSelector() );
Remember to add the necessary references to one or both of the following:
public class SwaggerDefaultValues : IOperationFilter
{
public void Apply( OpenApiOperation operation, OperationFilterContext context )
{
var apiDescription = context.ApiDescription;
operation.Deprecated |= apiDescription.IsDeprecated();
foreach ( var responseType in context.ApiDescription.SupportedResponseTypes )
{
var responseKey = responseType.IsDefaultResponse
? "default"
: responseType.StatusCode.ToString();
var response = operation.Responses[responseKey];
foreach ( var contentType in response.Content.Keys )
{
if ( !responseType.ApiResponseFormats.Any( x => x.MediaType == contentType ) )
{
response.Content.Remove( contentType );
}
}
}
if ( operation.Parameters == null )
{
return;
}
foreach ( var parameter in operation.Parameters )
{
var description = apiDescription.ParameterDescriptions
.First( p => p.Name == parameter.Name );
parameter.Description ??= description.ModelMetadata?.Description;
if ( parameter.Schema.Default == null && description.DefaultValue != null )
{
var json = JsonSerializer.Serialize(
description.DefaultValue,
description.ModelMetadata.ModelType );
parameter.Schema.Default = OpenApiAnyFactory.CreateFromJson( json );
}
parameter.Required |= description.IsRequired;
}
}
}
We also need a way to tell Swashbuckle about the API versions in the application:
public class ConfigureSwaggerOptions : IConfigureOptions<SwaggerGenOptions>
{
private readonly IApiVersionDescriptionProvider provider;
public ConfigureSwaggerOptions( IApiVersionDescriptionProvider provider ) => this.provider = provider;
public void Configure( SwaggerGenOptions options )
{
foreach ( var description in provider.ApiVersionDescriptions )
{
options.SwaggerDoc(
description.GroupName,
new OpenApiInfo()
{
Title = "Example API",
Description = "An example API",
Version = description.ApiVersion.ToString(),
} );
}
}
}
Now we can put it all together:
var builder = WebApplication.CreateBuilder( args );
builder.Services.AddControllers();
builder.Services.AddApiVersioning().AddMvc().AddApiExplorer();
builder.Services.AddTransient<IConfigureOptions<SwaggerGenOptions>, ConfigureSwaggerOptions>();
builder.Services.AddSwaggerGen( options => options.OperationFilter<SwaggerDefaultValues>() );
var app = builder.Build();
app.UseSwagger();
app.UseSwaggerUI(
options =>
{
foreach ( var description in app.DescribeApiVersions() )
{
options.SwaggerEndpoint(
$"/swagger/{description.GroupName}/swagger.json",
description.GroupName );
}
} );
app.MapControllers();
app.Run();
There are end-to-end examples using API versioning and Swashbuckle:
- ASP.NET Web API
- ASP.NET Core
- Home
- Quick Starts
- Version Format
- Version Discovery
- Version Policies
- How to Version Your Service
- API Versioning with OData
- Configuring Your Application
- Error Responses
- API Documentation
- Extensions and Customizations
- Known Limitations
- FAQ
- Examples