using System; using System.IO; using System.Linq; using xCommons.Filters; using xCommons.Constants; using xCommons.Configurations; using Microsoft.AspNetCore.Mvc; using Microsoft.OpenApi.Models; using System.Collections.Generic; using Microsoft.AspNetCore.Builder; using Swashbuckle.AspNetCore.SwaggerUI; using Swashbuckle.AspNetCore.SwaggerGen; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; namespace xCommons.Extensions { public static partial class DIExtensions { /// /// Inject Specific Registered Service from IServiceCollection /// /// /// /// public static T GetRegisteredService(this IServiceCollection source) { // var serviceProvider = source.BuildServiceProvider(); return serviceProvider.GetService(); } /// /// Register App Configuration as a Service /// /// /// public static void AddXAppConfiguration(this IServiceCollection services, IConfiguration configuration) { // var appConfiguration = configuration.GetXAppConfiguration(); services.AddSingleton(appConfiguration); } /// /// Search Assemblies, Extract XML Comments and /// Integrate them inside swagger gen documents ... /// /// public static void IncludeAssembliesXMLComments(this SwaggerGenOptions source) { // // Extract all Exists .xml files ... var basePath = AppContext.BaseDirectory; var xmlFiles = Directory.GetFiles(basePath, "*.xml", SearchOption.TopDirectoryOnly); var assemblies = AppDomain.CurrentDomain.GetAssemblies(); // // Loop through Detected XML Files ... foreach (var xmlFile in xmlFiles) { // try { // // Retrieve file name for Assembly Checking ... var assemblyName = Path.GetFileNameWithoutExtension(xmlFile); // // Try to retrieve Assembly ... var assembly = assemblies .FirstOrDefault(a => a.GetName().Name == assemblyName); if (!assembly.IsNullOrDefault() || File.Exists(Path.Combine(basePath, $"{assemblyName}.dll")) ) { // // Includes Selected XML Comments ... source.IncludeXmlComments(xmlFile); } } catch (Exception ex) { Console.WriteLine($"Warning: Could not include XML comments from {xmlFile}. Error: {ex.Message}"); } } } /// /// Add Required OperationFilters and Authorization Fields to Swagger Options /// /// /// /// /// /// public static void AddXSwaggerGenOptions( this SwaggerGenOptions source, string xmlFilePath = null, bool addRequiredXPoweredFilter = true, bool addXTokenAuthorization = true, bool addDefaultValueFilter = true ) { // if (source.IsNull()) { source = new SwaggerGenOptions(); } // // Add Xml File Path ... if (!xmlFilePath.IsNullOrEmpty()) { source.IncludeXmlComments(xmlFilePath); } // // Include all XML Documents ... source.IncludeAssembliesXMLComments(); // // Handle RequireXPowered Filter ... if (addRequiredXPoweredFilter) { source.OperationFilter(); } // // Add Default Values Filter ... if (addDefaultValueFilter) { source.OperationFilter(); } // // Handle XToken Authorizations ... if (addXTokenAuthorization) { // #region Bearer AccessToken ... // source.AddSecurityDefinition(nameof(XAuthorization.AccessToken), new OpenApiSecurityScheme { In = ParameterLocation.Header, Description = "Bearer token", Type = SecuritySchemeType.ApiKey, Name = XAuthorization.Header }); // source.AddSecurityRequirement(new OpenApiSecurityRequirement { { new OpenApiSecurityScheme { Reference = new OpenApiReference { Id = nameof (XAuthorization.AccessToken), Type = ReferenceType.SecurityScheme } }, Array.Empty () } }); #endregion // #region RefreshToken ... // source.AddSecurityDefinition(nameof(XAuthorization.RefreshToken), new OpenApiSecurityScheme { In = ParameterLocation.Header, Description = "refresh token", Type = SecuritySchemeType.ApiKey, Name = nameof(XAuthorization.RefreshToken) }); // source.AddSecurityRequirement(new OpenApiSecurityRequirement { { new OpenApiSecurityScheme { Reference = new OpenApiReference { Id = nameof (XAuthorization.RefreshToken), Type = ReferenceType.SecurityScheme } }, Array.Empty () } }); #endregion // #region ExpiresAt ... // source.AddSecurityDefinition(nameof(XAuthorization.ExpiresAt), new OpenApiSecurityScheme { In = ParameterLocation.Header, Description = "expires at", Type = SecuritySchemeType.ApiKey, Name = nameof(XAuthorization.ExpiresAt) }); // source.AddSecurityRequirement(new OpenApiSecurityRequirement { { new OpenApiSecurityScheme { Reference = new OpenApiReference { Id = nameof (XAuthorization.ExpiresAt), Type = ReferenceType.SecurityScheme } }, Array.Empty () } }); #endregion } } /// /// Register Swagger /// /// /// /// /// /// /// /// public static void AddXSwagger( this IServiceCollection source, IConfiguration configuration, SwaggerGenOptions settings = null, string xmlFilePath = null, bool addRequiredXPoweredFilter = true, bool addXTokenAuthorization = true, bool addDefaultValueFilter = true ) { // var xSwaggerConfig = configuration.GetXSwaggerConfiguration(); if (xSwaggerConfig.IsNull()) { xSwaggerConfig = new XSwaggerConfiguration(); } // source.AddSingleton(xSwaggerConfig); // #region Prepare SwaggerGenOptions ... if (settings.IsNull()) { settings = new SwaggerGenOptions(); } settings.AddXSwaggerGenOptions( xmlFilePath: xmlFilePath, addDefaultValueFilter: addDefaultValueFilter, addXTokenAuthorization: addXTokenAuthorization, addRequiredXPoweredFilter: addRequiredXPoweredFilter ); #endregion // #region Prepare Swagger Doc ... // // Api Document Section ... var apiDoc = new OpenApiInfo { Title = xSwaggerConfig.Title, Version = xSwaggerConfig.Version, Description = xSwaggerConfig.Description, }; // // Api Document TermsOfUse URL ... if (!xSwaggerConfig.TermsOfServiceUrl.IsNullOrEmpty()) { apiDoc.TermsOfService = new Uri(xSwaggerConfig.TermsOfServiceUrl); } // // Contact Section ... if (!xSwaggerConfig.Contact.IsNull()) { // var apiContact = new OpenApiContact { Name = xSwaggerConfig.Contact.Name, Email = xSwaggerConfig.Contact.Email }; // // Contact URL ... if (!xSwaggerConfig.Contact.Url.IsNullOrEmpty()) { apiContact.Url = new Uri(xSwaggerConfig.Contact.Url); } // apiDoc.Contact = apiContact; } // // License Section ... if (!xSwaggerConfig.License.IsNull()) { // var apiLicense = new OpenApiLicense { Name = xSwaggerConfig.License.Name, }; // // License URL ... if (!xSwaggerConfig.License.Url.IsNullOrEmpty()) { apiLicense.Url = new Uri(xSwaggerConfig.License.Url); } // apiDoc.License = apiLicense; } #endregion // // Register Swagger ... source.AddSwaggerGen( opt => { // opt.UpdateData(settings); // opt.SwaggerDoc("v1", apiDoc); } ); // // Register Swagger Operation Filters ... } /// /// Use Sagger /// /// /// public static void UseXSwagger( this IApplicationBuilder source, SwaggerUIOptions options = null ) { // source.UseSwagger(); // if (options.IsNull()) { source.UseSwaggerUI(); } else { source.UseSwaggerUI(options: options); } } /// /// Add Cross Origin Resource Sharings /// /// /// public static void AddXCors( this IServiceCollection source, IEnumerable allowedOrigins ) { // if (!allowedOrigins.HasChild()) { // Console.WriteLine($"XCommons: there is no provided allowedOrigins, start app without any specific cors, this may be unsecure ..."); // source.AddCors(options => { options.AddPolicy(XPolicy.AllowedOrigins, builder => { builder .AllowAnyOrigin() .AllowAnyHeader() .AllowAnyMethod() .WithExposedHeaders("*"); }); }); // return; } // source.AddCors(options => { options.AddPolicy(XPolicy.AllowedOrigins, builder => { builder .WithOrigins(allowedOrigins.ToArray()) .AllowAnyHeader() .AllowAnyMethod() .AllowCredentials() .WithExposedHeaders("*"); }); }); } /// /// Use X Registered Cross Origin Resource Sharings /// /// public static void UseXCors(this IApplicationBuilder sources) { // sources.UseCors(XPolicy.AllowedOrigins); } /// /// Register Api V1 Versioning ... /// /// public static void AddXApiV1Versioning(this IServiceCollection services) { // // Register Api Versioning ... services.AddApiVersioning(opt => { // // Set Default Api Version ... opt.DefaultApiVersion = new ApiVersion(1, 0); // // Set Routing to Default API Version, if Version unspecified ... opt.AssumeDefaultVersionWhenUnspecified = true; // // Report All Available Api Versions on Response ... opt.ReportApiVersions = true; }); } } }