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;
});
}
}
}