Last active
September 9, 2020 14:31
-
-
Save vpetkovic/1ba8d9298e4bba411df697d21e379806 to your computer and use it in GitHub Desktop.
[NETCore 3.1]
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using Microsoft.AspNetCore.Mvc.ApiExplorer; | |
using Microsoft.Extensions.DependencyInjection; | |
using Microsoft.Extensions.Options; | |
using Microsoft.OpenApi.Models; | |
using Swashbuckle.AspNetCore.SwaggerGen; | |
namespace SwaggerVersioning | |
{ | |
// <summary> | |
/// Configures the Swagger generation options. | |
/// </summary> | |
/// <remarks> | |
/// <para> | |
/// This allows API versioning to define a Swagger document per API version after the | |
/// <see cref="IApiVersionDescriptionProvider" /> service has been resolved from the service container. | |
/// </para> | |
/// <para>Taken from https://github.com/microsoft/aspnet-api-versioning.</para> | |
/// </remarks> | |
public class ConfigureSwaggerOptions : IConfigureOptions<SwaggerGenOptions> | |
{ | |
#region member vars | |
private readonly IApiVersionDescriptionProvider _provider; | |
#endregion | |
#region constructors and destructors | |
/// <summary> | |
/// Initializes a new instance of the <see cref="ConfigureSwaggerOptions" /> class. | |
/// </summary> | |
/// <param name="provider"> | |
/// The <see cref="IApiVersionDescriptionProvider">provider</see> used to generate Swagger | |
/// documents. | |
/// </param> | |
public ConfigureSwaggerOptions(IApiVersionDescriptionProvider provider) | |
{ | |
_provider = provider; | |
} | |
#endregion | |
#region explicit interfaces | |
/// <inheritdoc /> | |
public void Configure(SwaggerGenOptions options) | |
{ | |
// add a swagger document for each discovered API version | |
// note: you might choose to skip or document deprecated API versions differently | |
foreach (var description in _provider.ApiVersionDescriptions) | |
{ | |
options.SwaggerDoc(description.GroupName, CreateInfoForApiVersion(description)); | |
} | |
} | |
#endregion | |
#region methods | |
/// <summary> | |
/// Internal implementation for building the Swagger basic config. | |
/// </summary> | |
/// <param name="description">The description object containing the.</param> | |
/// <returns>The generated Open API info.</returns> | |
private static OpenApiInfo CreateInfoForApiVersion(ApiVersionDescription description) | |
{ | |
var info = new OpenApiInfo | |
{ | |
Title = "Title", | |
Version = description.ApiVersion.ToString(), | |
Description = @"", | |
}; | |
if (description.IsDeprecated) | |
{ | |
info.Description += @"<p><strong><span style=""color:white;background-color:red"">VERSION IS DEPRECATED</span></strong></p>"; | |
} | |
return info; | |
} | |
#endregion | |
} | |
// Add security lock for individual methods that require authorization | |
public class SecurityRequirementsOperationFilter : IOperationFilter | |
{ | |
public void Apply(OpenApiOperation operation, OperationFilterContext context) | |
{ | |
var authAttributes = context.MethodInfo.DeclaringType.GetCustomAttributes(true) | |
.Union(context.MethodInfo.GetCustomAttributes(true)) | |
.OfType<AuthorizeAttribute>(); | |
var allowAnonymousAttributes = context.MethodInfo.DeclaringType.GetCustomAttributes(true) | |
.Union(context.MethodInfo.GetCustomAttributes(true)) | |
.OfType<AllowAnonymousAttribute>(); | |
if (authAttributes.Any() && !allowAnonymousAttributes.Any()) | |
{ | |
operation.Security.Add(new OpenApiSecurityRequirement() | |
{ | |
{ | |
new OpenApiSecurityScheme | |
{ | |
Reference = new OpenApiReference | |
{ | |
Type = ReferenceType.SecurityScheme, | |
Id = "Bearer" | |
}, | |
Scheme = "OAuth2", | |
Name = "Bearer", | |
In = ParameterLocation.Header, | |
}, new List<string>() | |
} | |
}); | |
//operation.Responses.Add("401", new OpenApiResponse { Description = "Unauthorized" }); | |
//operation.Responses.Add("403", new OpenApiResponse { Description = "Forbidden" }); | |
} | |
} | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
public void ConfigureServices(IServiceCollection services) | |
{ | |
#region API Versioning | |
services.AddApiVersioning(o => | |
{ | |
o.AssumeDefaultVersionWhenUnspecified = true; | |
o.DefaultApiVersion = new ApiVersion(1, 0); | |
// reporting api versions will return the headers "api-supported-versions" and "api-deprecated-versions" | |
o.ReportApiVersions = true; | |
}); | |
services.AddVersionedApiExplorer( | |
options => | |
{ | |
// add the versioned api explorer, which also adds IApiVersionDescriptionProvider service | |
// note: the specified format code will format the version as "'v'major[.minor][-status]" | |
options.GroupNameFormat = "'v'VVV"; | |
// note: this option is only necessary when versioning by url segment. the SubstitutionFormat | |
// can also be used to control the format of the API version in route templates | |
options.SubstituteApiVersionInUrl = true; | |
}); | |
#endregion | |
#region API Documentation (Swagger) | |
services.AddTransient<IConfigureOptions<SwaggerGenOptions>, ConfigureSwaggerOptions>(); | |
services.AddSwaggerGen( | |
options => | |
{ | |
options.OperationFilter<SecurityRequirementsOperationFilter>(); | |
// integrate xml comments | |
var xmlFile = $"{Assembly.GetExecutingAssembly().GetName().Name}.xml"; | |
var xmlPath = Path.Combine(AppContext.BaseDirectory, xmlFile); | |
options.IncludeXmlComments(xmlPath); | |
}); | |
#endregion | |
} | |
public void Configure(IApplicationBuilder app, IWebHostEnvironment env) | |
{ | |
app.UseSwagger(); | |
app.UseSwaggerUI(c => | |
{ | |
c.SwaggerEndpoint("/swagger/v1/swagger.json", "API V1"); | |
c.SwaggerEndpoint("/swagger/v2/swagger.json", "API V2"); | |
c.RoutePrefix = "docs"; | |
c.InjectStylesheet("/swagger/ui/custom.css"); | |
}); | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using Microsoft.OpenApi.Models; | |
using Swashbuckle.AspNetCore.SwaggerGen; | |
using System.Linq; | |
namespace SwaggerVersioning | |
{ | |
public class SwaggerVersioning | |
{ | |
public class RemoveVersionFromParameter : IOperationFilter | |
{ | |
public void Apply(OpenApiOperation operation, OperationFilterContext context) | |
{ | |
var versionParameter = operation.Parameters.Single(p => p.Name == "version"); | |
operation.Parameters.Remove(versionParameter); | |
} | |
} | |
public class ReplaceVersionWithExactValueInPath : IDocumentFilter | |
{ | |
// https://stackoverflow.com/questions/60563647/migrate-code-2-0-to-3-1-core-code-then-swagger-api-versing-not-working | |
public void Apply(OpenApiDocument swaggerDoc, DocumentFilterContext context) | |
{ | |
var paths = new OpenApiPaths(); | |
foreach (var path in swaggerDoc.Paths) | |
{ | |
paths.Add(path.Key.Replace("v{version}", swaggerDoc.Info.Version), path.Value); | |
} | |
swaggerDoc.Paths = paths; | |
} | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment