Initial Commit ...

This commit is contained in:
2024-01-25 04:39:39 +03:30
commit c743026b3c
42 changed files with 3954 additions and 0 deletions
+8
View File
@@ -0,0 +1,8 @@
#
# DotNet ...
bin
obj
#
# Natural Docs ...
Documentation/*
+38
View File
@@ -0,0 +1,38 @@
using System.Linq;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Filters;
using xCommons.Constants;
using xCommons.Extensions;
namespace xCommons.Attributes {
public partial class RequireXPoweredAttribute : AuthorizeAttribute, IAuthorizationFilter {
private readonly bool ignoreAnonymous;
public RequireXPoweredAttribute (bool IgnoreAnonymous = true) {
ignoreAnonymous = IgnoreAnonymous;
}
public void OnAuthorization (AuthorizationFilterContext context) {
//
var config = context.GetXAppConfiguration ();
//
var isExistsXPowered = context.HttpContext.Request.Headers
.Any (h => h.Key
.ToNormalString () == XAuthorization.XPoweredBy.ToNormalString () &&
h.Value == config.XPoweredValue);
//
var isAnonymous = context.IsAnonymousAllowed ();
var handler = ignoreAnonymous ? isAnonymous ? false : true : true;
//
if (handler &&
!isExistsXPowered) {
context.Result = new UnauthorizedResult ();
}
}
}
}
+31
View File
@@ -0,0 +1,31 @@
using System.Linq;
using System.Threading.Tasks;
using IdentityModel;
using Microsoft.AspNetCore.Authorization;
namespace xCommons.Authorization {
public partial class RequiredRolesHandler : AuthorizationHandler<RequiredRolesRequirement> {
protected override Task HandleRequirementAsync (
AuthorizationHandlerContext context,
RequiredRolesRequirement requirement
) {
//
var conatinsRole = context.User.HasClaim (c => c.Type == JwtClaimTypes.Role);
if (!conatinsRole) {
return Task.CompletedTask;
}
//
var roleClaim = context.User.Claims.FirstOrDefault (c => c.Type == JwtClaimTypes.Role);
if (roleClaim == null ||
!requirement.Roles.Contains (roleClaim.Value)
) {
return Task.CompletedTask;
}
//
context.Succeed (requirement);
return Task.CompletedTask;
}
}
}
+10
View File
@@ -0,0 +1,10 @@
using Microsoft.AspNetCore.Authorization;
namespace xCommons.Authorization {
public partial class RequiredRolesRequirement : IAuthorizationRequirement {
public string[] Roles { get; }
public RequiredRolesRequirement (params string[] Roles) {
this.Roles = Roles;
}
}
}
+27
View File
@@ -0,0 +1,27 @@
using System.Collections.Generic;
namespace xCommons.Configurations {
/// <summary>
/// represent an xBackend Application
/// </summary>
public partial class XAppConfiguration {
public string Name { get; set; }
public string Version { get; set; }
public string XPoweredValue { get; set; }
public IEnumerable<string> AllowedOrigins { get; set; }
public string WelcomeMessage { get; set; }
public string DefaultLanguage { get; set; }
public XMessageResourceTitles MessageResourceTitles { get; set; }
}
public partial class XMessageResourceTitles {
public string Terms { get; set; }
public string Invite { get; set; }
public string RegistrationApprove { get; set; }
public string Registered { get; set; }
public string VerificationCode { get; set; }
public string ChangePassword { get; set; }
public string PasswordChanged { get; set; }
public string NewDeviceLoggedIn { get; set; }
}
}
+22
View File
@@ -0,0 +1,22 @@
namespace xCommons.Configurations {
public partial class XSwaggerConfiguration {
public string Title { get; set; } = "";
public string Version { get; set; } = "V1.0";
public string Description { get; set; } = "";
public string TermsOfServiceUrl { get; set; } = "";
public XSwaggerContact Contact { get; set; } = null;
public XSwaggerLicence License { get; set; } = null;
}
public partial class XSwaggerContact {
public string Name { get; set; }
public string Email { get; set; }
public string Url { get; set; }
}
public partial class XSwaggerLicence {
public string Name { get; set; }
public string Url { get; set; }
}
}
+5
View File
@@ -0,0 +1,5 @@
namespace xCommons.Constants {
public partial class CommonConstants {
public static char DEFAULT_LIST_SEPERATOR = ',';
}
}
+7
View File
@@ -0,0 +1,7 @@
namespace xCommons.Constants {
public partial struct ConfigurationNodeNames {
public const string CERTIFICATES_NODE = "Certificates";
public const string SWAGGER_NODE = "SwaggerConfiguration";
public const string MESSAGE_RESOURCE_TITLES_NODE = "MessageResourceTitles";
}
}
+9
View File
@@ -0,0 +1,9 @@
namespace xCommons.Constants {
public partial struct XAuthentication {
public const string JWT = "jwt";
public const string BEARER = "Bearer";
public const string TOKEN = "token";
public const string INTROSPECTION = "introspection";
public const string IDENTITY_SERVER_LOCAL_API = "IdentityServerAccessToken";
}
}
+13
View File
@@ -0,0 +1,13 @@
namespace xCommons.Constants {
public partial struct XAuthorization {
public const string TokenIdentifier = "Bearer ";
public const string Header = "Authorization";
public const string AccessToken = "access_token";
public const string RefreshToken = "refresh_token";
public const string ExpiresAt = "expires_at";
public const string AccessTokenExpired = "AccessToken-Expired";
public const string RevisionChecksum = "revision_checksum";
public const string XPoweredBy = "X-PoweredBy";
public const int ThresholdBeforeTokenExpiration = 600;
}
}
+24
View File
@@ -0,0 +1,24 @@
namespace xCommons.Constants {
public partial struct XCustomClaims {
public const string IsEnabled = "is_enabled";
public const string IsBanned = "is_banned";
public const string Issuer = "iss";
public const string ExpiredOn = "exp";
public const string Audience = "aud";
public const string ClientId = "client_id";
public const string AuthenticatedOn = "auth_time";
public const string UserId = "sub";
public const string UserName = "unique_name";
public const string FirstName = "given_name";
public const string LastName = "family_name";
public const string Gender = "gender";
public const string Picture = "picture";
public const string BrithDate = "birthdate";
public const string Email = "email";
public const string EmailVerified = "email_verified";
public const string PhoneNumber = "phone_number";
public const string PhoneNumberVerified = "phone_number_verified";
public const string Role = "role";
public const string Scope = "scope";
}
}
+11
View File
@@ -0,0 +1,11 @@
namespace xCommons.Constants {
/// <summary>
/// a collection of available Client Devices
/// </summary>
public enum XDeviceType {
Unknown,
Mobile,
Tablet,
Desktop
}
}
+10
View File
@@ -0,0 +1,10 @@
namespace xCommons.Constants {
public enum XFileType {
Image,
ProfileImasge,
CoverImage,
Audio,
Video,
Document
}
}
+5
View File
@@ -0,0 +1,5 @@
namespace xCommons.Constants {
public partial struct XPolicy {
public const string AllowedOrigins = "AllowedOrigins";
}
}
+139
View File
@@ -0,0 +1,139 @@
using System;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Logging;
using xCommons.Attributes;
using xCommons.Configurations;
using xCommons.Extensions;
using xCommons.Providers;
using xExceptions.Constants;
namespace xCommons.Controllers {
/// <summary>
/// Base Controller
/// </summary>
[Route ("[controller]")]
[Produces ("application/json")]
public abstract partial class XBaseController : ControllerBase {
public ILogger Logger { get; }
public XAppConfiguration AppConfiguration { get; }
public XValidationProvider ValidationProvider { get; }
public XBaseController (
ILogger logger,
XAppConfiguration appConfiguration,
XValidationProvider validationProvider
) {
Logger = logger;
AppConfiguration = appConfiguration;
ValidationProvider = validationProvider;
}
/// <summary>
/// Check the Controller Up and Running
/// </summary>
/// <returns>string message</returns>
[HttpGet]
[Route ("Test/Hi")]
[AllowAnonymous]
public virtual IActionResult Hi () {
//
var controllerName = GetControllerName ();
var message = $"{controllerName} Controller is Up and running ...";
//
return Ok (message);
}
/// <summary>
/// Check Controller ByPass XPowered Filter
/// </summary>
/// <returns>string message</returns>
[HttpGet]
[AllowAnonymous]
[RequireXPowered (false)]
[Route ("Test/PassRequireXPowered")]
public virtual IActionResult PassRequireXPowered () {
//
var controllerName = GetControllerName ();
var message = $"{controllerName} Controller bypass RequiredXPowered and Up and running ...";
//
return Ok (message);
}
//
#region Non Actions ...
/// <summary>
/// Convert an Exception to Propper Error Result
/// </summary>
/// <param name="ex"></param>
/// <returns></returns>
[NonAction]
public ActionResult GetExceptionActionResult (Exception ex) {
//
var exception = GetExceptionResult (ex);
var error = ex.Message.ToXError ();
//
Logger.LogError ($"exception: {exception}, error: {error}");
//
try {
var xError = exception.Message.ToXError ();
var xException = (XException) xError.Id;
//
switch (xException) {
//
case XException.NotFound:
return NotFound (error);
//
case XException.NotAuthorized:
return Unauthorized ();
}
} catch { }
//
return BadRequest (error);
}
/// <summary>
/// Return Structured Exception
/// </summary>
/// <param name="ex"></param>
/// <returns></returns>
[NonAction]
public Exception GetExceptionResult (Exception ex) {
//
// Log Exception Message ...
Logger.LogError (ex.Message);
//
// if Happens Exception is Know Error
// catch it and return it in BadRequest Container ...
var isEr = ex.Message.IsXError ();
//
if (isEr) {
return ex;
}
//
// if catched Exception Contains Unknown Error
// return an Unknown Error ...
return XException.Unknown.ToException ();
}
/// <summary>
/// Retrieve ControllerName
/// </summary>
/// <returns></returns>
[NonAction]
public string GetControllerName () {
return this.ControllerContext.RouteData.Values["controller"].ToString ();
}
#endregion
}
}
+12
View File
@@ -0,0 +1,12 @@
using Microsoft.Extensions.DependencyInjection;
using xCommons.Providers;
public static partial class XDIHelperExtension {
/// <summary>
/// Register XCommons Module Services
/// </summary>
/// <param name="services"></param>
public static void AddXCommons (this IServiceCollection services) {
services.AddSingleton<XValidationProvider> ();
}
}
+23
View File
@@ -0,0 +1,23 @@
using Microsoft.Extensions.Configuration;
using xCommons.Constants;
using xCommons.Models;
namespace xCommons.Extensions {
public static partial class CertificateExtensions {
/// <summary>
/// Retrieve Specific Certificate From app Settings
/// </summary>
/// <param name="configuration"></param>
/// <param name="name"></param>
/// <returns></returns>
public static XCertificate GetCertificate (this IConfiguration configuration, string name) {
//
var certificatesSection = configuration.GetSection (ConfigurationNodeNames.CERTIFICATES_NODE);
var certificateSection = certificatesSection.GetSection (name);
var certificate = certificateSection.Get<XCertificate> ();
//
return certificate;
}
}
}
File diff suppressed because it is too large Load Diff
+319
View File
@@ -0,0 +1,319 @@
using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.AspNetCore.Builder;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.OpenApi.Models;
using Swashbuckle.AspNetCore.SwaggerGen;
using Swashbuckle.AspNetCore.SwaggerUI;
using xCommons.Configurations;
using xCommons.Constants;
using xCommons.Filters;
namespace xCommons.Extensions {
public static partial class DIExtensions {
/// <summary>
/// Inject Specific Registered Service from IServiceCollection
/// </summary>
/// <param name="source"></param>
/// <typeparam name="T"></typeparam>
/// <returns></returns>
public static T GetRegisteredService<T> (this IServiceCollection source) {
//
var serviceProvider = source.BuildServiceProvider ();
return serviceProvider.GetService<T> ();
}
/// <summary>
/// Register App Configuration as a Service
/// </summary>
/// <param name="services"></param>
/// <param name="configuration"></param>
public static void AddXAppConfiguration (this IServiceCollection services, IConfiguration configuration) {
//
var appConfiguration = configuration.GetXAppConfiguration ();
services.AddSingleton<XAppConfiguration> (appConfiguration);
}
/// <summary>
/// Add Required OperationFilters and Authorization Fields to Swagger Options
/// </summary>
/// <param name="source"></param>
/// <param name="xmlFilePath"></param>
/// <param name="addRequiredXPoweredFilter"></param>
/// <param name="addXTokenAuthorization"></param>
public static void AddXSwaggerGenOptions (
this SwaggerGenOptions source,
string xmlFilePath = null,
bool addRequiredXPoweredFilter = true,
bool addXTokenAuthorization = true
) {
//
if (source.IsNull ()) {
source = new SwaggerGenOptions ();
}
//
// Add Xml File Path ...
if (!xmlFilePath.IsNullOrEmpty ()) {
source.IncludeXmlComments (xmlFilePath);
}
//
// Handle RequireXPowered Filter ...
if (addRequiredXPoweredFilter) {
source.OperationFilter<RequireXPoweredOperationFilter> ();
}
//
// 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<string> ()
}
});
#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<string> ()
}
});
#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<string> ()
}
});
#endregion
}
}
/// <summary>
/// Register Swagger
/// </summary>
/// <param name="source"></param>
/// <param name="configuration"></param>
/// <param name="settings"></param>
/// <param name="xmlFilePath"></param>
/// <param name="addRequiredXPoweredFilter"></param>
/// <param name="addXTokenAuthorization"></param>
public static void AddXSwagger (
this IServiceCollection source,
IConfiguration configuration,
SwaggerGenOptions settings = null,
string xmlFilePath = null,
bool addRequiredXPoweredFilter = true,
bool addXTokenAuthorization = true
) {
//
var xSwaggerConfig = configuration.GetXSwaggerConfiguration ();
if (xSwaggerConfig.IsNull ()) {
xSwaggerConfig = new XSwaggerConfiguration ();
}
//
#region Prepare SwaggerGenOptions ...
if (settings.IsNull ()) {
settings = new SwaggerGenOptions ();
}
settings.AddXSwaggerGenOptions (
xmlFilePath: xmlFilePath,
addRequiredXPoweredFilter: addRequiredXPoweredFilter,
addXTokenAuthorization: addXTokenAuthorization
);
#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);
}
);
}
/// <summary>
/// Use Sagger
/// </summary>
/// <param name="source"></param>
/// <param name="options"></param>
public static void UseXSwagger (
this IApplicationBuilder source,
SwaggerUIOptions options = null
) {
//
source.UseSwagger ();
//
if (options.IsNull ()) {
source.UseSwaggerUI ();
} else {
source.UseSwaggerUI (options: options);
}
}
/// <summary>
/// Add Cross Origin Resource Sharings
/// </summary>
/// <param name="source"></param>
/// <param name="allowedOrigins"></param>
public static void AddXCors (
this IServiceCollection source,
IEnumerable<string> 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 ("*");
});
});
}
/// <summary>
/// Use X Registered Cross Origin Resource Sharings
/// </summary>
/// <param name="sources"></param>
public static void UseXCors (this IApplicationBuilder sources) {
//
sources.UseCors (XPolicy.AllowedOrigins);
}
}
}
+23
View File
@@ -0,0 +1,23 @@
using System;
using System.Collections.Generic;
namespace xCommons.Extensions {
public static partial class EnumExtensions {
public static string GetKey (this Enum source) {
return Enum.GetName (source.GetType (), source);
}
public static T GetValue<T> (this string source) {
return (T) Enum.Parse (typeof (T), source);
}
public static void Iterate<T> (this IEnumerator<T> source, Action<T> action) {
//
while (source.MoveNext ()) {
//
var current = source.Current;
action (current);
}
}
}
}
+170
View File
@@ -0,0 +1,170 @@
using System;
using xExceptions.Constants;
using xExceptions.Models;
namespace xCommons.Extensions {
/// <summary>
/// this is an extension pack for Exceptions
/// </summary>
public static partial class ExceptionExtensions {
/// <summary>
/// determines an string contains an XError content or not
/// </summary>
/// <param name="source"></param>
/// <returns></returns>
public static bool IsXError (this string source) {
//
if (source.IsNullOrEmpty ()) {
return false;
}
//
var xError = source.ToXError ();
if (xError != null) {
return true;
}
//
// If Convert Proccess fails ...
var normalString = source.ToNormalString ();
//
// Return result based on string values ...
return normalString.Contains ("id") && normalString.Contains ("message");
}
/// <summary>
/// deserialize an string to to XError class instance
/// </summary>
/// <param name="source"></param>
/// <returns></returns>
public static XError ToXError (this string source) {
//
if (source.IsNullOrEmpty ()) {
return null;
}
//
try {
//
var err = source.FromJSON<XError> ();
//
// if err is null we have to manually get value
if (err == null) {
//
var normalString = source.ToNormalString ();
var parts = normalString.Split (',');
if (parts.Length > 2) {
return null;
}
//
var idContainer = parts[0];
var messageContainer = parts[1];
}
//
return err;
} catch {
return null;
}
}
public static XError ToXError (this XException source) {
//
var errorId = (int) source;
var errorMessage = source.GetStringValue ();
//
return new XError {
Id = errorId,
Message = errorMessage
};
}
/// <summary>
/// Convert an XError instance to an Exception
/// </summary>
/// <param name="source"></param>
/// <returns></returns>
public static Exception ToException (this XError source) {
//
var jsonStr = source.ToJSON ();
return new Exception (jsonStr);
}
public static Exception ToException (this XException source) {
return source
.ToXError ()
.ToException ();
}
/// <summary>
/// Convert an Exception to corresponding XError Object
/// </summary>
/// <param name="source"></param>
/// <returns></returns>
public static XError FromException (this Exception source) {
//
if (source == null || source.Message.IsNullOrEmpty ()) {
return null;
}
//
return source.Message.ToXError ();
}
/// <summary>
/// Add Content to Contentable XException member and return XError Object
/// </summary>
/// <param name="exception"></param>
/// <param name="value"></param>
/// <returns></returns>
public static XError AddContentToError (this XException exception, string value) {
//
var xError = exception.ToXError ();
xError.Message = string.Format (xError.Message, value);
//
return xError;
}
/// <summary>
/// Add Content to Contentable XException member and return Exception Object
/// </summary>
/// <param name="exception"></param>
/// <param name="value"></param>
/// <returns></returns>
public static Exception AddContentToException (this XException exception, string value) {
//
var xError = exception.ToXError ();
xError.Message = string.Format (xError.Message, value);
//
return xError.ToException ();
}
/// <summary>
/// Throw Specific Exception ...
/// </summary>
/// <param name="source"></param>
/// <param name="content"></param>
public static void Throw (
this XException source,
string content = null
) {
//
Exception exception = null;
if (content.IsNullOrEmpty ()) {
exception = source.ToException ();
} else {
exception = source.AddContentToException (content);
}
//
throw exception;
}
}
}
+34
View File
@@ -0,0 +1,34 @@
using System.Linq;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc.Authorization;
using Microsoft.AspNetCore.Mvc.Filters;
using xCommons.Configurations;
namespace xCommons.Extensions {
public static partial class FilterExtensions {
public static XAppConfiguration GetXAppConfiguration (this ActionExecutingContext source) {
//
var services = source.HttpContext.RequestServices;
return (XAppConfiguration) services.GetService (typeof (XAppConfiguration));
}
public static XAppConfiguration GetXAppConfiguration (this AuthorizationFilterContext source) {
//
var services = source.HttpContext.RequestServices;
return (XAppConfiguration) services.GetService (typeof (XAppConfiguration));
}
public static bool IsAnonymousAllowed (this AuthorizationFilterContext source) {
//
var result = source.Filters
.Any (f => f.GetType () == typeof (AllowAnonymousFilter)) ||
source.ActionDescriptor.FilterDescriptors
.Any (f => f.GetType () == typeof (AllowAnonymousFilter)) ||
source.ActionDescriptor.EndpointMetadata
.Any (f => f.GetType () == typeof (AllowAnonymousAttribute));
//
return result;
}
}
}
+48
View File
@@ -0,0 +1,48 @@
using System.Collections.Generic;
using Microsoft.Extensions.Configuration;
using xCommons.Configurations;
using xCommons.Constants;
namespace xCommons.Extensions {
public static partial class IConfigurationExtensions {
/// <summary>
/// Retrieve AppConfiguration from Configurations
/// </summary>
/// <param name="source"></param>
/// <returns></returns>
public static XAppConfiguration GetXAppConfiguration (this IConfiguration source) {
//
var xMessageResourceTitlesConfigSection = source
.GetSection (ConfigurationNodeNames.MESSAGE_RESOURCE_TITLES_NODE);
//
var result = new XAppConfiguration {
Name = source[nameof (XAppConfiguration.Name)],
Version = source[nameof (XAppConfiguration.Version)],
XPoweredValue = source[nameof (XAppConfiguration.XPoweredValue)],
WelcomeMessage = source[nameof (XAppConfiguration.WelcomeMessage)],
AllowedOrigins = source
.GetSection (nameof (XAppConfiguration.AllowedOrigins))
.Get<IEnumerable<string>> (),
DefaultLanguage = source[nameof (XAppConfiguration.DefaultLanguage)],
MessageResourceTitles = xMessageResourceTitlesConfigSection
.Get<XMessageResourceTitles> ()
};
//
return result;
}
/// <summary>
/// Retrieve Swagger Configurations
/// </summary>
/// <param name="source"></param>
/// <returns></returns>
public static XSwaggerConfiguration GetXSwaggerConfiguration (this IConfiguration source) {
//
var xSwaggerConfigSection = source
.GetSection (ConfigurationNodeNames.SWAGGER_NODE);
return xSwaggerConfigSection.Get<XSwaggerConfiguration> ();
}
}
}
+283
View File
@@ -0,0 +1,283 @@
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.Linq.Expressions;
namespace xCommons.Extensions {
public static partial class ModelExtensions {
/// <summary>
/// Update an Instance of a Typed Object with Data Provided by another Instance of Typed Object
/// </summary>
/// <param name="source"></param>
/// <param name="updateWith"></param>
/// <param name="propertyWhiteList"></param>
/// <param name="propertyBlackList"></param>
/// <param name="propertyValueProviders"></param>
/// <param name="updateWithNullOrEmptyValues"></param>
/// <param name="throwExceptionOnFails"></param>
/// <typeparam name="T"></typeparam>
/// <typeparam name="D"></typeparam>
/// <returns></returns>
public static T UpdateData<T, D> (
this T source,
D updateWith,
ICollection<string> propertyWhiteList = null,
ICollection<string> propertyBlackList = null,
ICollection<KeyValuePair<string, Func<D, object>>> propertyValueProviders = null,
bool updateWithNullOrEmptyValues = false,
bool throwExceptionOnFails = false
)
where T : class
where D : class {
//
var hasWhiteList = propertyWhiteList.HasChild<string> ();
var hasBlackList = propertyBlackList.HasChild<string> ();
var hasValueProvider = propertyValueProviders.HasChild<KeyValuePair<string, Func<D, object>>> ();
//
var fullPropertyList = updateWith.GetType ().GetProperties ().Select (prop => prop.Name);
var mustSetProps = (hasWhiteList ? propertyWhiteList : fullPropertyList);
//
if (hasBlackList) {
mustSetProps = mustSetProps.Where (propName => !propertyBlackList.Contains (propName));
}
//
mustSetProps.ToList ().ForEach (propName => {
//
try {
//
var sourceProp = source.GetType ().GetProperty (propName);
var sourceValue = sourceProp.GetValue (source);
var sourceValueType = sourceValue.IsNull () ? null : sourceValue.GetType ();
//
var updateWithProp = updateWith.GetType ().GetProperty (propName);
var updateWithValue = updateWithProp.GetValue (updateWith);
var updateWithValueType = updateWithValue.IsNull () ? null : updateWithValue.GetType ();
//
var valueProviderValue = hasValueProvider ? propertyValueProviders
.FirstOrDefault (p => p.Key == propName).Value : null;
var updateVal = !valueProviderValue.IsNull () ?
valueProviderValue.Invoke (updateWith) :
(updateWithValue.IsNull () && !updateWithNullOrEmptyValues) ?
sourceValue : updateWithValue;
var updateValType = updateVal.IsNull () ? null : updateVal.GetType ();
//
Type t = Nullable.GetUnderlyingType (sourceProp.PropertyType) ?? sourceProp.PropertyType;
object safeValue =
(updateVal == null) ?
null :
!updateValType.IsCollectionType () ?
Convert.ChangeType (updateVal, t) :
updateVal;
//
sourceProp.SetValue (source, safeValue);
} catch (Exception ex) {
//
if (throwExceptionOnFails) {
throw ex;
}
}
});
//
return source;
}
/// <summary>
/// Check two Instance of Typed Object Values are Same or not
/// </summary>
/// <param name="source"></param>
/// <param name="dest"></param>
/// <param name="propertyWhiteList"></param>
/// <param name="propertyBlackList"></param>
/// <param name="throwExceptionOnFails"></param>
/// <param name="propertyValueCheckers"></param>
/// /// <typeparam name="T"></typeparam>
/// <typeparam name="D"></typeparam>
/// <returns></returns>
public static bool IsSameContent<T, D> (
this T source,
D dest,
ICollection<string> propertyWhiteList = null,
ICollection<string> propertyBlackList = null,
ICollection<KeyValuePair<string, Func<T, D, bool>>> propertyValueCheckers = null,
bool throwExceptionOnFails = false
)
where T : class
where D : class {
//
var hasWhiteList = propertyWhiteList.HasChild<string> ();
var hasBlackList = propertyBlackList.HasChild<string> ();
var hasCheckerProvider = propertyValueCheckers.HasChild<KeyValuePair<string, Func<T, D, bool>>> ();
//
var fullPropertyList = dest.GetType ().GetProperties ().Select (prop => prop.Name);
var mustCheckProps = (hasWhiteList ? propertyWhiteList : fullPropertyList);
if (hasBlackList) {
mustCheckProps = mustCheckProps.Where (propName => !propertyBlackList.Contains (propName));
}
//
var result = true;
mustCheckProps.ToList ().ForEach (propName => {
//
try {
//
var sourceProp = source.GetType ().GetProperty (propName);
var destProp = dest.GetType ().GetProperty (propName);
//
// Check Types ...
var isSameType = true;
//
// Check
var isSameValue = false;
var mustDoCustomCheck = hasCheckerProvider && propertyValueCheckers.Any (p => p.Key == propName);
if (mustDoCustomCheck) {
//
// Check Values ...
var valueChecker = propertyValueCheckers.FirstOrDefault (p => p.Key == propName).Value;
isSameValue = valueChecker.Invoke (source, dest);
} else {
// //
// isSameType = (sourceProp.PropertyType == destProp.PropertyType &&
// sourceProp.ReflectedType == destProp.ReflectedType);
//
// Check Values ...
isSameValue = Equals (sourceProp.GetValue (source), destProp.GetValue (dest));
}
//
if (!isSameType || !isSameValue) {
result = false;
}
} catch (Exception ex) {
//
if (throwExceptionOnFails) {
throw ex;
}
}
});
//
return result;
}
/// <summary>
/// Check specific type is Collection Type or not
/// </summary>
/// <param name="source"></param>
/// <returns></returns>
public static bool IsCollectionType (this Type source) {
//
if (source.IsNull () || !source.IsGenericType) {
return false;
}
//
var genericTypeDefinition = source.GetGenericTypeDefinition ();
var result = genericTypeDefinition == typeof (List<>) ||
genericTypeDefinition == typeof (HashSet<>) ||
genericTypeDefinition == typeof (Collection<>) ||
genericTypeDefinition == typeof (ICollection<>) ||
genericTypeDefinition == typeof (IEnumerable<>);
//
return result;
}
/// <summary>
/// Retrieve a Property Value in Generic
/// </summary>
/// <param name="item"></param>
/// <typeparam name="T"></typeparam>
/// <returns></returns>
public static string GetPropValues<T> (this T item)
where T : class {
//
var props = item.GetType ().GetProperties ();
var vals = props.Select (p => p.GetValue (item));
//
return vals.ToJSON ();
}
/// <summary>
/// Check a Property Value Contains specific value
/// </summary>
/// <param name="item"></param>
/// <param name="value"></param>
/// <typeparam name="T"></typeparam>
/// <returns></returns>
public static bool PropValuesContains<T> (this T item, string value)
where T : class {
//
return item.GetPropValues ()
.ToNormalString ()
.Contains (value
.ToNormalString ());
}
/// <summary>
/// Generate Default Column Map
/// </summary>
/// <param name="item"></param>
/// <typeparam name="T"></typeparam>
/// <returns></returns>
public static IDictionary<string, Expression<Func<T, object>>> GetDefaultColumnsMap<T> (this T item)
where T : class {
//
if (item.IsNull ()) {
return null;
}
//
var result = new Dictionary<string, Expression<Func<T, object>>> ();
var props = item.GetType ().GetProperties ();
//
foreach (var prop in props) {
result.Add (prop.Name, t => t.GetType ().GetProperty (prop.Name).GetValue (t, null));
}
//
return result;
}
/// <summary>
/// Generate Default Column Map
/// </summary>
/// <param name="item"></param>
/// <typeparam name="T"></typeparam>
/// <returns></returns>
public static IDictionary<string, string> GetPropValuesDictionary<T> (this T item)
where T : class {
//
if (item.IsNull ()) {
return null;
}
//
var result = new Dictionary<string, string> ();
var props = item.GetType ().GetProperties ();
//
foreach (var prop in props) {
result.Add (prop.Name, prop.GetValue (item).ToJSON ());
}
//
return result;
}
}
}
+38
View File
@@ -0,0 +1,38 @@
using System;
using System.Collections;
using System.Collections.Generic;
using Microsoft.Extensions.DependencyInjection;
using xCommons.Helpers;
namespace xCommons.Extensions {
public static class ServiceProviderExtensions {
/// <summary>
/// Get all registered <see cref="ServiceDescriptor"/>
/// </summary>
/// <param name="provider"></param>
/// <returns></returns>
public static Dictionary<Type, ServiceDescriptor> GetAllServiceDescriptors (this IServiceProvider provider) {
//
if (provider is ServiceProvider serviceProvider) {
//
var result = new Dictionary<Type, ServiceDescriptor> ();
//
var engine = serviceProvider.GetFieldValue ("_engine");
var callSiteFactory = engine.GetPropertyValue ("CallSiteFactory");
var descriptorLookup = callSiteFactory.GetFieldValue ("_descriptorLookup");
if (descriptorLookup is IDictionary dictionary) {
foreach (DictionaryEntry entry in dictionary) {
result.Add ((Type) entry.Key, (ServiceDescriptor) entry.Value.GetPropertyValue ("Last"));
}
}
//
return result;
}
//
throw new NotSupportedException ($"Type '{provider.GetType()}' is not supported!");
}
}
}
+22
View File
@@ -0,0 +1,22 @@
using System.IO;
using Microsoft.AspNetCore.Http;
namespace xCommons.Extensions {
public static partial class XHttpContextExtensions {
/// <summary>
/// Convert IFormFile to Bytes Array
/// </summary>
/// <param name="source"></param>
/// <returns></returns>
public static byte[] ToByteArray (this IFormFile source) {
//
byte[] data;
using (var br = new BinaryReader (source.OpenReadStream ())) {
data = br.ReadBytes ((int) source.OpenReadStream ().Length);
}
//
return data;
}
}
}
+17
View File
@@ -0,0 +1,17 @@
using System;
using Microsoft.AspNetCore.Builder;
using xCommons.Middlewares;
namespace xCommons.Extensions
{
public static class XMiddlewareExtensions
{
/// <summary>
/// Use XRequestLogger Middleware for log Requests ...
/// </summary>
/// <param name="app"></param>
public static void UseXRequestLogger(this IApplicationBuilder app) {
app.UseMiddleware<XRequestLogger>();
}
}
}
+39
View File
@@ -0,0 +1,39 @@
using System.Collections.Generic;
using Microsoft.OpenApi.Any;
using Microsoft.OpenApi.Models;
using Swashbuckle.AspNetCore.SwaggerGen;
using xCommons.Configurations;
using xCommons.Constants;
using xCommons.Extensions;
namespace xCommons.Filters {
/// <summary>
/// RequireXPowered for NGSwag
/// </summary>
public partial class RequireXPoweredOperationFilter : IOperationFilter {
private readonly XAppConfiguration config;
public RequireXPoweredOperationFilter (XAppConfiguration config) {
this.config = config;
}
public void Apply (OpenApiOperation operation, OperationFilterContext context) {
//
if (operation.Parameters.IsNull ()) {
operation.Parameters = new List<OpenApiParameter> ();
}
//
operation.Parameters.Add (new OpenApiParameter {
In = ParameterLocation.Header,
Name = XAuthorization.XPoweredBy,
Description = "a Basic Authorization Filter",
Required = false,
Schema = new OpenApiSchema {
Type = "String",
Default = new OpenApiString (config.XPoweredValue)
}
});
}
}
}
+99
View File
@@ -0,0 +1,99 @@
using System;
using System.Collections.Generic;
using System.Linq;
namespace xCommons.Helpers {
public partial class ObjectHelper {
/// <summary>
/// Convert Enum Keys to Array
/// </summary>
/// <typeparam name="T"></typeparam>
/// <returns></returns>
public static Array GetKeys<T> () {
//
ValidateEnumbType<T> ();
var type = typeof (T);
//
var result = Enum.GetNames (type);
//
return result;
}
/// <summary>
/// Convert EnumValues to Array
/// </summary>
/// <typeparam name="T"></typeparam>
/// <returns></returns>
public static Array GetValues<T> () {
//
ValidateEnumbType<T> ();
var type = typeof (T);
//
var result = Enum.GetValues (type);
//
return result;
}
/// <summary>
/// Convert an Enum to IEnumerable of it's Childs
/// </summary>
/// <typeparam name="T"></typeparam>
/// <returns></returns>
public static IEnumerable<T> ToEnumerableValues<T> () {
//
ValidateEnumbType<T> ();
var type = typeof (T);
//
var result = GetValues<T> ()
.Cast<T> ();
//
return result;
}
/// <summary>
/// Retrieve Keys of an Enumerable
/// </summary>
/// <typeparam name="T"></typeparam>
/// <returns></returns>
public static IEnumerable<string> ToEnumerableKeys<T> () {
//
ValidateEnumbType<T> ();
var type = typeof (T);
//
var result = GetKeys<T> ()
.Cast<string> ();
//
return result;
}
public static IDictionary<string, int> ToDictionary<T> () {
//
ValidateEnumbType<T> ();
//
var result = new Dictionary<string, int> ();
foreach (var name in Enum.GetNames (typeof (T))) {
result.Add (name, (int) Enum.Parse (typeof (T), name));
}
//
return result;
}
private static void ValidateEnumbType<T> () {
//
var type = typeof (T);
if (!type.IsEnum) {
throw new InvalidCastException ();
}
}
}
}
+16
View File
@@ -0,0 +1,16 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
namespace xCommons.Helpers {
public partial class XDateHelper {
/// <summary>
/// retrieve utc now timestam unix like representation ...
/// </summary>
/// <returns></returns>
public static long UtcNowTimespan () {
return DateTimeOffset.UtcNow.ToUnixTimeMilliseconds ();
}
}
}
+178
View File
@@ -0,0 +1,178 @@
using System;
using System.Collections.Generic;
using System.Text;
using System.Xml;
namespace xCommons.Helpers {
public partial class XMLToJSONHelper {
//
#region Actions ...
public static string ToJSON (string xml) {
//
XmlDocument doc = new XmlDocument ();
doc.LoadXml (xml);
//
return XmlToJSON (doc);
}
public static string XmlToJSON (XmlDocument xmlDoc) {
//
StringBuilder sbJSON = new StringBuilder ();
//
sbJSON.Append ("{ ");
XmlToJSONnode (sbJSON, xmlDoc.DocumentElement, true);
sbJSON.Append ("}");
//
return sbJSON.ToString ();
}
#endregion
//
#region Private ...
//
private static void XmlToJSONnode (StringBuilder sbJSON, XmlElement node, bool showNodeName) {
//
if (showNodeName) {
sbJSON.Append ("\"" + SafeJSON (node.Name) + "\": ");
}
//
sbJSON.Append ("{");
//
// Build a sorted list of key-value pairs
// where key is case-sensitive nodeName
// value is an ArrayList of string or XmlElement
// so that we know whether the nodeName is an array or not.
SortedList<string, object> childNodeNames = new SortedList<string, object> ();
//
// Add in all node attributes
if (node.Attributes != null)
foreach (XmlAttribute attr in node.Attributes)
StoreChildNode (childNodeNames, attr.Name, attr.InnerText);
//
// Add in all nodes
foreach (XmlNode cnode in node.ChildNodes) {
//
if (cnode is XmlText) {
StoreChildNode (childNodeNames, "value", cnode.InnerText);
} else if (cnode is XmlElement) {
StoreChildNode (childNodeNames, cnode.Name, cnode);
}
}
//
// Now output all stored info
foreach (string childname in childNodeNames.Keys) {
//
List<object> alChild = (List<object>) childNodeNames[childname];
if (alChild.Count == 1) {
OutputNode (childname, alChild[0], sbJSON, true);
} else {
//
sbJSON.Append (" \"" + SafeJSON (childname) + "\": [ ");
//
foreach (object Child in alChild) {
OutputNode (childname, Child, sbJSON, false);
}
//
sbJSON.Remove (sbJSON.Length - 2, 2);
sbJSON.Append (" ], ");
}
}
//
sbJSON.Remove (sbJSON.Length - 2, 2);
sbJSON.Append (" }");
}
//
// StoreChildNode: Store data associated with each nodeName
// so that we know whether the nodeName is an array or not.
private static void StoreChildNode (SortedList<string, object> childNodeNames, string nodeName, object nodeValue) {
//
// Pre-process contraction of XmlElement-s
if (nodeValue is XmlElement) {
//
// Convert <aa></aa> into "aa":null
// <aa>xx</aa> into "aa":"xx"
XmlNode cnode = (XmlNode) nodeValue;
if (cnode.Attributes.Count == 0) {
//
XmlNodeList children = cnode.ChildNodes;
if (children.Count == 0) {
nodeValue = null;
} else if (children.Count == 1 && (children[0] is XmlText)) {
nodeValue = ((XmlText) (children[0])).InnerText;
}
}
}
//
// Add nodeValue to ArrayList associated with each nodeName
// If nodeName doesn't exist then add it
List<object> ValuesAL;
//
if (childNodeNames.ContainsKey (nodeName)) {
ValuesAL = (List<object>) childNodeNames[nodeName];
} else {
//
ValuesAL = new List<object> ();
childNodeNames[nodeName] = ValuesAL;
}
//
ValuesAL.Add (nodeValue);
}
//
private static void OutputNode (string childname, object alChild, StringBuilder sbJSON, bool showNodeName) {
if (alChild == null) {
if (showNodeName)
sbJSON.Append ("\"" + SafeJSON (childname) + "\": ");
sbJSON.Append ("null");
} else if (alChild is string) {
if (showNodeName)
sbJSON.Append ("\"" + SafeJSON (childname) + "\": ");
string sChild = (string) alChild;
sChild = sChild.Trim ();
sbJSON.Append ("\"" + SafeJSON (sChild) + "\"");
} else
XmlToJSONnode (sbJSON, (XmlElement) alChild, showNodeName);
sbJSON.Append (", ");
}
//
// Make a string safe for JSON
private static string SafeJSON (string sIn) {
//
StringBuilder sbOut = new StringBuilder (sIn.Length);
foreach (char ch in sIn) {
//
if (Char.IsControl (ch) || ch == '\'') {
//
int ich = (int) ch;
sbOut.Append (@"\u" + ich.ToString ("x4"));
continue;
} else if (ch == '\"' || ch == '\\' || ch == '/') {
sbOut.Append ('\\');
}
//
sbOut.Append (ch);
}
//
return sbOut.ToString ();
}
#endregion
}
}
+81
View File
@@ -0,0 +1,81 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Net.NetworkInformation;
using System.Net.Sockets;
using System.Threading.Tasks;
using xCommons.Models;
namespace xCommons.Helpers {
public static class XNetworkHelper {
/// <summary>
/// Retrieve Application Host's Machin IP Addresses ...
/// </summary>
/// <returns>string</returns>
public static string GetIp () {
//
var name = Dns.GetHostName (); // get container id
var result = Dns.GetHostEntry (name)
.AddressList
.FirstOrDefault (
x => x.AddressFamily == AddressFamily.InterNetwork
)
.MapToIPv4 ()
.ToString ();
//
return result;
}
/// <summary>
/// Retrieve All Available IP's in Application Host's Machin ...
/// </summary>
/// <returns>a Collection of XNetworkInfo class instances</returns>
public static IEnumerable<XNetworkInfo> GetNetworkInfos () {
//
var result = System.Net.NetworkInformation.NetworkInterface
.GetAllNetworkInterfaces ()
.Where (
ni =>
!ni.IsReceiveOnly &&
ni.OperationalStatus == OperationalStatus.Up &&
ni.NetworkInterfaceType != NetworkInterfaceType.Loopback
)
.SelectMany (ni =>
ni
.GetIPProperties ()
.GatewayAddresses
.Select (ga =>
new {
Name = ni.Name,
Description = ni.Description,
Gateway = ga.Address
.MapToIPv4 ()
.ToString (),
NI = ni
}
)
)
.SelectMany (data =>
data.NI
.GetIPProperties ()
.UnicastAddresses
.Select (ip =>
new XNetworkInfo {
Name = data.Name,
Gateway = data.Gateway,
Description = data.Description,
NetworkInterface = data.NI,
IP = ip.Address
.MapToIPv4 ()
.ToString ()
}
)
);
//
return result;
}
}
}
+70
View File
@@ -0,0 +1,70 @@
using System;
using System.Reflection;
namespace xCommons.Helpers {
public static class XReflectionHelper {
public static object GetFieldValue (this object obj, string fieldName) {
if (obj == null)
throw new ArgumentNullException (nameof (obj));
Type objType = obj.GetType ();
var fieldInfo = GetFieldInfo (objType, fieldName);
if (fieldInfo == null)
throw new ArgumentOutOfRangeException (fieldName,
$"Couldn't find field {fieldName} in type {objType.FullName}");
return fieldInfo.GetValue (obj);
}
public static void SetFieldValue (this object obj, string fieldName, object val) {
if (obj == null)
throw new ArgumentNullException (nameof (obj));
Type objType = obj.GetType ();
var fieldInfo = GetFieldInfo (objType, fieldName);
if (fieldInfo == null)
throw new ArgumentOutOfRangeException (fieldName,
$"Couldn't find field {fieldName} in type {objType.FullName}");
fieldInfo.SetValue (obj, val);
}
private static FieldInfo GetFieldInfo (Type type, string fieldName) {
FieldInfo fieldInfo = null;
do {
fieldInfo = type.GetField (fieldName, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
type = type.BaseType;
} while (fieldInfo == null && type != null);
return fieldInfo;
}
public static object GetPropertyValue (this object obj, string propertyName) {
if (obj == null)
throw new ArgumentNullException (nameof (obj));
Type objType = obj.GetType ();
var propertyInfo = GetPropertyInfo (objType, propertyName);
if (propertyInfo == null)
throw new ArgumentOutOfRangeException (propertyName,
$"Couldn't find property {propertyName} in type {objType.FullName}");
return propertyInfo.GetValue (obj, null);
}
public static void SetPropertyValue (this object obj, string propertyName, object val) {
if (obj == null)
throw new ArgumentNullException (nameof (obj));
Type objType = obj.GetType ();
var propertyInfo = GetPropertyInfo (objType, propertyName);
if (propertyInfo == null)
throw new ArgumentOutOfRangeException (propertyName,
$"Couldn't find property {propertyName} in type {objType.FullName}");
propertyInfo.SetValue (obj, val, null);
}
private static PropertyInfo GetPropertyInfo (Type type, string propertyName) {
PropertyInfo propertyInfo = null;
do {
propertyInfo = type.GetProperty (propertyName, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
type = type.BaseType;
} while (propertyInfo == null && type != null);
return propertyInfo;
}
}
}
View File
+144
View File
@@ -0,0 +1,144 @@
using System;
using System.IO;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.Logging;
using xCommons.Extensions;
using xCommons.Models;
namespace xCommons.Middlewares {
public partial class XRequestLogger {
private readonly ILogger logger;
private readonly RequestDelegate next;
public XRequestLogger (
RequestDelegate next,
ILoggerFactory loggerFactory
) {
//
this.next = next;
this.logger = loggerFactory
.CreateLogger<XRequestLogger> ();
}
public async Task InvokeAsync (HttpContext context) {
//
var logModel = new XLoggerModel ();
//
logModel.Path = context.Request.Path;
logModel.Schema = context.Request.Scheme;
logModel.Method = context.Request.Method;
logModel.Headers = context.Request.Headers;
logModel.Host = context.Request.Host.ToString ();
logModel.QueryString = context.Request.QueryString.ToString ();
logModel.UserID = context.User.Identity.IsAuthenticated ? context.User.Identity.Name : "Not Authenticated";
//
logModel.Connection = new XLoggerHttpConnection {
Id = context.Connection.Id,
RemoteIpAddress = context.Connection.RemoteIpAddress.ToString (),
RemotePort = context.Connection.RemotePort.ToString (),
LocalIpAddress = context.Connection.LocalIpAddress.ToString (),
LocalPort = context.Connection.LocalPort.ToString (),
};
//
// Check if a request is a Post Call so read data from Body ...
if (context.Request.Method.ToNormalString () == "post") {
//
context.Request.EnableBuffering ();
var request = await new StreamReader (context.Request.Body)
.ReadToEndAsync ();
//
context.Request.Body.Position = 0;
logModel.Request = request;
}
//
logModel.RequestedOn = DateTime.UtcNow;
//
// Do Request ...
await next.Invoke (context);
//
using (Stream originalRequest = context.Response.Body) {
try {
using (var memStream = new MemoryStream ()) {
//
context.Response.Body = memStream;
//
// All the Request processing as described above
// happens from here.
// Response handling starts from here
// set the pointer to the beginning of the
// memory stream to read
memStream.Position = 0;
//
// read the memory stream till the end
var response = await new StreamReader (memStream)
.ReadToEndAsync ();
//
logModel.Response = response;
logModel.RespondedOn = DateTime.UtcNow;
logModel.StatusCode = context.Response.StatusCode;
logModel.IsSucceed = context.Response.StatusCode >= 200 && context.Response.StatusCode <= 299;
//
// since we have read till the end of the stream,
// reset it onto the first position
memStream.Position = 0;
//
// now copy the content of the temporary memory
// stream we have passed to the actual response body
// which will carry the response out.
await memStream.CopyToAsync (originalRequest);
}
} catch (Exception ex) {
//
// Log Exception ...
logger.LogError ($"Error on Logging Request/Response ... {ex.ToJSON()}");
} finally {
//
// assign the response body to the actual context
context.Response.Body = originalRequest;
}
}
//
// Log Response ...
logger.LogCritical ($"Http Response/Response Information:{Environment.NewLine}" +
$"Schema:{logModel.Schema} " + Environment.NewLine +
$"Host: {logModel.Host} " + Environment.NewLine +
$"Path: {logModel.Path} " + Environment.NewLine +
$"Method: {logModel.Method} " + Environment.NewLine +
$"UserID: {logModel.UserID} " + Environment.NewLine +
$"QueryString: {context.Request.QueryString} " + Environment.NewLine +
$"Headers: {logModel.Headers.ToJSON()}" + Environment.NewLine +
$"" + Environment.NewLine +
$"Http Connection: " + Environment.NewLine +
$"Id: {logModel.Connection.Id}" + Environment.NewLine +
$"RemoteIpAddress: {logModel.Connection.RemoteIpAddress}" + Environment.NewLine +
$"RemotePort: {logModel.Connection.RemotePort}" + Environment.NewLine +
$"LocalIpAddress: {logModel.Connection.LocalIpAddress}" + Environment.NewLine +
$"LocalPort: {logModel.Connection.LocalPort}" + Environment.NewLine +
$"" + Environment.NewLine +
$"Request Body: {logModel.Request}" + Environment.NewLine +
$"RequestedOn: {logModel.RequestedOn}" + Environment.NewLine +
$"" + Environment.NewLine +
$"IsSucceed: {logModel.IsSucceed}" + Environment.NewLine +
$"StatucCode: {logModel.StatusCode}" + Environment.NewLine +
$"Response Body: {logModel.Response}" + Environment.NewLine +
$"RespondedOn: {logModel.RespondedOn}" + Environment.NewLine +
$"" + Environment.NewLine
);
}
}
}
+6
View File
@@ -0,0 +1,6 @@
namespace xCommons.Models {
public partial class XCertificate {
public string Path { get; set; }
public string Secret { get; set; }
}
}
+29
View File
@@ -0,0 +1,29 @@
using System;
using Microsoft.AspNetCore.Http;
namespace xCommons.Models {
public class XLoggerModel {
public string Schema { get; set; }
public string Host { get; set; }
public string Path { get; set; }
public string Method { get; set; }
public string UserID { get; set; }
public string QueryString { get; set; }
public IHeaderDictionary Headers { get; set; }
public string Request { get; set; }
public int StatusCode { get; set; }
public bool IsSucceed { get; set; }
public string Response { get; set; }
public DateTime RequestedOn { get; set; }
public DateTime RespondedOn { get; set; }
public XLoggerHttpConnection Connection { get; set; }
}
public class XLoggerHttpConnection {
public string Id { get; set; }
public string RemoteIpAddress { get; set; }
public string RemotePort { get; set; }
public string LocalIpAddress { get; set; }
public string LocalPort { get; set; }
}
}
+39
View File
@@ -0,0 +1,39 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net.NetworkInformation;
using System.Threading.Tasks;
namespace xCommons.Models {
public class XNetworkInfo {
/// <summary>
/// Network Name ...
/// </summary>
/// <value></value>
public string Name { get; set; }
/// <summary>
/// Network Description ...
/// </summary>
/// <value></value>
public string Description { get; set; }
/// <summary>
/// IP Address which Exists on Current Network ...
/// </summary>
/// <value></value>
public string IP { get; set; }
/// <summary>
/// Current Networks Gateway Address ...
/// </summary>
/// <value></value>
public string Gateway { get; set; }
/// <summary>
/// Network Interface Object ...
/// </summary>
/// <value></value>
public NetworkInterface NetworkInterface { get; set; }
}
}
+405
View File
@@ -0,0 +1,405 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using xCommons.Extensions;
using xExceptions.Constants;
namespace xCommons.Providers {
public partial class XValidationProvider {
private ICollection<System.Action> validationGroup;
//
#region Simple Validators ...
/// <summary>
/// given objects must not null
/// </summary>
/// <param name="values"></param>
public void NotNull (
params object[] values) {
//
foreach (var o in values) {
//
if (o == null) {
XException.InvalidArgs.Throw ();
}
}
}
/// <summary>
/// given strings must not empty or null
/// </summary>
/// <param name="values"></param>
public void NotEmpty (
params string[] values) {
//
foreach (var s in values) {
//
if (s.IsNullOrEmpty ()) {
XException.InvalidArgs.Throw ();
}
}
}
/// <summary>
/// Check a numeric value is bigger than 0
/// </summary>
/// <param name="values"></param>
public void NotZero (
params int[] values) {
//
foreach (var s in values) {
//
if (s == 0) {
XException.InvalidArgs.Throw ();
}
}
}
/// <summary>
/// Check a numeric value is bigger than 0
/// </summary>
/// <param name="values"></param>
public void NotZero (
params long[] values) {
//
foreach (var s in values) {
//
if (s == 0) {
XException.InvalidArgs.Throw ();
}
}
}
/// <summary>
/// Check a numeric value is bigger than 0
/// </summary>
/// <param name="values"></param>
public void NotZero (
params decimal[] values) {
//
foreach (var s in values) {
//
if (s == 0) {
XException.InvalidArgs.Throw ();
}
}
}
/// <summary>
/// Check a Value is a Valid Guid ...
/// </summary>
/// <param name="values"></param>
public void IsGuid (params string[] values) {
//
foreach (var s in values) {
//
if (!s.IsGuid () || s.IsDefaultGuid ()) {
XException.InvalidArgs.Throw ();
}
}
}
/// <summary>
/// Check a Value is a Valid Guid ...
/// </summary>
/// <param name="values"></param>
public void IsGuid (params Guid[] values) {
//
foreach (var s in values) {
//
if (s.IsNull () || s.IsDefaultGuid ()) {
XException.InvalidArgs.Throw ();
}
}
}
/// <summary>
/// Check a Value is an MD5 ...
/// </summary>
/// <param name="values"></param>
public void IsMD5 (params string[] values) {
//
foreach (var s in values) {
//
if (!s.IsMD5String ()) {
XException.InvalidArgs.Throw ();
}
}
}
/// <summary>
/// non zero childs
/// </summary>
/// <param name="values"></param>
public void NotZeroChilds (
params IEnumerable<object>[] values) {
//
foreach (var s in values) {
//
if (s == null ||
s.Count () == 0) {
XException.InvalidArgs.Throw ();
}
}
}
/// <summary>
/// non zero childs
/// </summary>
/// <param name="values"></param>
public void NotZeroChilds (
params ICollection<object>[] values) {
//
foreach (var s in values) {
//
if (s == null ||
s.Count == 0) {
XException.InvalidArgs.Throw ();
}
}
}
/// <summary>
/// given string must be a valid URL ...
/// </summary>
/// <param name="url"></param>
/// <param name="exception"></param>
public void Url (
string url,
Exception exception = null
) {
//
NotEmpty (url);
//
if (exception == null) {
exception = XException.InavlidUrl.ToException ();
}
//
if (!url.IsValidUrl ()) {
throw exception;
}
}
/// <summary>
/// given string must be a valid Email Address ...
/// </summary>
/// <param name="emailAdress"></param>
/// <param name="exception"></param>
public void EmailAddress (
string emailAdress,
Exception exception = null
) {
//
NotEmpty (emailAdress);
//
if (exception == null) {
exception = XException.InvalidEmailAddress.ToException ();
}
//
if (!emailAdress.IsValidEmail ()) {
throw exception;
}
}
/// <summary>
/// given string must be a valid Mobile Number ...
/// </summary>
/// <param name="mobileNumber"></param>
/// <param name="exception"></param>
public void MobileNumber (
string mobileNumber,
Exception exception = null
) {
//
NotEmpty (mobileNumber);
//
if (exception == null) {
exception = XException.InvalidMobileNumber.ToException ();
}
//
if (!mobileNumber.IsValidMobileNumber ()) {
throw exception;
}
}
#endregion
//
#region Group Validatos ...
public XValidationProvider GroupValidationBuilder () {
//
validationGroup = new List<System.Action> ();
//
return this;
}
public XValidationProvider AddNotEmpty (params string[] values) {
//
this.validationGroup.Add (() =>
this.NotEmpty (values)
);
//
return this;
}
public XValidationProvider AddNotNull (params object[] values) {
//
this.validationGroup.Add (() =>
this.NotNull (values)
);
//
return this;
}
public XValidationProvider AddNotZero (params int[] values) {
//
this.validationGroup.Add (() =>
this.NotZero (values)
);
//
return this;
}
public XValidationProvider AddNotZero (params long[] values) {
//
this.validationGroup.Add (() =>
this.NotZero (values)
);
//
return this;
}
public XValidationProvider AddNotZero (params decimal[] values) {
//
this.validationGroup.Add (() =>
this.NotZero (values)
);
//
return this;
}
public XValidationProvider AddIsGuid (params string[] values) {
//
this.validationGroup.Add (() =>
this.IsGuid (values)
);
//
return this;
}
public XValidationProvider AddIsGuid (params Guid[] values) {
//
this.validationGroup.Add (() =>
this.IsGuid (values)
);
//
return this;
}
public XValidationProvider AddIsMD5 (params string[] values) {
//
this.validationGroup.Add (() =>
this.IsMD5 (values)
);
//
return this;
}
public XValidationProvider AddNotZeroChilds (params IEnumerable<object>[] values) {
//
this.validationGroup.Add (() =>
this.NotZeroChilds (values)
);
//
return this;
}
public XValidationProvider AddNotZeroChilds (params ICollection<object>[] values) {
//
this.validationGroup.Add (() =>
this.NotZeroChilds (values)
);
//
return this;
}
public XValidationProvider AddEmailAddress (
string emailAdress,
Exception exception = null) {
//
this.validationGroup.Add (() =>
this.EmailAddress (emailAdress, exception)
);
//
return this;
}
public XValidationProvider AddMobileNumber (
string mobileNumber,
Exception exception = null) {
//
this.validationGroup.Add (() =>
this.MobileNumber (mobileNumber, exception)
);
//
return this;
}
public XValidationProvider AddUrl (
string url,
Exception exception = null) {
//
this.validationGroup.Add (() =>
this.Url (url, exception)
);
//
return this;
}
public void ValidateGroup () {
//
// Run each Tasks ...
foreach (var action in validationGroup) {
action.Invoke ();
}
//
// Clear Task List ...
validationGroup.Clear ();
}
public async Task ValidateGroupAsync () {
//
// Run each Tasks ...
foreach (var action in validationGroup) {
await Task.Run (action);
}
//
// Clear Task List ...
validationGroup.Clear ();
}
#endregion
}
}
+148
View File
@@ -0,0 +1,148 @@
# xCommons
it is a Part of xDashboard on SaherElm IT Center which provides:
- Common Configuration Models.
- Common Usefull extra Extensions.
- Data Validation Provider.
- Provided features such as Enums, Models, Attributes, Filters, Authorization Policies, Middlewares and Helpers.
- etc.
this module has no dependency and itself uses as a base dependency for all XProject modules/
for configure and use this Module refer to DI.XDIHelperExtension.cs file.
## Implementing
after adding this package as a dependency to your project you can do following:
### 1. Register it on DI
```c#
public void ConfigureServices (IServiceCollection services) {
...
//
// Register Validation Provider and all XCommons Module Services ...
services.AddXCommons ();
...
}
```
this will provide XValidationHelper service which accessible through DI.
### 2. Register Application Configuration on DI
since many of features in this Framework works by accessing the configuration of class application. you had to register it on DI.
configure you app in **appSettings.json**:
```javascript
{
...
"Version": "0.1",
"Name": "SaherElm Sample App",
"DefaultLanguage": "fa-IR",
"XPoweredValue": "SaherElmITCenter",
"WelcomeMessage": "Welcome to Application",
"AllowedOrigins": [
"http://localhost:4200",
"https://localhost:4200"
],
...
},
```
then register your configuration on DI in **Startup** file:
```c#
public void ConfigureServices (IServiceCollection services) {
...
//
// Register App Configuration ...
services.AddXAppConfiguration (Configuration);
var appConfiguration = services.GetRegisteredService<XAppConfiguration> ();
...
}
```
### 3. Register Available Cross Origin Resource sharing (Cors)
for determining which addresses can access your application and enabling core mechanism you can simply do it by follow this structure ...
**NOTE**: notice that you have configured allowed origins in **appSettings.json** before on AppConfiguration section.
```c#
public void ConfigureServices (IServiceCollection services) {
...
//
// Register Allowed Origins ...
services.AddXCors (appConfiguration.AllowedOrigins);
...
}
```
the you can enable cors handling like this:
```c#
public void Configure (IApplicationBuilder app, IWebHostEnvironment env) {
...
//
// Using Cors ...
app.UseXCors ();
...
}
```
**Note**: remember **AllowedOrigins** can provided using **appSettings.json** file dynamically;
### 4. Enable Swagger
also you can add swagger documentation to your project:
```c#
public void ConfigureServices (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;
});
//
// Register Swagger ...
var xmlFile = $"{Assembly.GetExecutingAssembly().GetName().Name}.xml";
var xmlPath = Path.Combine (AppContext.BaseDirectory, xmlFile);
services.AddXSwagger (Configuration, xmlFilePath : xmlPath);
...
}
```
the you can enable swagger middleware like this:
```c#
public void Configure (IApplicationBuilder app, IWebHostEnvironment env) {
...
//
// Use Swagger Middleware ...
app.UseXSwagger ();
...
}
```
## Maintainer
Hadi Khazaee asl
[https://www.saherelm.ir](https://www.saherelm.ir)
[hadi_khazaee_asl@yahoo.com](mailto:hadi_khazaee_asl@yahoo.com)
+7
View File
@@ -0,0 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<packageSources>
<add key="nuget" value="https://api.nuget.org/v3/index.json" protocolVersion="3" />
<add key="liget" value="https://nuget.saherelmhub.ir/v3/index.json" protocolVersion="3" />
</packageSources>
</configuration>
+63
View File
@@ -0,0 +1,63 @@
<Project Sdk="Microsoft.NET.Sdk">
<!-- Runtime Definition -->
<PropertyGroup>
<TargetFramework>netstandard2.0</TargetFramework>
<PackageId>xDashboard.xCommons</PackageId>
<Version>1.0.0</Version>
<Authors>Hadi Khazaee Asl</Authors>
<Company>SaherElm IT Center</Company>
<Description>
provide all commonly used actions/extensions and classes which required to xDashboard project.
</Description>
<!-- Icon Definition -->
<PackageIcon>icon.png</PackageIcon>
</PropertyGroup>
<!-- Icon Handling -->
<ItemGroup>
<None Include="../../Resources/Images/favicon.png" Link="icon.png" Pack="true" PackagePath="\icon.png" />
</ItemGroup>
<!-- Local Dependencies -->
<ItemGroup>
<PackageReference Include="xDashboard.xExceptions" Version="1.0.0" />
<!-- <ProjectReference Include="../xExceptions/xExceptions.csproj" /> -->
</ItemGroup>
<!-- Dependencies -->
<ItemGroup>
<PackageReference Include="AutoMapper" Version="10.1.1" />
<PackageReference Include="IdentityModel" Version="5.0.1" />
<PackageReference Include="System.Reactive" Version="5.0.0" />
<PackageReference Include="Newtonsoft.Json" Version="12.0.3" />
<PackageReference Include="libphonenumber-csharp" Version="8.12.17" />
<PackageReference Include="Microsoft.AspNetCore.Cors" Version="2.2.0" />
<PackageReference Include="Microsoft.AspNetCore.Mvc.Core" Version="2.2.5" />
<PackageReference Include="Microsoft.Extensions.Configuration" Version="5.0.0" />
<PackageReference Include="Microsoft.IO.RecyclableMemoryStream" Version="1.4.0" />
<PackageReference Include="Microsoft.AspNetCore.Mvc.Abstractions" Version="2.2.0" />
<PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="5.0.1" />
<PackageReference Include="Microsoft.AspNetCore.Authorization.Policy" Version="2.2.0" />
<PackageReference Include="Microsoft.Extensions.Configuration.Binder" Version="5.0.0" />
<PackageReference Include="Microsoft.AspNetCore.Authentication.JwtBearer" Version="2.2.0" />
<PackageReference Include="Microsoft.AspNetCore.Authentication.Abstractions" Version="2.2.0" />
<PackageReference Include="AutoMapper.Extensions.Microsoft.DependencyInjection" Version="8.1.0" />
</ItemGroup>
<!-- Swagger -->
<ItemGroup>
<PackageReference Include="Swashbuckle.AspNetCore" Version="6.0.2" />
<PackageReference Include="Swashbuckle.AspNetCore.SwaggerGen" Version="6.0.2" />
<PackageReference Include="Swashbuckle.AspNetCore.SwaggerUI" Version="6.0.2" />
</ItemGroup>
<!-- For XML Documentation Support -->
<PropertyGroup>
<CopyLocalLockFileAssemblies>true</CopyLocalLockFileAssemblies>
<GenerateDocumentationFile>true</GenerateDocumentationFile>
<NoWarn>$(NoWarn);1591</NoWarn>
</PropertyGroup>
</Project>