147 lines
4.2 KiB
C#
147 lines
4.2 KiB
C#
using Asp.Versioning;
|
|
using Asp.Versioning.ApiExplorer;
|
|
using Microsoft.AspNetCore.Mvc.ApiExplorer;
|
|
using Microsoft.AspNetCore.Mvc.ModelBinding;
|
|
using Microsoft.Extensions.Options;
|
|
using Microsoft.OpenApi.Models;
|
|
using Swashbuckle.AspNetCore.SwaggerGen;
|
|
using System.Text;
|
|
using System.Text.Json;
|
|
|
|
namespace Sufi.Demo.PeopleDirectory.UI.Server.Extensions
|
|
{
|
|
/// <summary>
|
|
/// Extension class.
|
|
/// </summary>
|
|
public static class ServiceCollectionExtensions
|
|
{
|
|
internal static void RegisterSwagger(this IServiceCollection services)
|
|
{
|
|
services.ConfigureOptions<ConfigureSwaggerGenOptions>();
|
|
services.AddSwaggerGen(c =>
|
|
{
|
|
//TODO - Lowercase Swagger Documents
|
|
//c.DocumentFilter<LowercaseDocumentFilter>();
|
|
//Refer - https://gist.github.com/rafalkasa/01d5e3b265e5aa075678e0adfd54e23f
|
|
|
|
// include all project's xml comments
|
|
var baseDirectory = AppDomain.CurrentDomain.BaseDirectory;
|
|
foreach (var assembly in AppDomain.CurrentDomain.GetAssemblies())
|
|
{
|
|
if (!assembly.IsDynamic)
|
|
{
|
|
var xmlFile = $"{assembly.GetName().Name}.xml";
|
|
var xmlPath = Path.Combine(baseDirectory, xmlFile);
|
|
if (File.Exists(xmlPath))
|
|
{
|
|
c.IncludeXmlComments(xmlPath);
|
|
}
|
|
}
|
|
}
|
|
|
|
c.OperationFilter<SwaggerDefaultValues>();
|
|
})
|
|
.AddApiVersioning(config =>
|
|
{
|
|
config.DefaultApiVersion = new ApiVersion(1, 0);
|
|
config.AssumeDefaultVersionWhenUnspecified = true;
|
|
config.ApiVersionReader = new UrlSegmentApiVersionReader();
|
|
})
|
|
.AddApiExplorer(options =>
|
|
{
|
|
options.GroupNameFormat = "'v'VVV";
|
|
options.SubstituteApiVersionInUrl = true;
|
|
});
|
|
}
|
|
}
|
|
|
|
internal class ConfigureSwaggerGenOptions(IApiVersionDescriptionProvider provider) : IConfigureOptions<SwaggerGenOptions>
|
|
{
|
|
public void Configure(SwaggerGenOptions options)
|
|
{
|
|
foreach (var description in provider.ApiVersionDescriptions)
|
|
{
|
|
options.SwaggerDoc(description.GroupName, CreateInfoForApiVersion(description));
|
|
}
|
|
}
|
|
|
|
private static OpenApiInfo CreateInfoForApiVersion(ApiVersionDescription description)
|
|
{
|
|
var text = new StringBuilder("This application is for demo purposes by Sufi only.");
|
|
var info = new OpenApiInfo
|
|
{
|
|
Title = "Sufi.Demo.App",
|
|
Version = description.ApiVersion.ToString(),
|
|
License = new OpenApiLicense
|
|
{
|
|
Name = "MIT License",
|
|
Url = new Uri("https://opensource.org/licenses/MIT")
|
|
}
|
|
};
|
|
|
|
if (description.IsDeprecated)
|
|
{
|
|
text.Append("This Api version has been deprecated.");
|
|
}
|
|
|
|
if (description.SunsetPolicy is SunsetPolicy policy && policy.Date is DateTimeOffset when)
|
|
{
|
|
text.Append(" The Api will be sunset on ")
|
|
.Append(when.Date.ToShortDateString())
|
|
.Append('.');
|
|
}
|
|
|
|
info.Description = text.ToString();
|
|
|
|
return info;
|
|
}
|
|
}
|
|
|
|
internal 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 &&
|
|
description.DefaultValue is not DBNull &&
|
|
description.ModelMetadata is ModelMetadata modelMetadata)
|
|
{
|
|
var json = JsonSerializer.Serialize(description.DefaultValue, modelMetadata.ModelType);
|
|
parameter.Schema.Default = OpenApiAnyFactory.CreateFromJson(json);
|
|
}
|
|
|
|
parameter.Required |= description.IsRequired;
|
|
}
|
|
}
|
|
}
|
|
}
|