Initial code commit.

This commit is contained in:
2026-02-03 10:44:31 +08:00
parent 8927c5ae0e
commit d69fe2cc1f
99 changed files with 10839 additions and 0 deletions

View File

@@ -0,0 +1,146 @@
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;
}
}
}
}