
### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xAiModels\Configurations\Entities\XAiConversationEntityConfiguration.cs

using System;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Metadata.Builders;
using xAiModels.Constants;
using xAiModels.Models.Entities;
using xDataService.Providers;

namespace xAiModels.Configurations.Entities
{
    public class XAiConversationEntityConfiguration : XBaseEntityTypeConfiguration<XAiConversation, Guid>
    {
        public override void Configure(EntityTypeBuilder<XAiConversation> builder)
        {
            builder.ToTable(XAiModelsConstants.XAiConversationTable);
        }
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xAiModels\Configurations\Entities\XAiConversationMappingAction.cs

using System;
using AutoMapper;
using xAiModels.Interfaces;
using xAiModels.Models.Dtos;
using xAiModels.Models.Entities;
using xIdentityService.Extensions;
using xIdentityService.Interfaces;

namespace xAiModels.Configurations.Entities
{
    public class XAiConversationMappingAction : IMappingAction<XAiConversation, XAiConversationDto>
    {
        private readonly IXIdentityProvider identityProvider;
        private readonly IXAiProjectTitleResourceProvider projectTitleResourceProvider;
        private readonly IXAiConversationTitleResourceProvider conversationTitleResourceProvider;
        private readonly IXAiProjectDescriptionResourceProvider projectDescriptionResourceProvider;

        public XAiConversationMappingAction(
            IXIdentityProvider identityProvider,
            IXAiProjectTitleResourceProvider projectTitleResourceProvider,
            IXAiConversationTitleResourceProvider conversationTitleResourceProvider,
            IXAiProjectDescriptionResourceProvider projectDescriptionResourceProvider
        )
        {
            this.identityProvider = identityProvider;
            this.projectTitleResourceProvider = projectTitleResourceProvider;
            this.conversationTitleResourceProvider = conversationTitleResourceProvider;
            this.projectDescriptionResourceProvider = projectDescriptionResourceProvider;
        }

        public void Process(
            XAiConversation source,
            XAiConversationDto destination,
            ResolutionContext context
        )
        {
            //
            // Retrieve Owner ...
            var device = identityProvider.GetDevice();
            var ownerUserInfo = identityProvider.GetUserInfo(
                device: device,
                userSelectByParam: source.OwnerId
            )
            .GetAwaiter()
            .GetResult();
            var owner = ownerUserInfo.ToXPersonDto();

            //
            // Setting Owner ...
            destination.Owner = owner;

            // Retrieve Project Info ...
            throw new NotImplementedException();
        }
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xAiModels\Configurations\Entities\XAiMessageEntityConfiguration.cs

using System;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Metadata.Builders;
using xAiModels.Constants;
using xAiModels.Models.Entities;
using xDataService.Providers;

namespace xAiModels.Configurations.Entities
{
    public class XAiMessageEntityConfiguration : XBaseEntityTypeConfiguration<XAiMessage, Guid>
    {
        public override void Configure(EntityTypeBuilder<XAiMessage> builder)
        {
            builder.ToTable(XAiModelsConstants.XAiMessageTable);
        }
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xAiModels\Configurations\Entities\XAiMessageMappingAction.cs

using System;
using AutoMapper;
using xAiModels.Models.Dtos;
using xAiModels.Models.Entities;
using xIdentityService.Extensions;
using xIdentityService.Interfaces;

namespace xAiModels.Configurations.Entities
{
    public class XAiMessageMappingAction : IMappingAction<XAiMessage, XAiMessageDto>
    {
        private readonly IXIdentityProvider identityProvider;

        public XAiMessageMappingAction(
            IXIdentityProvider identityProvider
        )
        {
            this.identityProvider = identityProvider;
        }
        
        public void Process(
            XAiMessage source, 
            XAiMessageDto destination, 
            ResolutionContext context
        )
        {
            //
            // Retrieve Owner ...
            var device = identityProvider.GetDevice();
            var ownerUserInfo = identityProvider.GetUserInfo(
                device: device,
                userSelectByParam: source.OwnerId
            )
            .GetAwaiter()
            .GetResult();
            var owner = ownerUserInfo.ToXPersonDto();

            //
            // Setting Owner ...
            destination.Owner = owner;
            
            //
            // Retrieve Owner ...
            // Retrieve Conversation ...
            throw new NotImplementedException();
        }
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xAiModels\Configurations\Entities\XAiProjectEntityConfiguration.cs

using System;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Metadata.Builders;
using xAiModels.Constants;
using xAiModels.Models.Entities;
using xDataService.Providers;

namespace xAiModels.Configurations.Entities
{
    public class XAiProjectEntityConfiguration : XBaseEntityTypeConfiguration<XAiProject, Guid>
    {
        public override void Configure(EntityTypeBuilder<XAiProject> builder)
        {
            builder.ToTable(XAiModelsConstants.XAiProjectTable);
        }
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xAiModels\Configurations\Entities\XAiProjectMappingAction.cs

using System;
using AutoMapper;
using xAiModels.Models.Dtos;
using xAiModels.Models.Entities;
using xIdentityService.Extensions;
using xIdentityService.Interfaces;

namespace xAiModels.Configurations.Entities
{
    public class XAiProjectMappingAction : IMappingAction<XAiProject, XAiProjectDto>
    {
        private readonly IXIdentityProvider identityProvider;

        public XAiProjectMappingAction(
            IXIdentityProvider identityProvider
        )
        {
            this.identityProvider = identityProvider;
        }
        
        public void Process(
            XAiProject source,
            XAiProjectDto destination,
            ResolutionContext context
        )
        {
            //
            // Retrieve Owner ...
            var device = identityProvider.GetDevice();
            var ownerUserInfo = identityProvider.GetUserInfo(
                device: device,
                userSelectByParam: source.OwnerId
            )
            .GetAwaiter()
            .GetResult();
            var owner = ownerUserInfo.ToXPersonDto();

            //
            // Setting Owner ...
            destination.Owner = owner;
            
            //
            // Retrieve Owner ...
            // Retrieve Title Resources ...
            // Retrieve Description Resources ...
            throw new NotImplementedException();
        }
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xAiModels\Configurations\XAiApiConfiguration.cs

using xAiModels.Constants;
using xAiModels.Models;

namespace xAiModels.Configurations
{
    public class XAiApiConfiguration
    {
        /// <summary>
        /// Model Providers ...
        /// </summary>
        public XAiModelDescriptor[] Models { get; set; } = [];

        /// <summary>
        /// Each User must Has a Default Project, this is Title Resource Identifier ... 
        /// </summary>
        public string DefaultProjectTitleResource { get; set; } = XAiModelsConstants.DefaultXAiProjectTitleResourceID;

        /// <summary>
        /// Each User must Has a Default Project, this is Description Resource Identifier ... 
        /// </summary>
        public string DefaultProjectDescriptionResource { get; set; } = XAiModelsConstants.DefaultXAiProjectDescriptionResourceID;

        /// <summary>
        /// Each User must Has a Default Conversation, this is Title Resource Identifier ...  ...
        /// </summary>
        public string DefaultConversationTitleResource { get; set; } = XAiModelsConstants.DefaultXAiConversationTitleResourceID;
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xAiModels\Configurations\XAiModelMappersProfile.cs

using AutoMapper;
using xAiModels.Configurations.Entities;
using xAiModels.Models.Dtos;
using xAiModels.Models.Entities;

namespace xAiModels.Configurations
{
    public class XAiModelMappersProfile : Profile
    {
        public XAiModelMappersProfile()
        {
            //
            // XAiMessage ...
            CreateMap<XAiMessage, XAiMessageDto>()
                .AfterMap<XAiMessageMappingAction>();

            //
            // XAiProject ...
            CreateMap<XAiProject, XAiProjectDto>()
            .AfterMap<XAiProjectMappingAction>();

            //
            // XAiConversation ...
            CreateMap<XAiConversation, XAiConversationDto>()
            .AfterMap<XAiConversationMappingAction>();
        }
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xAiModels\Constants\ConfigurationNodeNames.cs

namespace xAiModels.Constants
{
    public partial struct ConfigurationNodeNames
    {
        public const string AI_API_NODE = "AiApiConfiguration";
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xAiModels\Constants\XAiChatRole.cs

using xExceptions.Attributes;

namespace xAiModels.Constants
{
    public struct XAiChatRoles
    {
        public const string None = "none";
        public const string User = "user";
        public const string Tool = "tool";
        public const string System = "system";
        public const string Assistant = "assistant";
    }

    public enum XAiChatRole
    {
        [StringValue(XAiChatRoles.None)]
        None,
        [StringValue(XAiChatRoles.User)]
        User,
        [StringValue(XAiChatRoles.Tool)]
        Tool,
        [StringValue(XAiChatRoles.System)]
        System,
        [StringValue(XAiChatRoles.Assistant)]
        Assistant,
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xAiModels\Constants\XAiModelProviderType.cs

namespace xAiModels.Constants
{
    /// <summary>
    /// Specifiy Provider Type ...
    /// </summary>
    public enum XAiModelProviderType
    {
        None,
        Ollama,
        DeepSeek,
        HuggingFace        
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xAiModels\Constants\XAiModelsConstants.cs

namespace xAiModels.Constants
{
    public struct XAiModelsConstants
    {
        //
        // Service Extensions Log Tag ...
        public const string XAiModelsDILogTag = "XAiModels";
        
        //
        // Table Mapping Identifiers ...
        public const string XAiMessageTable = "AiMessages";
        public const string XAiProjectTable = "AiProjects";
        public const string XAiConversationTable = "AiConversations";

        //
        // GraphQL Collection Mappings ...
        public const string XAiMessageSingleName = "aiMessage";
        public const string XAiProjectSingleName = "aiProject";
        public const string XAiConversationSignleName = "aiConversation";

        public const string XAiMessageCollectionName = "aiMessages";
        public const string XAiProjectCollectionName = "AiProjectsa";
        public const string XAiConversationCollectionName = "aiConversations";

        //
        // Hubs ...
        public const string XAiMessageDtoHub = "aiMessageDto";
        public const string XAiMessageEntityHub = "aiMessageEntity";

        public const string XAiProjectDtoHub = "aiProjectDto";
        public const string XAiProjectEntityHub = "aiProjectEntity";

        public const string XAiConversationDtoHub = "aiConversationDto";
        public const string XAiConversationEntityHub = "aiConversationEntity";

        //
        // Resource Provider Identifiers ...
        public const string XAiProjectTitleIdentifier = "AiPrjT";
        public const string XAiProjectDescriptionIdentifier = "AiPrjD";
        public const string XAiConversationTitleIdentifier = "AiCnvrT";

        //
        // EF Repositories Helper Extensions ...
        public const string GetXAiMessageEFRepositoryDescriptor = "GetXAiMessageEFRepositoryDescriptor";
        public const string GetXAiProjectEFRepositoryDescriptor = "GetXAiProjectEFRepositoryDescriptor";
        public const string GetXAiConversationEFRepositoryDescriptor = "GetXAiConversationEFRepositoryDescriptor";

        //
        public const string DefaultXAiProjectTitleResourceID = "XAiPrjT";         
        public const string DefaultXAiConversationTitleResourceID = "XAiCnvT";         
        public const string DefaultXAiProjectDescriptionResourceID = "XAiPrjD";         
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xAiModels\DI\XDIHelperExtension.cs

using System;
using Microsoft.AspNetCore.Builder;
using Microsoft.Extensions.DependencyInjection;
using xAiModels.Providers.Dtos;
using xAiModels.Providers.Entities;
using xCommons.Extensions;
using xDataService.Constants;
using xDataService.Db;
using xDataService.Models;
using xExceptions.Constants;
using xPushService.Helpers;
using xPushService.DI;
using xDataService.DI;
using xAiModels.Interfaces.Dtos;
using xAiModels.Helpers;
using xCommons.Helpers;
using xAiModels.Interfaces.Entities;
using xAiModels.Interfaces;
using xAiModels.Providers;
using xAiModels.Constants;

namespace xAiModels.DI
{
    /// <summary>
    /// Service Registration Extensions Classes ...
    /// </summary>
    public static class XDIHelperExtension
    {
        /// <summary>
        /// Register Service ...
        /// </summary>
        /// <param name="services"></param>
        /// <param name="repositoryType"></param>
        /// <param name="lifeTime"></param>
        public static void AddXAiDataService(
            this IServiceCollection services,
            XRepositoryType repositoryType,
            ServiceLifetime lifeTime = ServiceLifetime.Scoped
        )
        {
            AddAiDataService(
                contextType: null,
                services: services,
                lifeTime: lifeTime,
                repositoryType: repositoryType
            );
        }

        /// <summary>
        /// Register Service ...
        /// </summary>
        /// <typeparam name="TContext"></typeparam>
        /// <param name="services"></param>
        /// <param name="repositoryType"></param>
        /// <param name="lifeTime"></param>
        public static void AddXAiDataService<TContext>(
            this IServiceCollection services,
            XRepositoryType repositoryType,
            ServiceLifetime lifeTime = ServiceLifetime.Scoped
        )
        where TContext : XDbContext
        {
            AddAiDataService(
                services: services,
                lifeTime: lifeTime,
                contextType: typeof(TContext),
                repositoryType: repositoryType
            );
        }

        /// <summary>
        /// Use XSubCategoryService Middleware ... 
        /// </summary>
        /// <param name="app"></param>
        /// <param name="isDevelopmentEnvironment"></param>
        public static void UseXAiDataService(
            this IApplicationBuilder app,
            bool isDevelopmentEnvironment = false
        )
        {
            //
            #region Using Hubs ...
            //
            var pushHelper = new XPushServiceHelper();

            //
            // XAiMessage ...
            pushHelper.AddHub<XAiMessageDtoHub>(XAiModelsConstants.XAiMessageDtoHub);
            pushHelper.AddHub<XAiMessageEntityHub>(XAiModelsConstants.XAiMessageEntityHub);

            //
            // XAiProject ...
            pushHelper.AddHub<XAiProjectDtoHub>(XAiModelsConstants.XAiProjectDtoHub);
            pushHelper.AddHub<XAiProjectEntityHub>(XAiModelsConstants.XAiProjectEntityHub);

            //
            // XAiConversation ...
            pushHelper.AddHub<XAiConversationDtoHub>(XAiModelsConstants.XAiConversationDtoHub);
            pushHelper.AddHub<XAiConversationEntityHub>(XAiModelsConstants.XAiConversationEntityHub);

            //
            app.UseXPushService(pushHelper);
            #endregion

            //
            // Using XAiConversation Repository Descriptor ...
            if (!aiConversationDescriptor.IsNull())
            {
                //
                app.UseXRepository(
                    descriptor: aiConversationDescriptor,
                    isDevelopmentEnvironment: isDevelopmentEnvironment
                );
            }

            //
            // Using XAiMessage Repository Descriptor ...
            if (!aiMessageDescriptor.IsNull())
            {
                //
                app.UseXRepository(
                    descriptor: aiMessageDescriptor,
                    isDevelopmentEnvironment: isDevelopmentEnvironment
                );
            }

            //
            // Using XAiProject Repository Descriptor ...
            if (!aiProjectDescriptor.IsNull())
            {
                //
                app.UseXRepository(
                    descriptor: aiProjectDescriptor,
                    isDevelopmentEnvironment: isDevelopmentEnvironment
                );
            }

            //
            // Create an Scope for Services Acces ...
            // Handle Seeding Category/SubCategory Resources ...
            // TODO: Enable Seeding if Required ...
            // using (var scope = app.ApplicationServices.CreateScope())
            // {
            //     //
            //     // Retrieve Configuratuions ...
            //     var aiMessageProvider = scope.ServiceProvider.GetService<IXAiMessageServiceProvider>();
            //     var aiProjectProvider = scope.ServiceProvider.GetService<IXAiProjectServiceProvider>();
            //     var aiConversationProvider = scope.ServiceProvider.GetService<IXAiConversationServiceProvider>();
            //     var configuration = scope.ServiceProvider.GetService<XAiDataServiceServiceConfiguration>();
            //     if (!configuration.IsNullOrDefault() &&
            //         !categoryProvider.IsNullOrDefault() &&
            //         !subaiConversationDescriptor.IsNullOrDefault()
            //     )
            //     {
            //         //
            //         // Logging ...
            //         Log("Start Seeding ...");

            //         //
            //         // Count Data in Category ...
            //         var hasCategory = (categoryProvider.Count().GetAwaiter().GetResult()) > 0;
            //         var hasSubCategory = (subCategoryProvider.Count().GetAwaiter().GetResult()) > 0;

            //         //
            //         // Seed Category Resources ...
            //         var canSeed =
            //             !hasCategory &&
            //             configuration.Categories.HasChild();
            //         if (canSeed)
            //         {
            //             //
            //             // Loop through Provided items ...
            //             foreach (var cat in configuration.Categories)
            //             {
            //                 //
            //                 try
            //                 {
            //                     //
            //                     Log($"Start Seeding Category: {cat.Titles.Locales.ToArray()[0].Value} ...");

            //                     //
            //                     categoryProvider.Refresh(
            //                         resource: cat,
            //                         userInfo: null,
            //                         connectionId: null,
            //                         cancellationToken: default
            //                     )
            //                     .GetAwaiter()
            //                     .GetResult();

            //                     //
            //                     Log($"Seeding Category: {cat.Titles.Locales.ToArray()[0].Value} Finished Successfully ...");
            //                 }
            //                 catch (Exception ex)
            //                 {
            //                     Log($"Seeding Category: {cat.Titles.Locales.ToArray()[0].Value} Failed due: {ex.Message} ...");
            //                 }
            //             }
            //         }

            //         //
            //         // Seed SubCategory Resources ...
            //         canSeed =
            //             !hasSubCategory &&
            //             configuration.SubCategories.HasChild();
            //         if (canSeed)
            //         {
            //             //
            //             // Loop through Provided items ...
            //             foreach (var subcat in configuration.SubCategories)
            //             {
            //                 //
            //                 try
            //                 {
            //                     //
            //                     Log($"Start Seeding SubCategory: {subcat.Titles.Locales.ToArray()[0].Value} ...");

            //                     //
            //                     subCategoryProvider.Refresh(
            //                         userInfo: null,
            //                         resource: subcat,
            //                         connectionId: null,
            //                         cancellationToken: default
            //                     )
            //                     .GetAwaiter()
            //                     .GetResult();

            //                     //
            //                     Log($"Seeding SubCategory: {subcat.Titles.Locales.ToArray()[0].Value} Finished Successfully ...");
            //                 }
            //                 catch (Exception ex)
            //                 {
            //                     Log($"Seeding SubCategory: {subcat.Titles.Locales.ToArray()[0].Value} Failed due: {ex.Message} ...");
            //                 }
            //             }
            //         }

            //         //
            //         Log("Finish Seeding ...");
            //     }
            // }
        }

        //
        #region Private ...
        private static XRepositoryDescriptor aiMessageDescriptor = null;
        private static XRepositoryDescriptor aiProjectDescriptor = null;
        private static XRepositoryDescriptor aiConversationDescriptor = null;

        /// <summary>
        /// a LogTag for Service ...
        /// </summary>
        private static string XLogTag = XAiModelsConstants.XAiModelsDILogTag;

        /// <summary>
        /// print a log in Console ...
        /// </summary>
        /// <param name="message"></param>
        private static void Log(string message)
        {
            Console.WriteLine($"{XLogTag} => {message}");
        }

        /// <summary>
        /// Register Service ...
        /// </summary>
        /// <param name="services"></param>
        /// <param name="repositoryType"></param>
        /// <param name="contextType"></param>
        /// <param name="lifeTime"></param>
        private static void AddAiDataService(
            IServiceCollection services,
            XRepositoryType repositoryType,
            Type contextType = null,
            ServiceLifetime lifeTime = ServiceLifetime.Scoped
        )
        {
            //
            var exception = XException.InvalidArgs.ToException(); ;

            //
            // Services ...
            var isServicesExists = !services.IsNull();
            if (!isServicesExists)
            {
                //
                Log("Service Registration failed, services not provided ...");
                throw exception;
            }

            //
            // Lifetime ...
            var isLifetimeExists = !lifeTime.IsNull();
            if (!isLifetimeExists)
            {
                //
                Log("Service Registration failed, lifetime not provided ...");
                throw exception;
            }

            //
            // Validate Repository Type ...
            var isRepositoryTypeValid =
                (repositoryType == XRepositoryType.EF &&
                !contextType.IsNull()) ||
                ((repositoryType == XRepositoryType.Mongo ||
                    repositoryType == XRepositoryType.InMemory) &&
                contextType.IsNull());
            if (!isRepositoryTypeValid)
            {
                //
                Log("Service Registration failed, Invalid Repository Type and Context Type ...");
                throw exception;
            }

            //
            // Maske Instance of Repository Descriptor 
            // Based on Provided Type ...
            switch (repositoryType)
            {
                //
                case XRepositoryType.EF:
                    //
                    // XAiMessage ...
                    aiMessageDescriptor = typeof(XAiModelsHelper)
                        .InvokeGenericMethod<XRepositoryDescriptor>(
                            args: null,
                            runtimeType: contextType,
                            methodName: XAiModelsConstants.GetXAiMessageEFRepositoryDescriptor
                    );

                    //
                    // XAiProject ...
                    aiProjectDescriptor = typeof(XAiModelsHelper)
                        .InvokeGenericMethod<XRepositoryDescriptor>(
                            args: null,
                            runtimeType: contextType,
                            methodName: XAiModelsConstants.GetXAiProjectEFRepositoryDescriptor
                    );

                    //
                    // XAiConversation ...
                    aiConversationDescriptor = typeof(XAiModelsHelper)
                        .InvokeGenericMethod<XRepositoryDescriptor>(
                            args: null,
                            runtimeType: contextType,
                            methodName: XAiModelsConstants.GetXAiConversationEFRepositoryDescriptor
                    );
                    break;

                //
                case XRepositoryType.Mongo:
                    //
                    // XAiMessage ...
                    aiMessageDescriptor = XAiModelsHelper.GetXAiMessageMongoRepositoryDescriptor();

                    //
                    // XAiProject ...
                    aiProjectDescriptor = XAiModelsHelper.GetXAiProjectMongoRepositoryDescriptor();

                    //
                    // XAiConversation ...
                    aiConversationDescriptor = XAiModelsHelper.GetXAiConversationMongoRepositoryDescriptor();
                    break;

                //
                case XRepositoryType.InMemory:
                    //
                    // XAiMessage ...
                    aiMessageDescriptor = XAiModelsHelper.GetXAiMessageInMemoryRepositoryDescriptor();

                    //
                    // XAiProject ...
                    aiProjectDescriptor = XAiModelsHelper.GetXAiProjectInMemoryRepositoryDescriptor();

                    //
                    // XAiConversation ...
                    aiConversationDescriptor = XAiModelsHelper.GetXAiConversationInMemoryRepositoryDescriptor();
                    break;
            }

            //
            #region Register Repository Descriptor ...
            //
            // XAiMessage ...
            if (!aiMessageDescriptor.IsNull())
            {
                //
                services.AddXRepository(
                    lifeTime: lifeTime,
                    descriptor: aiMessageDescriptor
                );
            }

            //
            // XAiProject ...
            if (!aiProjectDescriptor.IsNull())
            {
                //
                services.AddXRepository(
                    lifeTime: lifeTime,
                    descriptor: aiProjectDescriptor
                );
            }

            //
            // XAiConversation ...
            if (!aiConversationDescriptor.IsNull())
            {
                //
                services.AddXRepository(
                    lifeTime: lifeTime,
                    descriptor: aiConversationDescriptor
                );
            }
            #endregion

            //
            #region Register Services ...
            //
            #region AiMessage ...
            //
            // Models ...
            services.Add(
                new ServiceDescriptor(typeof(IXAiMessageServiceProvider), typeof(XAiMessageServiceProvider), lifeTime)
            );
            services.Add(
                new ServiceDescriptor(typeof(IXAiMessageRepositoryService), typeof(XAiMessageRepositoryService), lifeTime)
            );
            services.Add(
                new ServiceDescriptor(typeof(IXAiMessageRepositoryProvider), typeof(XAiMessageRepositoryProvider), lifeTime)
            );
            #endregion

            //
            #region AiProject ...
            //
            // Models ...
            services.Add(
                new ServiceDescriptor(typeof(IXAiProjectServiceProvider), typeof(XAiProjectServiceProvider), lifeTime)
            );
            services.Add(
                new ServiceDescriptor(typeof(IXAiProjectRepositoryService), typeof(XAiProjectRepositoryService), lifeTime)
            );
            services.Add(
                new ServiceDescriptor(typeof(IXAiProjectRepositoryProvider), typeof(XAiProjectRepositoryProvider), lifeTime)
            );

            //
            // Resource Providers ...
            services.Add(
                new ServiceDescriptor(typeof(IXAiProjectTitleResourceProvider), typeof(XAiProjectTitleResourceProvider), lifeTime)
            );
            services.Add(
                new ServiceDescriptor(typeof(IXAiProjectDescriptionResourceProvider), typeof(XAiProjectDescriptionResourceProvider), lifeTime)
            );
            #endregion

            //
            #region AiConversation ...
            //
            // Models ...
            services.Add(
                new ServiceDescriptor(typeof(IXAiConversationServiceProvider), typeof(XAiConversationServiceProvider), lifeTime)
            );
            services.Add(
                new ServiceDescriptor(typeof(IXAiConversationRepositoryService), typeof(XAiConversationRepositoryService), lifeTime)
            );
            services.Add(
                new ServiceDescriptor(typeof(IXAiConversationRepositoryProvider), typeof(XAiConversationRepositoryProvider), lifeTime)
            );

            //
            // Resource Providers ...
            services.Add(
                new ServiceDescriptor(typeof(IXAiConversationTitleResourceProvider), typeof(XAiConversationTitleResourceProvider), lifeTime)
            );
            #endregion
            #endregion

            //
            Log("Service Regitration Succeed ...");
        }
        #endregion        
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xAiModels\Extensions\ChatResponseExtensions.cs

using Microsoft.Extensions.AI;
using xCommons.Extensions;

namespace xAiModels.Extensions
{
    public static class ChatResponseExtensions
    {
        /// <summary>
        /// Validate a Chat Response ...
        /// </summary>
        /// <param name="source"></param>
        /// <returns></returns>
        public static bool IsValid(this ChatResponse source)
        {
            //
            var result =
                source is not null &&
                !source.IsNullOrDefault() &&
                !string.IsNullOrWhiteSpace(source.Text) &&
                source.FinishReason == ChatFinishReason.Stop;

            //
            return result;
        }
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xAiModels\Extensions\ChatRoleExtensions.cs

using Microsoft.Extensions.AI;
using xAiModels.Constants;
using xCommons.Extensions;

namespace xAiModels.Extensions
{
    /// <summary>
    /// Extensions for ChatRole ...
    /// </summary>
    public static class ChatRoleExtensions
    {
        /// <summary>
        /// Normalize an String to Propper Chat Role Value ...
        /// <see cref="XAiChatRoles"/>>
        /// </summary>
        /// <param name="source"></param>
        /// <returns></returns>
        public static string GetChatRoleTitle(this string source)
        {
            //
            var result = XAiChatRoles.None;

            //
            if (source.ToNormalString() == XAiChatRoles.None.ToNormalString())
            {
                result = XAiChatRoles.None;
            }
            else if (source.ToNormalString() == XAiChatRoles.User.ToNormalString())
            {
                result = XAiChatRoles.User;
            }
            else if (source.ToNormalString() == XAiChatRoles.Tool.ToNormalString())
            {
                result = XAiChatRoles.Tool;
            }
            else if (source.ToNormalString() == XAiChatRoles.System.ToNormalString())
            {
                result = XAiChatRoles.System;
            }
            else if (source.ToNormalString() == XAiChatRoles.Assistant.ToNormalString())
            {
                result = XAiChatRoles.Assistant;
            }

            //
            return result;
        }

        /// <summary>
        /// Get Chat Role Title from Chat Role Class ...
        /// <see cref="XAiChatRoles"/>
        /// </summary>
        /// <param name="source"></param>
        /// <returns></returns>
        public static string GetRole(this ChatRole source)
        {
            //
            var result = source.Value
                .GetChatRoleTitle();

            //
            return result;
        }

        /// <summary>
        /// Generate Chat Role Class Based on role Title ...
        /// </summary>
        /// <param name="source"></param>
        /// <returns></returns>
        public static ChatRole ToChatRole(this string source)
        {
            //
            var role = source.GetChatRoleTitle();
            ChatRole result = new ChatRole(role);

            //
            return result;
        }

        /// <summary>
        /// Generate Chat Role Class Based on role Title ...
        /// </summary>
        /// <param name="source"></param>
        /// <returns></returns>
        public static ChatRole ToChatRole(this XAiChatRole source)
        {
            //
            var role = source.GetStringValue();
            ChatRole result = new ChatRole(role);

            //
            return result;
        }

        /// <summary>
        /// Extract Chat Role Enum from Chat Role ...
        /// <see cref="ChatRole"/>
        /// <see cref="XAiChatRole"/>
        /// </summary>
        /// <param name="source"></param>
        /// <returns></returns>
        public static XAiChatRole ToChatRole(this ChatRole source)
        {
            //
            var role = source
                .GetRole()
                .GetChatRoleTitle();

            //
            XAiChatRole result = XAiChatRole.User;

            //
            if (role == XAiChatRoles.User)
            {
                result = XAiChatRole.User;
            }
            else if (role == XAiChatRoles.Tool)
            {
                result = XAiChatRole.Tool;
            }
            else if (role == XAiChatRoles.System)
            {
                result = XAiChatRole.System;
            }
            else if (role == XAiChatRoles.Assistant)
            {
                result = XAiChatRole.Assistant;
            }

            //
            return result;
        }

        /// <summary>
        /// Validate an String as Chat Role ...
        /// </summary>
        /// <param name="source"></param>
        /// <returns></returns>
        public static bool IsValid(this string source)
        {
            //
            var result =
                source != XAiChatRoles.None &&
                source.ToNormalString() != XAiChatRoles.None.ToNormalString();

            //
            return result;
        }

        /// <summary>
        /// Validate Role ...
        /// <see cref="XAiChatRole"/>>
        /// </summary>
        /// <param name="source"></param>
        /// <returns></returns>
        public static bool IsValid(this XAiChatRole source)
        {
            //
            var result = source != XAiChatRole.None;
            return result;
        }

        /// <summary>
        /// Validate Role ...
        /// <see cref="ChatRole"/>>
        /// </summary>
        /// <param name="source"></param>
        /// <returns></returns>
        public static bool IsValid(this ChatRole source)
        {
            //
            var role = source.ToChatRole();
            var result = role.IsValid();
            return result;
        }
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xAiModels\Extensions\XAiApiConfigurationExtensions.cs

using System.Linq;
using xAiModels.Configurations;
using xAiModels.Models;
using xCommons.Extensions;

namespace xAiModels.Extensions
{
    public static class XAiApiConfigurationExtensions
    {
        /// <summary>
        /// Validate Api Configuration ...
        /// </summary>
        /// <param name="source"></param>
        /// <returns></returns>
        public static bool IsValid(this XAiApiConfiguration source)
        {
            return
                !source.IsNullOrDefault() &&
                source.Models.HasChild();
        }

        /// <summary>
        /// Retrieve Default Model Descriptor ...
        /// </summary>
        /// <param name="source"></param>
        /// <returns></returns>
        public static XAiModelDescriptor GetDefaultModel(this XAiApiConfiguration source)
        {
            //
            XAiModelDescriptor result = null;

            //
            if (source.IsValid())
            {
                result = source.Models.First();
            }

            //
            return result;
        }
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xAiModels\Helpers\XAiModelsHelper.cs

using System;
using GraphQL.Types;
using xAiModels.Interfaces.Entities;
using xAiModels.Models.Entities;
using xAiModels.Providers.Entities;
using xAiModels.Providers.GraphQL;
using xDataService.Db;
using xDataService.Models;
using xDataService.Providers;

namespace xAiModels.Helpers
{
    public static class XAiModelsHelper
    {
        //
        #region XAiConversation ...
        //
        #region EF Repository Descriptor Provider(s) ...
        public static XEFRepositoryDescriptor<
            XAiConversation,
            Guid,
            IXAiConversationKeyGenerator,
            XAiConversationKeyGenerator,
            IXAiConversationRepositoryEvents,
            XAiConversationRepositoryEvents,
            XAiConversationGraphType,
            GuidGraphType,
            XAiConversationGraphQuery,
            IXAiConversationGraphQLTypeHelper,
            XAiConversationGraphQLTypeHelper,
            XAiConversationGraphSchema,
            IXAiConversationRepository,
            XAiConversationEFRepository<TContext>,
            TContext
        > GetXAiConversationEFRepositoryDescriptor<TContext>()
        where TContext : XDbContext
        {
            //
            var result = new XEFRepositoryDescriptor<
                XAiConversation,
                Guid,
                IXAiConversationKeyGenerator,
                XAiConversationKeyGenerator,
                IXAiConversationRepositoryEvents,
                XAiConversationRepositoryEvents,
                XAiConversationGraphType,
                GuidGraphType,
                XAiConversationGraphQuery,
                IXAiConversationGraphQLTypeHelper,
                XAiConversationGraphQLTypeHelper,
                XAiConversationGraphSchema,
                IXAiConversationRepository,
                XAiConversationEFRepository<TContext>,
                TContext
            >();

            //
            return result;
        }

        public static XEFRepositoryDescriptor<
            XAiConversation,
            Guid,
            IXAiConversationKeyGenerator,
            XAiConversationKeyGenerator,
            IXAiConversationRepositoryEvents,
            XAiConversationRepositoryEvents,
            XAiConversationGraphType,
            GuidGraphType,
            XAiConversationGraphQuery,
            IXAiConversationGraphQLTypeHelper,
            XAiConversationGraphQLTypeHelper,
            XAiConversationGraphSchema,
            IXAiConversationRepository,
            XAiConversationEFRepository<TContext>,
            TContext,
            IXAiConversationSeeder,
            TSeederImplementation
        > GetXAiConversationEFRepositoryDescriptor<TContext, TSeederImplementation>()
        where TContext : XDbContext
        where TSeederImplementation : XBaseDbSeeder<XAiConversation, Guid>
        {
            //
            var result = new XEFRepositoryDescriptor<
                XAiConversation,
                Guid,
                IXAiConversationKeyGenerator,
                XAiConversationKeyGenerator,
                IXAiConversationRepositoryEvents,
                XAiConversationRepositoryEvents,
                XAiConversationGraphType,
                GuidGraphType,
                XAiConversationGraphQuery,
                IXAiConversationGraphQLTypeHelper,
                XAiConversationGraphQLTypeHelper,
                XAiConversationGraphSchema,
                IXAiConversationRepository,
                XAiConversationEFRepository<TContext>,
                TContext,
                IXAiConversationSeeder,
                TSeederImplementation
            >();

            //
            return result;
        }
        #endregion

        //
        #region Mongo Repository Descriptor Provider(s) ...
        public static XMongoRepositoryDescriptor<
            XAiConversation,
            Guid,
            IXAiConversationKeyGenerator,
            XAiConversationKeyGenerator,
            IXAiConversationRepositoryEvents,
            XAiConversationRepositoryEvents,
            XAiConversationGraphType,
            GuidGraphType,
            XAiConversationGraphQuery,
            IXAiConversationGraphQLTypeHelper,
            XAiConversationGraphQLTypeHelper,
            XAiConversationGraphSchema,
            IXAiConversationRepository,
            XAiConversationMongoRepository
        > GetXAiConversationMongoRepositoryDescriptor()
        {
            //
            var result = new XMongoRepositoryDescriptor<
                XAiConversation,
                Guid,
                IXAiConversationKeyGenerator,
                XAiConversationKeyGenerator,
                IXAiConversationRepositoryEvents,
                XAiConversationRepositoryEvents,
                XAiConversationGraphType,
                GuidGraphType,
                XAiConversationGraphQuery,
                IXAiConversationGraphQLTypeHelper,
                XAiConversationGraphQLTypeHelper,
                XAiConversationGraphSchema,
                IXAiConversationRepository,
                XAiConversationMongoRepository
            >();

            //
            return result;
        }

        public static XMongoRepositoryDescriptor<
            XAiConversation,
            Guid,
            IXAiConversationKeyGenerator,
            XAiConversationKeyGenerator,
            IXAiConversationRepositoryEvents,
            XAiConversationRepositoryEvents,
            XAiConversationGraphType,
            GuidGraphType,
            XAiConversationGraphQuery,
            IXAiConversationGraphQLTypeHelper,
            XAiConversationGraphQLTypeHelper,
            XAiConversationGraphSchema,
            IXAiConversationRepository,
            XAiConversationMongoRepository,
            IXAiConversationSeeder,
            TSeederImplementation
        > GetXAiConversationMongoRepositoryDescriptor<TSeederImplementation>()
        where TSeederImplementation : XBaseDbSeeder<XAiConversation, Guid>
        {
            //
            var result = new XMongoRepositoryDescriptor<
                XAiConversation,
                Guid,
                IXAiConversationKeyGenerator,
                XAiConversationKeyGenerator,
                IXAiConversationRepositoryEvents,
                XAiConversationRepositoryEvents,
                XAiConversationGraphType,
                GuidGraphType,
                XAiConversationGraphQuery,
                IXAiConversationGraphQLTypeHelper,
                XAiConversationGraphQLTypeHelper,
                XAiConversationGraphSchema,
                IXAiConversationRepository,
                XAiConversationMongoRepository,
                IXAiConversationSeeder,
                TSeederImplementation
            >();

            //
            return result;
        }
        #endregion

        //
        #region InMemory Repository Descriptor Provider(s) ...
        public static XInMemoryRepositoryDescriptor<
            XAiConversation,
            Guid,
            IXAiConversationKeyGenerator,
            XAiConversationKeyGenerator,
            IXAiConversationRepositoryEvents,
            XAiConversationRepositoryEvents,
            XAiConversationGraphType,
            GuidGraphType,
            XAiConversationGraphQuery,
            IXAiConversationGraphQLTypeHelper,
            XAiConversationGraphQLTypeHelper,
            XAiConversationGraphSchema,
            IXAiConversationRepository,
            XAiConversationInMemoryRepository
        > GetXAiConversationInMemoryRepositoryDescriptor()
        {
            //
            var result = new XInMemoryRepositoryDescriptor<
                XAiConversation,
                Guid,
                IXAiConversationKeyGenerator,
                XAiConversationKeyGenerator,
                IXAiConversationRepositoryEvents,
                XAiConversationRepositoryEvents,
                XAiConversationGraphType,
                GuidGraphType,
                XAiConversationGraphQuery,
                IXAiConversationGraphQLTypeHelper,
                XAiConversationGraphQLTypeHelper,
                XAiConversationGraphSchema,
                IXAiConversationRepository,
                XAiConversationInMemoryRepository
            >();

            //
            return result;
        }

        public static XInMemoryRepositoryDescriptor<
            XAiConversation,
            Guid,
            IXAiConversationKeyGenerator,
            XAiConversationKeyGenerator,
            IXAiConversationRepositoryEvents,
            XAiConversationRepositoryEvents,
            XAiConversationGraphType,
            GuidGraphType,
            XAiConversationGraphQuery,
            IXAiConversationGraphQLTypeHelper,
            XAiConversationGraphQLTypeHelper,
            XAiConversationGraphSchema,
            IXAiConversationRepository,
            XAiConversationInMemoryRepository,
            IXAiConversationSeeder,
            TSeederImplementation
        > GetXAiConversationInMemoryRepositoryDescriptor<TSeederImplementation>()
        where TSeederImplementation : XBaseDbSeeder<XAiConversation, Guid>
        {
            //
            var result = new XInMemoryRepositoryDescriptor<
                XAiConversation,
                Guid,
                IXAiConversationKeyGenerator,
                XAiConversationKeyGenerator,
                IXAiConversationRepositoryEvents,
                XAiConversationRepositoryEvents,
                XAiConversationGraphType,
                GuidGraphType,
                XAiConversationGraphQuery,
                IXAiConversationGraphQLTypeHelper,
                XAiConversationGraphQLTypeHelper,
                XAiConversationGraphSchema,
                IXAiConversationRepository,
                XAiConversationInMemoryRepository,
                IXAiConversationSeeder,
                TSeederImplementation
            >();

            //
            return result;
        }
        #endregion        
        #endregion

        //
        #region XAiMessage ...
        //
        #region EF Repository Descriptor Provider(s) ...
        public static XEFRepositoryDescriptor<
            XAiMessage,
            Guid,
            IXAiMessageKeyGenerator,
            XAiMessageKeyGenerator,
            IXAiMessageRepositoryEvents,
            XAiMessageRepositoryEvents,
            XAiMessageGraphType,
            GuidGraphType,
            XAiMessageGraphQuery,
            IXAiMessageGraphQLTypeHelper,
            XAiMessageGraphQLTypeHelper,
            XAiMessageGraphSchema,
            IXAiMessageRepository,
            XAiMessageEFRepository<TContext>,
            TContext
        > GetXAiMessageEFRepositoryDescriptor<TContext>()
        where TContext : XDbContext
        {
            //
            var result = new XEFRepositoryDescriptor<
                XAiMessage,
                Guid,
                IXAiMessageKeyGenerator,
                XAiMessageKeyGenerator,
                IXAiMessageRepositoryEvents,
                XAiMessageRepositoryEvents,
                XAiMessageGraphType,
                GuidGraphType,
                XAiMessageGraphQuery,
                IXAiMessageGraphQLTypeHelper,
                XAiMessageGraphQLTypeHelper,
                XAiMessageGraphSchema,
                IXAiMessageRepository,
                XAiMessageEFRepository<TContext>,
                TContext
            >();

            //
            return result;
        }

        public static XEFRepositoryDescriptor<
            XAiMessage,
            Guid,
            IXAiMessageKeyGenerator,
            XAiMessageKeyGenerator,
            IXAiMessageRepositoryEvents,
            XAiMessageRepositoryEvents,
            XAiMessageGraphType,
            GuidGraphType,
            XAiMessageGraphQuery,
            IXAiMessageGraphQLTypeHelper,
            XAiMessageGraphQLTypeHelper,
            XAiMessageGraphSchema,
            IXAiMessageRepository,
            XAiMessageEFRepository<TContext>,
            TContext,
            IXAiMessageSeeder,
            TSeederImplementation
        > GetXAiMessageEFRepositoryDescriptor<TContext, TSeederImplementation>()
        where TContext : XDbContext
        where TSeederImplementation : XBaseDbSeeder<XAiMessage, Guid>
        {
            //
            var result = new XEFRepositoryDescriptor<
                XAiMessage,
                Guid,
                IXAiMessageKeyGenerator,
                XAiMessageKeyGenerator,
                IXAiMessageRepositoryEvents,
                XAiMessageRepositoryEvents,
                XAiMessageGraphType,
                GuidGraphType,
                XAiMessageGraphQuery,
                IXAiMessageGraphQLTypeHelper,
                XAiMessageGraphQLTypeHelper,
                XAiMessageGraphSchema,
                IXAiMessageRepository,
                XAiMessageEFRepository<TContext>,
                TContext,
                IXAiMessageSeeder,
                TSeederImplementation
            >();

            //
            return result;
        }
        #endregion

        //
        #region Mongo Repository Descriptor Provider(s) ...
        public static XMongoRepositoryDescriptor<
            XAiMessage,
            Guid,
            IXAiMessageKeyGenerator,
            XAiMessageKeyGenerator,
            IXAiMessageRepositoryEvents,
            XAiMessageRepositoryEvents,
            XAiMessageGraphType,
            GuidGraphType,
            XAiMessageGraphQuery,
            IXAiMessageGraphQLTypeHelper,
            XAiMessageGraphQLTypeHelper,
            XAiMessageGraphSchema,
            IXAiMessageRepository,
            XAiMessageMongoRepository
        > GetXAiMessageMongoRepositoryDescriptor()
        {
            //
            var result = new XMongoRepositoryDescriptor<
                XAiMessage,
                Guid,
                IXAiMessageKeyGenerator,
                XAiMessageKeyGenerator,
                IXAiMessageRepositoryEvents,
                XAiMessageRepositoryEvents,
                XAiMessageGraphType,
                GuidGraphType,
                XAiMessageGraphQuery,
                IXAiMessageGraphQLTypeHelper,
                XAiMessageGraphQLTypeHelper,
                XAiMessageGraphSchema,
                IXAiMessageRepository,
                XAiMessageMongoRepository
            >();

            //
            return result;
        }

        public static XMongoRepositoryDescriptor<
            XAiMessage,
            Guid,
            IXAiMessageKeyGenerator,
            XAiMessageKeyGenerator,
            IXAiMessageRepositoryEvents,
            XAiMessageRepositoryEvents,
            XAiMessageGraphType,
            GuidGraphType,
            XAiMessageGraphQuery,
            IXAiMessageGraphQLTypeHelper,
            XAiMessageGraphQLTypeHelper,
            XAiMessageGraphSchema,
            IXAiMessageRepository,
            XAiMessageMongoRepository,
            IXAiMessageSeeder,
            TSeederImplementation
        > GetXAiMessageMongoRepositoryDescriptor<TSeederImplementation>()
        where TSeederImplementation : XBaseDbSeeder<XAiMessage, Guid>
        {
            //
            var result = new XMongoRepositoryDescriptor<
                XAiMessage,
                Guid,
                IXAiMessageKeyGenerator,
                XAiMessageKeyGenerator,
                IXAiMessageRepositoryEvents,
                XAiMessageRepositoryEvents,
                XAiMessageGraphType,
                GuidGraphType,
                XAiMessageGraphQuery,
                IXAiMessageGraphQLTypeHelper,
                XAiMessageGraphQLTypeHelper,
                XAiMessageGraphSchema,
                IXAiMessageRepository,
                XAiMessageMongoRepository,
                IXAiMessageSeeder,
                TSeederImplementation
            >();

            //
            return result;
        }
        #endregion

        //
        #region InMemory Repository Descriptor Provider(s) ...
        public static XInMemoryRepositoryDescriptor<
            XAiMessage,
            Guid,
            IXAiMessageKeyGenerator,
            XAiMessageKeyGenerator,
            IXAiMessageRepositoryEvents,
            XAiMessageRepositoryEvents,
            XAiMessageGraphType,
            GuidGraphType,
            XAiMessageGraphQuery,
            IXAiMessageGraphQLTypeHelper,
            XAiMessageGraphQLTypeHelper,
            XAiMessageGraphSchema,
            IXAiMessageRepository,
            XAiMessageInMemoryRepository
        > GetXAiMessageInMemoryRepositoryDescriptor()
        {
            //
            var result = new XInMemoryRepositoryDescriptor<
                XAiMessage,
                Guid,
                IXAiMessageKeyGenerator,
                XAiMessageKeyGenerator,
                IXAiMessageRepositoryEvents,
                XAiMessageRepositoryEvents,
                XAiMessageGraphType,
                GuidGraphType,
                XAiMessageGraphQuery,
                IXAiMessageGraphQLTypeHelper,
                XAiMessageGraphQLTypeHelper,
                XAiMessageGraphSchema,
                IXAiMessageRepository,
                XAiMessageInMemoryRepository
            >();

            //
            return result;
        }

        public static XInMemoryRepositoryDescriptor<
            XAiMessage,
            Guid,
            IXAiMessageKeyGenerator,
            XAiMessageKeyGenerator,
            IXAiMessageRepositoryEvents,
            XAiMessageRepositoryEvents,
            XAiMessageGraphType,
            GuidGraphType,
            XAiMessageGraphQuery,
            IXAiMessageGraphQLTypeHelper,
            XAiMessageGraphQLTypeHelper,
            XAiMessageGraphSchema,
            IXAiMessageRepository,
            XAiMessageInMemoryRepository,
            IXAiMessageSeeder,
            TSeederImplementation
        > GetXAiMessageInMemoryRepositoryDescriptor<TSeederImplementation>()
        where TSeederImplementation : XBaseDbSeeder<XAiMessage, Guid>
        {
            //
            var result = new XInMemoryRepositoryDescriptor<
                XAiMessage,
                Guid,
                IXAiMessageKeyGenerator,
                XAiMessageKeyGenerator,
                IXAiMessageRepositoryEvents,
                XAiMessageRepositoryEvents,
                XAiMessageGraphType,
                GuidGraphType,
                XAiMessageGraphQuery,
                IXAiMessageGraphQLTypeHelper,
                XAiMessageGraphQLTypeHelper,
                XAiMessageGraphSchema,
                IXAiMessageRepository,
                XAiMessageInMemoryRepository,
                IXAiMessageSeeder,
                TSeederImplementation
            >();

            //
            return result;
        }
        #endregion
        #endregion

        //
        #region XAiProject ...
        //
        #region EF Repository Descriptor Provider(s) ...
        public static XEFRepositoryDescriptor<
            XAiProject,
            Guid,
            IXAiProjectKeyGenerator,
            XAiProjectKeyGenerator,
            IXAiProjectRepositoryEvents,
            XAiProjectRepositoryEvents,
            XAiProjectGraphType,
            GuidGraphType,
            XAiProjectGraphQuery,
            IXAiProjectGraphQLTypeHelper,
            XAiProjectGraphQLTypeHelper,
            XAiProjectGraphSchema,
            IXAiProjectRepository,
            XAiProjectEFRepository<TContext>,
            TContext
        > GetXAiProjectEFRepositoryDescriptor<TContext>()
        where TContext : XDbContext
        {
            //
            var result = new XEFRepositoryDescriptor<
                XAiProject,
                Guid,
                IXAiProjectKeyGenerator,
                XAiProjectKeyGenerator,
                IXAiProjectRepositoryEvents,
                XAiProjectRepositoryEvents,
                XAiProjectGraphType,
                GuidGraphType,
                XAiProjectGraphQuery,
                IXAiProjectGraphQLTypeHelper,
                XAiProjectGraphQLTypeHelper,
                XAiProjectGraphSchema,
                IXAiProjectRepository,
                XAiProjectEFRepository<TContext>,
                TContext
            >();

            //
            return result;
        }

        public static XEFRepositoryDescriptor<
            XAiProject,
            Guid,
            IXAiProjectKeyGenerator,
            XAiProjectKeyGenerator,
            IXAiProjectRepositoryEvents,
            XAiProjectRepositoryEvents,
            XAiProjectGraphType,
            GuidGraphType,
            XAiProjectGraphQuery,
            IXAiProjectGraphQLTypeHelper,
            XAiProjectGraphQLTypeHelper,
            XAiProjectGraphSchema,
            IXAiProjectRepository,
            XAiProjectEFRepository<TContext>,
            TContext,
            IXAiProjectSeeder,
            TSeederImplementation
        > GetXAiProjectEFRepositoryDescriptor<TContext, TSeederImplementation>()
        where TContext : XDbContext
        where TSeederImplementation : XBaseDbSeeder<XAiProject, Guid>
        {
            //
            var result = new XEFRepositoryDescriptor<
                XAiProject,
                Guid,
                IXAiProjectKeyGenerator,
                XAiProjectKeyGenerator,
                IXAiProjectRepositoryEvents,
                XAiProjectRepositoryEvents,
                XAiProjectGraphType,
                GuidGraphType,
                XAiProjectGraphQuery,
                IXAiProjectGraphQLTypeHelper,
                XAiProjectGraphQLTypeHelper,
                XAiProjectGraphSchema,
                IXAiProjectRepository,
                XAiProjectEFRepository<TContext>,
                TContext,
                IXAiProjectSeeder,
                TSeederImplementation
            >();

            //
            return result;
        }
        #endregion

        //
        #region Mongo Repository Descriptor Provider(s) ...
        public static XMongoRepositoryDescriptor<
            XAiProject,
            Guid,
            IXAiProjectKeyGenerator,
            XAiProjectKeyGenerator,
            IXAiProjectRepositoryEvents,
            XAiProjectRepositoryEvents,
            XAiProjectGraphType,
            GuidGraphType,
            XAiProjectGraphQuery,
            IXAiProjectGraphQLTypeHelper,
            XAiProjectGraphQLTypeHelper,
            XAiProjectGraphSchema,
            IXAiProjectRepository,
            XAiProjectMongoRepository
        > GetXAiProjectMongoRepositoryDescriptor()
        {
            //
            var result = new XMongoRepositoryDescriptor<
                XAiProject,
                Guid,
                IXAiProjectKeyGenerator,
                XAiProjectKeyGenerator,
                IXAiProjectRepositoryEvents,
                XAiProjectRepositoryEvents,
                XAiProjectGraphType,
                GuidGraphType,
                XAiProjectGraphQuery,
                IXAiProjectGraphQLTypeHelper,
                XAiProjectGraphQLTypeHelper,
                XAiProjectGraphSchema,
                IXAiProjectRepository,
                XAiProjectMongoRepository
            >();

            //
            return result;
        }

        public static XMongoRepositoryDescriptor<
            XAiProject,
            Guid,
            IXAiProjectKeyGenerator,
            XAiProjectKeyGenerator,
            IXAiProjectRepositoryEvents,
            XAiProjectRepositoryEvents,
            XAiProjectGraphType,
            GuidGraphType,
            XAiProjectGraphQuery,
            IXAiProjectGraphQLTypeHelper,
            XAiProjectGraphQLTypeHelper,
            XAiProjectGraphSchema,
            IXAiProjectRepository,
            XAiProjectMongoRepository,
            IXAiProjectSeeder,
            TSeederImplementation
        > GetXAiProjectMongoRepositoryDescriptor<TSeederImplementation>()
        where TSeederImplementation : XBaseDbSeeder<XAiProject, Guid>
        {
            //
            var result = new XMongoRepositoryDescriptor<
                XAiProject,
                Guid,
                IXAiProjectKeyGenerator,
                XAiProjectKeyGenerator,
                IXAiProjectRepositoryEvents,
                XAiProjectRepositoryEvents,
                XAiProjectGraphType,
                GuidGraphType,
                XAiProjectGraphQuery,
                IXAiProjectGraphQLTypeHelper,
                XAiProjectGraphQLTypeHelper,
                XAiProjectGraphSchema,
                IXAiProjectRepository,
                XAiProjectMongoRepository,
                IXAiProjectSeeder,
                TSeederImplementation
            >();

            //
            return result;
        }
        #endregion

        //
        #region InMemory Repository Descriptor Provider(s) ...
        public static XInMemoryRepositoryDescriptor<
            XAiProject,
            Guid,
            IXAiProjectKeyGenerator,
            XAiProjectKeyGenerator,
            IXAiProjectRepositoryEvents,
            XAiProjectRepositoryEvents,
            XAiProjectGraphType,
            GuidGraphType,
            XAiProjectGraphQuery,
            IXAiProjectGraphQLTypeHelper,
            XAiProjectGraphQLTypeHelper,
            XAiProjectGraphSchema,
            IXAiProjectRepository,
            XAiProjectInMemoryRepository
        > GetXAiProjectInMemoryRepositoryDescriptor()
        {
            //
            var result = new XInMemoryRepositoryDescriptor<
                XAiProject,
                Guid,
                IXAiProjectKeyGenerator,
                XAiProjectKeyGenerator,
                IXAiProjectRepositoryEvents,
                XAiProjectRepositoryEvents,
                XAiProjectGraphType,
                GuidGraphType,
                XAiProjectGraphQuery,
                IXAiProjectGraphQLTypeHelper,
                XAiProjectGraphQLTypeHelper,
                XAiProjectGraphSchema,
                IXAiProjectRepository,
                XAiProjectInMemoryRepository
            >();

            //
            return result;
        }

        public static XInMemoryRepositoryDescriptor<
            XAiProject,
            Guid,
            IXAiProjectKeyGenerator,
            XAiProjectKeyGenerator,
            IXAiProjectRepositoryEvents,
            XAiProjectRepositoryEvents,
            XAiProjectGraphType,
            GuidGraphType,
            XAiProjectGraphQuery,
            IXAiProjectGraphQLTypeHelper,
            XAiProjectGraphQLTypeHelper,
            XAiProjectGraphSchema,
            IXAiProjectRepository,
            XAiProjectInMemoryRepository,
            IXAiProjectSeeder,
            TSeederImplementation
        > GetXAiProjectInMemoryRepositoryDescriptor<TSeederImplementation>()
        where TSeederImplementation : XBaseDbSeeder<XAiProject, Guid>
        {
            //
            var result = new XInMemoryRepositoryDescriptor<
                XAiProject,
                Guid,
                IXAiProjectKeyGenerator,
                XAiProjectKeyGenerator,
                IXAiProjectRepositoryEvents,
                XAiProjectRepositoryEvents,
                XAiProjectGraphType,
                GuidGraphType,
                XAiProjectGraphQuery,
                IXAiProjectGraphQLTypeHelper,
                XAiProjectGraphQLTypeHelper,
                XAiProjectGraphSchema,
                IXAiProjectRepository,
                XAiProjectInMemoryRepository,
                IXAiProjectSeeder,
                TSeederImplementation
            >();

            //
            return result;
        }
        #endregion        
        #endregion    
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xAiModels\Interfaces\Dtos\IXAiConversationDtoHub.cs

using System;
using xAiModels.Models.Dtos;
using xAiModels.Models.Entities;
using xPushService.Interfaces;

namespace xAiModels.Interfaces.Dtos
{
    public interface IXAiConversationDtoHub : IXBaseDtoHub<XAiConversation, XAiConversationDto, Guid>
    { }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xAiModels\Interfaces\Dtos\IXAiConversationRepositoryService.cs

using System;
using xAiModels.Models.Dtos;
using xAiModels.Models.Entities;
using xDataService.Interfaces;

namespace xAiModels.Interfaces.Dtos
{
    public interface IXAiConversationRepositoryService : IXBaseRepositoryService<XAiConversation, XAiConversationDto, Guid>
    { }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xAiModels\Interfaces\Dtos\IXAiConversationServiceProvider.cs

using System;
using xAiModels.Models.Dtos;
using xAiModels.Models.Entities;
using xAiModels.Providers.Dtos;
using xPushService.Interfaces;

namespace xAiModels.Interfaces.Dtos
{
    public interface IXAiConversationServiceProvider : IXBaseDtoProvider<XAiConversation, XAiConversationDto, Guid, XAiConversationDtoHub>
    { }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xAiModels\Interfaces\Dtos\IXAiMessageDtoHub.cs

using System;
using xAiModels.Models.Dtos;
using xAiModels.Models.Entities;
using xPushService.Interfaces;

namespace xAiModels.Interfaces.Dtos
{
    public interface IXAiMessageDtoHub : IXBaseDtoHub<XAiMessage, XAiMessageDto, Guid>
    { }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xAiModels\Interfaces\Dtos\IXAiMessageRepositoryService.cs

using System;
using xAiModels.Models.Dtos;
using xAiModels.Models.Entities;
using xDataService.Interfaces;

namespace xAiModels.Interfaces.Dtos
{
    public interface IXAiMessageRepositoryService : IXBaseRepositoryService<XAiMessage, XAiMessageDto, Guid>
    { }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xAiModels\Interfaces\Dtos\IXAiMessageServiceProvider.cs

using System;
using xAiModels.Models.Dtos;
using xAiModels.Models.Entities;
using xAiModels.Providers.Dtos;
using xPushService.Interfaces;

namespace xAiModels.Interfaces.Dtos
{
    public interface IXAiMessageServiceProvider : IXBaseDtoProvider<XAiMessage, XAiMessageDto, Guid, XAiMessageDtoHub>
    { }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xAiModels\Interfaces\Dtos\IXAiProjectDtoHub.cs

using System;
using xAiModels.Models.Dtos;
using xAiModels.Models.Entities;
using xPushService.Interfaces;

namespace xAiModels.Interfaces.Dtos
{
    public interface IXAiProjectDtoHub : IXBaseDtoHub<XAiProject, XAiProjectDto, Guid>
    { }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xAiModels\Interfaces\Dtos\IXAiProjectRepositoryService.cs

using System;
using xAiModels.Models.Dtos;
using xAiModels.Models.Entities;
using xDataService.Interfaces;

namespace xAiModels.Interfaces.Dtos
{
    public interface IXAiProjectRepositoryService : IXBaseRepositoryService<XAiProject, XAiProjectDto, Guid>
    { }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xAiModels\Interfaces\Dtos\IXAiProjectServiceProvider.cs

using System;
using xAiModels.Models.Dtos;
using xAiModels.Models.Entities;
using xAiModels.Providers.Dtos;
using xPushService.Interfaces;

namespace xAiModels.Interfaces.Dtos
{
    public interface IXAiProjectServiceProvider : IXBaseDtoProvider<XAiProject, XAiProjectDto, Guid, XAiProjectDtoHub>
    { }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xAiModels\Interfaces\Entities\IXAiConversationEntityHub.cs

using System;
using xAiModels.Models.Entities;
using xPushService.Interfaces;

namespace xAiModels.Interfaces.Entities
{
    public interface IXAiConversationEntityHub : IXBaseEntityHub<XAiConversation, Guid>
    { }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xAiModels\Interfaces\Entities\IXAiConversationGraphQLTypeHelper.cs

using System;
using xAiModels.Models.Entities;
using xDataService.Interfaces;

namespace xAiModels.Interfaces.Entities
{
    public interface IXAiConversationGraphQLTypeHelper : IXBaseGraphQLTypeHelper<XAiConversation, Guid>
    { }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xAiModels\Interfaces\Entities\IXAiConversationKeyGenerator.cs

using System;
using xAiModels.Models.Entities;
using xDataService.Interfaces;

namespace xAiModels.Interfaces.Entities
{
    public interface IXAiConversationKeyGenerator : IXKeyGenerator<XAiConversation, Guid>
    { }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xAiModels\Interfaces\Entities\IXAiConversationRepository.cs

using System;
using xAiModels.Models.Entities;
using xDataService.Interfaces;

namespace xAiModels.Interfaces.Entities
{
    public interface IXAiConversationRepository : IXBaseRepository<XAiConversation, Guid>
    { }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xAiModels\Interfaces\Entities\IXAiConversationRepositoryEvents.cs

using xAiModels.Models.Entities;
using xDataService.Interfaces;

namespace xAiModels.Interfaces.Entities
{
    public interface IXAiConversationRepositoryEvents : IXBaseRepositoryEvents<XAiConversation>
    { }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xAiModels\Interfaces\Entities\IXAiConversationRepositoryProvider.cs

using System;
using xAiModels.Models.Entities;
using xAiModels.Providers.Entities;
using xPushService.Interfaces;

namespace xAiModels.Interfaces.Entities
{
    public interface IXAiConversationRepositoryProvider : IXBaseEntityProvider<XAiConversation, Guid, XAiConversationEntityHub>
    { }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xAiModels\Interfaces\Entities\IXAiConversationSeeder.cs

using System;
using xAiModels.Models.Entities;
using xDataService.Interfaces;

namespace xAiModels.Interfaces.Entities
{
    public interface IXAiConversationSeeder : IXBaseDbSeeder<XAiConversation, Guid>
    { }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xAiModels\Interfaces\Entities\IXAiMessageEntityHub.cs

using System;
using xAiModels.Models.Entities;
using xPushService.Interfaces;

namespace xAiModels.Interfaces.Entities
{
    public interface IXAiMessageEntityHub : IXBaseEntityHub<XAiMessage, Guid>
    { }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xAiModels\Interfaces\Entities\IXAiMessageGraphQLTypeHelper.cs

using System;
using xAiModels.Models.Entities;
using xDataService.Interfaces;

namespace xAiModels.Interfaces.Entities
{
    public interface IXAiMessageGraphQLTypeHelper : IXBaseGraphQLTypeHelper<XAiMessage, Guid>
    { }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xAiModels\Interfaces\Entities\IXAiMessageKeyGenerator.cs

using System;
using xAiModels.Models.Entities;
using xDataService.Interfaces;

namespace xAiModels.Interfaces.Entities
{
    public interface IXAiMessageKeyGenerator : IXKeyGenerator<XAiMessage, Guid>
    { }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xAiModels\Interfaces\Entities\IXAiMessageRepository.cs

using System;
using xAiModels.Models.Entities;
using xDataService.Interfaces;

namespace xAiModels.Interfaces.Entities
{
    public interface IXAiMessageRepository : IXBaseRepository<XAiMessage, Guid>
    { }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xAiModels\Interfaces\Entities\IXAiMessageRepositoryEvents.cs

using xAiModels.Models.Entities;
using xDataService.Interfaces;

namespace xAiModels.Interfaces.Entities
{
    public interface IXAiMessageRepositoryEvents : IXBaseRepositoryEvents<XAiMessage>
    { }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xAiModels\Interfaces\Entities\IXAiMessageRepositoryProvider.cs

using System;
using xAiModels.Models.Entities;
using xAiModels.Providers.Entities;
using xPushService.Interfaces;

namespace xAiModels.Interfaces.Entities
{
    public interface IXAiMessageRepositoryProvider : IXBaseEntityProvider<XAiMessage, Guid, XAiMessageEntityHub>
    { }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xAiModels\Interfaces\Entities\IXAiMessageSeeder.cs

using System;
using xAiModels.Models.Entities;
using xDataService.Interfaces;

namespace xAiModels.Interfaces.Entities
{
    public interface IXAiMessageSeeder : IXBaseDbSeeder<XAiMessage, Guid>
    { }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xAiModels\Interfaces\Entities\IXAiProjectEntityHub.cs

using System;
using xAiModels.Models.Entities;
using xPushService.Interfaces;

namespace xAiModels.Interfaces.Entities
{
    public interface IXAiProjectEntityHub : IXBaseEntityHub<XAiProject, Guid>
    { }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xAiModels\Interfaces\Entities\IXAiProjectGraphQLTypeHelper.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using xAiModels.Models.Entities;
using xDataService.Interfaces;

namespace xAiModels.Interfaces.Entities
{
    public interface IXAiProjectGraphQLTypeHelper : IXBaseGraphQLTypeHelper<XAiProject, Guid>
    { }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xAiModels\Interfaces\Entities\IXAiProjectKeyGenerator.cs

using System;
using xAiModels.Models.Entities;
using xDataService.Interfaces;

namespace xAiModels.Interfaces.Entities
{
    public interface IXAiProjectKeyGenerator : IXKeyGenerator<XAiProject, Guid>
    { }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xAiModels\Interfaces\Entities\IXAiProjectRepository.cs

using System;
using xAiModels.Models.Entities;
using xDataService.Interfaces;

namespace xAiModels.Interfaces.Entities
{
    public interface IXAiProjectRepository : IXBaseRepository<XAiProject, Guid>
    { }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xAiModels\Interfaces\Entities\IXAiProjectRepositoryEvents.cs

using xAiModels.Models.Entities;
using xDataService.Interfaces;

namespace xAiModels.Interfaces.Entities
{
    public interface IXAiProjectRepositoryEvents : IXBaseRepositoryEvents<XAiProject>
    { }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xAiModels\Interfaces\Entities\IXAiProjectRepositoryProvider.cs

using System;
using xAiModels.Models.Entities;
using xAiModels.Providers.Entities;
using xPushService.Interfaces;

namespace xAiModels.Interfaces.Entities
{
    public interface IXAiProjectRepositoryProvider : IXBaseEntityProvider<XAiProject, Guid, XAiProjectEntityHub>
    { }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xAiModels\Interfaces\Entities\IXAiProjectSeeder.cs

using System;
using xAiModels.Models.Entities;
using xDataService.Interfaces;

namespace xAiModels.Interfaces.Entities
{
    public interface IXAiProjectSeeder : IXBaseDbSeeder<XAiProject, Guid>
    { }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xAiModels\Interfaces\IXAiConversationTitleResourceProvider.cs

using xStringService.Interfaces;

namespace xAiModels.Interfaces
{
    public interface IXAiConversationTitleResourceProvider : IXItemResourceProvider
    { }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xAiModels\Interfaces\IXAiDataProvider.cs

namespace xAiModels.Interfaces
{
    /// <summary>
    /// All Data Manipulation Requirements ...
    /// </summary>
    public interface IXAiDataProvider
    {
        
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xAiModels\Interfaces\IXAiProjectDescriptionResourceProvider.cs

using xStringService.Interfaces;

namespace xAiModels.Interfaces
{
    public interface IXAiProjectDescriptionResourceProvider : IXItemResourceProvider
    { }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xAiModels\Interfaces\IXAiProjectTitleResourceProvider.cs

using xStringService.Interfaces;

namespace xAiModels.Interfaces
{
    public interface IXAiProjectTitleResourceProvider : IXItemResourceProvider
    { }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xAiModels\Models\Dtos\XAiConversationDto.cs

using System;
using xModels.Base;
using xModels.Dtos;

namespace xAiModels.Models.Dtos
{
    /// <summary>
    /// Conversation Describe ...
    /// </summary>
    public class XAiConversationDto : XBaseGuidIDEntityDto
    {
        /// <summary>
        /// User Identifier ...
        /// </summary>
        /// <value></value>
        public string OwnerId { get; set; }

        /// <summary>
        /// Owner Info ...
        /// </summary>
        public virtual XPersonDto Owner { get; set; } = null;

        /// <summary>
        /// Conversation Title Resource ID ...
        /// </summary>
        public string Title { get; set; }

        /// <summary>
        /// All Exists Title Locale Resources ...
        /// </summary>
        public virtual XLocaleResourceDto[] TitleLocales { get; set; }

        /// <summary>
        /// Created Time ...
        /// </summary>
        public DateTime CreatedOn { get; set; }

        /// <summary>
        /// Updated Time ...
        /// </summary>
        public DateTime UpdatedAt { get; set; }

        /// <summary>
        /// Project ID ...
        /// </summary>
        public Guid ProjectId { get; set; }

        /// <summary>
        /// Project Title Resource ID ...
        /// </summary>
        public virtual string ProjectTitle { get; set; } = null;

        /// <summary>
        /// Project Description Resource ID ...
        /// </summary>
        public virtual string ProjectDescription { get; set; } = null;

        /// <summary>
        /// Project Title Locale Resources ...
        /// </summary>
        public virtual XLocaleResourceDto[] ProjectTitleLocales { get; set; }

        /// <summary>
        /// Project Description Locale Resources ...
        /// </summary>
        public virtual XLocaleResourceDto[] ProjectDescriptionLocales { get; set; }
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xAiModels\Models\Dtos\XAiMessageDto.cs

using System;
using System.Collections.Generic;
using xAiModels.Constants;
using xCommons.Extensions;
using xModels.Base;
using xModels.Dtos;

namespace xAiModels.Models.Dtos
{
    public class XAiMessageDto : XBaseGuidIDEntityDto
    {
        /// <summary>
        /// User Identifier ...
        /// </summary>
        /// <value></value>
        public string OwnerId { get; set; }

        /// <summary>
        /// Owner Info ...
        /// </summary>
        public virtual XPersonDto Owner { get; set; } = null;

        /// <summary>
        /// Message of Chat ...
        /// </summary>
        public string Content { get; set; }

        /// <summary>
        /// Role of Message ...
        /// </summary>
        public XAiChatRole Role { get; set; }

        /// <summary>
        /// Created Time ...
        /// </summary>
        public DateTime CreatedOn { get; set; }

        /// <summary>
        /// Updated Time ...
        /// </summary>
        public DateTime UpdatedAt { get; set; }

        /// <summary>
        /// Conversation Id ...
        /// </summary>
        public Guid ConversationId { get; set; }

        /// <summary>
        /// Conversation Info ...
        /// </summary>
        public virtual XAiConversationDto Conversation { get; set; } = null;

        //
        #region Meta Data Property ...
        private string _metadata;

        /// <summary>
        /// Meta Data of Message ...
        /// </summary>
        public IDictionary<string, object> Metadata { get; private set; } = null;

        /// <summary>
        /// Meta Data of MEssage in Json ... 
        /// </summary>
        public string MeatDatas
        {
            //
            get => _metadata;

            //
            set
            {
                //
                // Converts Json String to Dictionary ...
                if (!value.IsNullOrEmpty())
                {
                    Metadata = value.FromJSON<IDictionary<string, object>>();
                }

                //
                _metadata = value;
            }
        }
        #endregion                
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xAiModels\Models\Dtos\XAiProjectDto.cs

using System;
using System.Collections.Generic;
using xModels.Base;
using xModels.Dtos;

namespace xAiModels.Models.Dtos
{
    /// <summary>
    /// Describe a Project ...
    /// </summary>
    public class XAiProjectDto : XBaseGuidIDEntityDto
    {
        /// <summary>
        /// User Identifier ...
        /// </summary>
        /// <value></value>
        public string OwnerId { get; set; }

        /// <summary>
        /// Owner Info ...
        /// </summary>
        public virtual XPersonDto Owner { get; set; } = null;

        /// <summary>
        /// Title of Project ...
        /// </summary>
        public string Title { get; set; }

        /// <summary>
        /// Description of Project ...
        /// </summary>
        public string Description { get; set; }

        /// <summary>
        /// a Prompt for Project Start ...
        /// </summary>
        public string Prompt { get; set; }

        /// <summary>
        /// Created Time ...
        /// </summary>
        public DateTime CreatedOn { get; set; }

        /// <summary>
        /// Updated Time ...
        /// </summary>
        public DateTime UpdatedAt { get; set; }

        /// <summary>
        /// Conversations ...
        /// </summary>
        public virtual IList<XAiConversationDto> Conversations { get; set; } = [];
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xAiModels\Models\Entities\XAiConversation.cs

using System;
using System.ComponentModel.DataAnnotations;
using xModels.Base;

namespace xAiModels.Models.Entities
{
    /// <summary>
    /// Conversation Describe ...
    /// </summary>
    public class XAiConversation : XBaseGuidIDEntity
    {
        /// <summary>
        /// User Identifier ...
        /// </summary>
        /// <value></value>
        [Required]
        [StringLength(255)]
        public string OwnerId { get; set; }

        /// <summary>
        /// Title of Conversation ...
        /// </summary>
        [Required]
        [StringLength(255)]
        public string Title { get; set; }

        /// <summary>
        /// Created Time ...
        /// </summary>
        public DateTime CreatedOn { get; set; }

        /// <summary>
        /// Updated Time ...
        /// </summary>
        public DateTime UpdatedAt { get; set; }

        /// <summary>
        /// Project ID ...
        /// </summary>
        [Required]
        public Guid ProjectId { get; set; }
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xAiModels\Models\Entities\XAiMessage.cs

using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
using xAiModels.Constants;
using xCommons.Extensions;
using xModels.Base;

namespace xAiModels.Models.Entities
{
    /// <summary>
    /// Message Model of Ai ... 
    /// </summary>
    public class XAiMessage : XBaseGuidIDEntity
    {
        /// <summary>
        /// User Identifier ...
        /// </summary>
        /// <value></value>
        [Required]
        [StringLength(255)]
        public string OwnerId { get; set; }

        /// <summary>
        /// Message of Chat ...
        /// </summary>
        [Required]
        public string Content { get; set; }

        /// <summary>
        /// Role of Message ...
        /// </summary>
        public XAiChatRole Role { get; set; }

        /// <summary>
        /// Created Time ...
        /// </summary>
        public DateTime CreatedOn { get; set; }

        /// <summary>
        /// Updated Time ...
        /// </summary>
        public DateTime UpdatedAt { get; set; }

        /// <summary>
        /// Conversation Id ...
        /// </summary>
        [StringLength(255)]
        public Guid ConversationId { get; set; }

        //
        #region Meta Data Property ...
        private string _metadata;

        /// <summary>
        /// Meta Data of Message ...
        /// </summary>
        [NotMapped]
        public IDictionary<string, object> Metadata { get; private set; } = null;

        /// <summary>
        /// Meta Data of MEssage in Json ... 
        /// </summary>
        public string MeatDatas
        {
            //
            get => _metadata;

            //
            set
            {
                //
                // Converts Json String to Dictionary ...
                if (!value.IsNullOrEmpty())
                {
                    Metadata = value.FromJSON<IDictionary<string, object>>();
                }

                //
                _metadata = value;
            }
        }
        #endregion        
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xAiModels\Models\Entities\XAiProject.cs

using System;
using System.ComponentModel.DataAnnotations;
using xModels.Base;

namespace xAiModels.Models.Entities
{
    /// <summary>
    /// Describe a Project ...
    /// </summary>
    public class XAiProject : XBaseGuidIDEntity
    {
        /// <summary>
        /// User Identifier ...
        /// </summary>
        /// <value></value>
        [Required]
        [StringLength(255)]
        public string OwnerId { get; set; }

        /// <summary>
        /// Title of Project ...
        /// </summary>
        [Required]
        [StringLength(255)]
        public string Title { get; set; }

        /// <summary>
        /// Description of Project ...
        /// </summary>
        [StringLength(1000)]
        public string Description { get; set; }

        /// <summary>
        /// a Prompt for Project Start ...
        /// </summary>
        public string Prompt { get; set; }

        /// <summary>
        /// Created Time ...
        /// </summary>
        public DateTime CreatedOn { get; set; }

        /// <summary>
        /// Updated Time ...
        /// </summary>
        public DateTime UpdatedAt { get; set; }
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xAiModels\Models\XAiModelDescriptor.cs

using xAiModels.Constants;

namespace xAiModels.Models
{
    /// <summary>
    /// Describe a Provided Model ...
    /// </summary>
    public class XAiModelDescriptor
    {
        /// <summary>
        /// Provider Name ...
        /// </summary>
        public string Name { get; set; }

        /// <summary>
        /// LLM Provider Url ...
        /// </summary>
        public string Url { get; set; }

        /// <summary>
        /// Model Name ...
        /// </summary>
        public string LLM { get; set; }

        /// <summary>
        /// Api Key for Connection ...
        /// </summary>
        public string ApiKey { get; set; }

        /// <summary>
        /// Specified Model Provider Type ...
        /// </summary>
        public XAiModelProviderType Provider { get; set; } = XAiModelProviderType.Ollama;        
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xAiModels\Providers\Dtos\XAiConversationDtoHub.cs

using System;
using Microsoft.Extensions.Logging;
using xAiModels.Interfaces.Dtos;
using xAiModels.Models.Dtos;
using xAiModels.Models.Entities;
using xPushService.Base;

namespace xAiModels.Providers.Dtos
{
    public class XAiConversationDtoHub : XBaseDtoHub<XAiConversation, XAiConversationDto, Guid>, IXAiConversationDtoHub
    {
        public XAiConversationDtoHub(
            ILogger<XAiConversationDtoHub> logger
        ) : base(logger)
        { }
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xAiModels\Providers\Dtos\XAiConversationRepositoryService.cs

using System;
using System.Collections.Generic;
using AutoMapper;
using xAiModels.Interfaces.Dtos;
using xAiModels.Interfaces.Entities;
using xAiModels.Models.Dtos;
using xAiModels.Models.Entities;
using xDataService.Providers;

namespace xAiModels.Providers.Dtos
{
    public class XAiConversationRepositoryService : XBaseRepositoryService<XAiConversation, XAiConversationDto, Guid>, IXAiConversationRepositoryService
    {
        public XAiConversationRepositoryService(
            IXAiConversationRepository repository,
            IEnumerable<Profile> mapperProfiles = null
        ) : base(
            repository,
            mapperProfiles
        )
        { }
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xAiModels\Providers\Dtos\XAiConversationServiceProvider.cs

using System;
using Microsoft.AspNetCore.SignalR;
using xAiModels.Interfaces.Dtos;
using xAiModels.Models.Dtos;
using xAiModels.Models.Entities;
using xDataService.Configuration;
using xIdentityService.Interfaces;
using xPushService.Base;

namespace xAiModels.Providers.Dtos
{
    public class XAiConversationServiceProvider : XBaseDtoProvider<XAiConversation, XAiConversationDto, Guid, XAiConversationDtoHub>, IXAiConversationServiceProvider
    {
        public XAiConversationServiceProvider(
            IHubContext<XAiConversationDtoHub> hub,
            XDataServiceConfiguration dataConfiguration,
            IXAiConversationRepositoryService service,
            IXIdentityProvider identityProvider = null
        ) : base(
            hub,
            dataConfiguration,
            service,
            identityProvider
        )
        { }
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xAiModels\Providers\Dtos\XAiMessageDtoHub.cs

using System;
using Microsoft.Extensions.Logging;
using xAiModels.Interfaces.Dtos;
using xAiModels.Models.Dtos;
using xAiModels.Models.Entities;
using xPushService.Base;

namespace xAiModels.Providers.Dtos
{
    public class XAiMessageDtoHub : XBaseDtoHub<XAiMessage, XAiMessageDto, Guid>, IXAiMessageDtoHub
    {
        public XAiMessageDtoHub(
            ILogger<XAiMessageDtoHub> logger
        ) : base(logger)
        { }
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xAiModels\Providers\Dtos\XAiMessageRepositoryService.cs

using System;
using System.Collections.Generic;
using AutoMapper;
using xAiModels.Interfaces.Dtos;
using xAiModels.Interfaces.Entities;
using xAiModels.Models.Dtos;
using xAiModels.Models.Entities;
using xDataService.Providers;

namespace xAiModels.Providers.Dtos
{
    public class XAiMessageRepositoryService : XBaseRepositoryService<XAiMessage, XAiMessageDto, Guid>, IXAiMessageRepositoryService
    {
        public XAiMessageRepositoryService(
            IXAiMessageRepository repository,
            IEnumerable<Profile> mapperProfiles = null
        ) : base(
            repository,
            mapperProfiles
        )
        { }
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xAiModels\Providers\Dtos\XAiMessageServiceProvider.cs

using System;
using Microsoft.AspNetCore.SignalR;
using xAiModels.Interfaces.Dtos;
using xAiModels.Models.Dtos;
using xAiModels.Models.Entities;
using xDataService.Configuration;
using xIdentityService.Interfaces;
using xPushService.Base;

namespace xAiModels.Providers.Dtos
{
    public class XAiMessageServiceProvider : XBaseDtoProvider<XAiMessage, XAiMessageDto, Guid, XAiMessageDtoHub>, IXAiMessageServiceProvider
    {
        public XAiMessageServiceProvider(
            IHubContext<XAiMessageDtoHub> hub,
            XDataServiceConfiguration dataConfiguration,
            IXAiMessageRepositoryService service,
            IXIdentityProvider identityProvider = null
        ) : base(
            hub,
            dataConfiguration,
            service,
            identityProvider
        )
        { }
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xAiModels\Providers\Dtos\XAiProjectDtoHub.cs

using System;
using Microsoft.Extensions.Logging;
using xAiModels.Interfaces.Dtos;
using xAiModels.Models.Dtos;
using xAiModels.Models.Entities;
using xPushService.Base;

namespace xAiModels.Providers.Dtos
{
    public class XAiProjectDtoHub : XBaseDtoHub<XAiProject, XAiProjectDto, Guid>, IXAiProjectDtoHub
    {
        public XAiProjectDtoHub(
            ILogger<XAiProjectDtoHub> logger
        ) : base(logger)
        { }
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xAiModels\Providers\Dtos\XAiProjectRepositoryService.cs

using System;
using System.Collections.Generic;
using AutoMapper;
using xAiModels.Interfaces.Dtos;
using xAiModels.Interfaces.Entities;
using xAiModels.Models.Dtos;
using xAiModels.Models.Entities;
using xDataService.Providers;

namespace xAiModels.Providers.Dtos
{
    public class XAiProjectRepositoryService : XBaseRepositoryService<XAiProject, XAiProjectDto, Guid>, IXAiProjectRepositoryService
    {
        public XAiProjectRepositoryService(
            IXAiProjectRepository repository,
            IEnumerable<Profile> mapperProfiles = null
        ) : base(
            repository,
            mapperProfiles
        )
        { }
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xAiModels\Providers\Dtos\XAiProjectServiceProvider.cs

using System;
using Microsoft.AspNetCore.SignalR;
using xAiModels.Interfaces.Dtos;
using xAiModels.Models.Dtos;
using xAiModels.Models.Entities;
using xDataService.Configuration;
using xIdentityService.Interfaces;
using xPushService.Base;

namespace xAiModels.Providers.Dtos
{
    public class XAiProjectServiceProvider : XBaseDtoProvider<XAiProject, XAiProjectDto, Guid, XAiProjectDtoHub>, IXAiProjectServiceProvider
    {
        public XAiProjectServiceProvider(
            IHubContext<XAiProjectDtoHub> hub,
            XDataServiceConfiguration dataConfiguration,
            IXAiProjectRepositoryService service,
            IXIdentityProvider identityProvider = null
        ) : base(
            hub,
            dataConfiguration,
            service,
            identityProvider
        )
        { }
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xAiModels\Providers\Entities\XAiConversationEFRepository.cs

using System;
using xAiModels.Interfaces.Entities;
using xAiModels.Models.Entities;
using xDataService.Configuration;
using xDataService.Db;
using xDataService.Interfaces;
using xDataService.Providers;

namespace xAiModels.Providers.Entities
{
    public class XAiConversationEFRepository<TContext> : XBaseEFRepository<XAiConversation, Guid, TContext>, IXAiConversationRepository
    where TContext : XDbContext
    {
        public XAiConversationEFRepository(
            IXUnitOfWorks<TContext> unitOfWorks,
            XDataServiceConfiguration configuration,
            IXAiConversationKeyGenerator keyGenerator = null,
            IXAiConversationRepositoryEvents baseRepositoryEvents = null
        ) : base(
            unitOfWorks,
            configuration,
            keyGenerator,
            baseRepositoryEvents
        )
        { }
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xAiModels\Providers\Entities\XAiConversationEntityHub.cs

using System;
using Microsoft.Extensions.Logging;
using xAiModels.Interfaces.Entities;
using xAiModels.Models.Entities;
using xPushService.Base;

namespace xAiModels.Providers.Entities
{
    public class XAiConversationEntityHub : XBaseEntityHub<XAiConversation, Guid>, IXAiConversationEntityHub
    {
        public XAiConversationEntityHub(
            ILogger<XAiConversationEntityHub> logger
        ) : base(logger)
        { }
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xAiModels\Providers\Entities\XAiConversationInMemoryRepository.cs

using System;
using xAiModels.Interfaces.Entities;
using xAiModels.Models.Entities;
using xDataService.Configuration;
using xDataService.Providers;

namespace xAiModels.Providers.Entities
{
    public class XAiConversationInMemoryRepository : XBaseInMemoryRepository<XAiConversation, Guid>, IXAiConversationRepository
    {
        public XAiConversationInMemoryRepository(
            XDataServiceConfiguration configuration,
            IXAiConversationKeyGenerator keyGenerator = null,
            IXAiConversationRepositoryEvents baseRepositoryEvents = null
        ) : base(
            configuration,
            keyGenerator,
            baseRepositoryEvents
        )
        { }
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xAiModels\Providers\Entities\XAiConversationKeyGenerator.cs

using xAiModels.Interfaces.Entities;
using xAiModels.Models.Entities;
using xDataService.Providers;

namespace xAiModels.Providers.Entities
{
    public class XAiConversationKeyGenerator : XGuidKeyGenerator<XAiConversation>, IXAiConversationKeyGenerator
    { }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xAiModels\Providers\Entities\XAiConversationMongoRepository.cs

using System;
using xAiModels.Interfaces.Entities;
using xAiModels.Models.Entities;
using xDataService.Configuration;
using xDataService.Providers;

namespace xAiModels.Providers.Entities
{
    public class XAiConversationMongoRepository : XBaseMongoRepository<XAiConversation, Guid>, IXAiConversationRepository
    {
        public XAiConversationMongoRepository(
            XDataBaseConfiguration dbConfiguration,
            XDataServiceConfiguration configuration,
            string collectionName = null,
            IXAiConversationKeyGenerator keyGenerator = null,
            IXAiConversationRepositoryEvents baseRepositoryEvents = null
        ) : base(
            dbConfiguration,
            configuration,
            collectionName,
            keyGenerator,
            baseRepositoryEvents
        )
        { }
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xAiModels\Providers\Entities\XAiConversationRepositoryEvents.cs

using xAiModels.Interfaces.Entities;
using xAiModels.Models.Entities;
using xDataService.Providers;

namespace xAiModels.Providers.Entities
{
    public class XAiConversationRepositoryEvents : XBaseRepositoryEvents<XAiConversation>, IXAiConversationRepositoryEvents
    { }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xAiModels\Providers\Entities\XAiConversationRepositoryProvider.cs

using System;
using Microsoft.AspNetCore.SignalR;
using xAiModels.Interfaces.Entities;
using xAiModels.Models.Entities;
using xDataService.Configuration;
using xIdentityService.Interfaces;
using xPushService.Base;

namespace xAiModels.Providers.Entities
{
    public class XAiConversationRepositoryProvider : XBaseEntityProvider<XAiConversation, Guid, XAiConversationEntityHub>, IXAiConversationRepositoryProvider
    {
        public XAiConversationRepositoryProvider(
            IHubContext<XAiConversationEntityHub> hub,
            IXAiConversationRepository repository,
            XDataServiceConfiguration dataConfiguration,
            IXIdentityProvider identityProvider = null
        ) : base(
            hub,
            repository,
            dataConfiguration,
            identityProvider
        )
        { }
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xAiModels\Providers\Entities\XAiConversationSeederBase.cs

using System;
using xAiModels.Interfaces.Entities;
using xAiModels.Models.Entities;
using xDataService.Configuration;
using xDataService.Providers;

namespace xAiModels.Providers.Entities
{
    public abstract class XAiConversationSeederBase : XBaseDbSeeder<XAiConversation, Guid>, IXAiConversationSeeder
    {
        protected XAiConversationSeederBase(
            string entity,
            string database,
            IXAiConversationRepository repository,
            XDataServiceConfiguration dataServiceConfiguration
        ) : base(
            entity,
            database,
            repository,
            dataServiceConfiguration
        )
        { }
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xAiModels\Providers\Entities\XAiMessageEFRepository.cs

using System;
using xAiModels.Interfaces.Entities;
using xAiModels.Models.Entities;
using xDataService.Configuration;
using xDataService.Db;
using xDataService.Interfaces;
using xDataService.Providers;

namespace xAiModels.Providers.Entities
{
    public class XAiMessageEFRepository<TContext> : XBaseEFRepository<XAiMessage, Guid, TContext>, IXAiMessageRepository
    where TContext : XDbContext
    {
        public XAiMessageEFRepository(
            IXUnitOfWorks<TContext> unitOfWorks,
            XDataServiceConfiguration configuration,
            IXAiMessageKeyGenerator keyGenerator = null,
            IXAiMessageRepositoryEvents baseRepositoryEvents = null
        ) : base(
            unitOfWorks,
            configuration,
            keyGenerator,
            baseRepositoryEvents
        )
        { }
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xAiModels\Providers\Entities\XAiMessageEntityHub.cs

using System;
using Microsoft.Extensions.Logging;
using xAiModels.Interfaces.Entities;
using xAiModels.Models.Entities;
using xPushService.Base;

namespace xAiModels.Providers.Entities
{
    public class XAiMessageEntityHub : XBaseEntityHub<XAiMessage, Guid>, IXAiMessageEntityHub
    {
        public XAiMessageEntityHub(
            ILogger<XAiMessageEntityHub> logger
        ) : base(logger)
        { }
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xAiModels\Providers\Entities\XAiMessageInMemoryRepository.cs

using System;
using xAiModels.Interfaces.Entities;
using xAiModels.Models.Entities;
using xDataService.Configuration;
using xDataService.Providers;

namespace xAiModels.Providers.Entities
{
    public class XAiMessageInMemoryRepository : XBaseInMemoryRepository<XAiMessage, Guid>, IXAiMessageRepository
    {
        public XAiMessageInMemoryRepository(
            XDataServiceConfiguration configuration,
            IXAiMessageKeyGenerator keyGenerator = null,
            IXAiMessageRepositoryEvents baseRepositoryEvents = null
        ) : base(
            configuration,
            keyGenerator,
            baseRepositoryEvents
        )
        { }
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xAiModels\Providers\Entities\XAiMessageKeyGenerator.cs

using xAiModels.Interfaces.Entities;
using xAiModels.Models.Entities;
using xDataService.Providers;

namespace xAiModels.Providers.Entities
{
    public class XAiMessageKeyGenerator : XGuidKeyGenerator<XAiMessage>, IXAiMessageKeyGenerator
    { }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xAiModels\Providers\Entities\XAiMessageMongoRepository.cs

using System;
using xAiModels.Interfaces.Entities;
using xAiModels.Models.Entities;
using xDataService.Configuration;
using xDataService.Providers;

namespace xAiModels.Providers.Entities
{
    public class XAiMessageMongoRepository : XBaseMongoRepository<XAiMessage, Guid>, IXAiMessageRepository
    {
        public XAiMessageMongoRepository(
            XDataBaseConfiguration dbConfiguration,
            XDataServiceConfiguration configuration,
            string collectionName = null,
            IXAiMessageKeyGenerator keyGenerator = null,
            IXAiMessageRepositoryEvents baseRepositoryEvents = null
        ) : base(
            dbConfiguration,
            configuration,
            collectionName,
            keyGenerator,
            baseRepositoryEvents
        )
        { }
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xAiModels\Providers\Entities\XAiMessageRepositoryEvents.cs

using xAiModels.Interfaces.Entities;
using xAiModels.Models.Entities;
using xDataService.Providers;

namespace xAiModels.Providers.Entities
{
    public class XAiMessageRepositoryEvents : XBaseRepositoryEvents<XAiMessage>, IXAiMessageRepositoryEvents
    { }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xAiModels\Providers\Entities\XAiMessageRepositoryProvider.cs

using System;
using Microsoft.AspNetCore.SignalR;
using xAiModels.Interfaces.Entities;
using xAiModels.Models.Entities;
using xDataService.Configuration;
using xIdentityService.Interfaces;
using xPushService.Base;

namespace xAiModels.Providers.Entities
{
    public class XAiMessageRepositoryProvider : XBaseEntityProvider<XAiMessage, Guid, XAiMessageEntityHub>, IXAiMessageRepositoryProvider
    {
        public XAiMessageRepositoryProvider(
            IHubContext<XAiMessageEntityHub> hub,
            IXAiMessageRepository repository,
            XDataServiceConfiguration dataConfiguration,
            IXIdentityProvider identityProvider = null
        ) : base(
            hub,
            repository,
            dataConfiguration,
            identityProvider
        )
        { }
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xAiModels\Providers\Entities\XAiMessageSeederBase.cs

using System;
using xAiModels.Interfaces.Entities;
using xAiModels.Models.Entities;
using xDataService.Configuration;
using xDataService.Providers;

namespace xAiModels.Providers.Entities
{
    public abstract class XAiMessageSeederBase : XBaseDbSeeder<XAiMessage, Guid>, IXAiMessageSeeder
    {
        protected XAiMessageSeederBase(
            string entity,
            string database,
            IXAiMessageRepository repository,
            XDataServiceConfiguration dataServiceConfiguration
        ) : base(
            entity,
            database,
            repository,
            dataServiceConfiguration
        )
        { }
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xAiModels\Providers\Entities\XAiProjectEFRepository.cs

using System;
using xAiModels.Interfaces.Entities;
using xAiModels.Models.Entities;
using xDataService.Configuration;
using xDataService.Db;
using xDataService.Interfaces;
using xDataService.Providers;

namespace xAiModels.Providers.Entities
{
    public class XAiProjectEFRepository<TContext> : XBaseEFRepository<XAiProject, Guid, TContext>, IXAiProjectRepository
    where TContext : XDbContext
    {
        public XAiProjectEFRepository(
            IXUnitOfWorks<TContext> unitOfWorks,
            XDataServiceConfiguration configuration,
            IXAiProjectKeyGenerator keyGenerator = null,
            IXAiProjectRepositoryEvents baseRepositoryEvents = null
        ) : base(
            unitOfWorks,
            configuration,
            keyGenerator,
            baseRepositoryEvents
        )
        { }
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xAiModels\Providers\Entities\XAiProjectEntityHub.cs

using System;
using Microsoft.Extensions.Logging;
using xAiModels.Interfaces.Entities;
using xAiModels.Models.Entities;
using xPushService.Base;

namespace xAiModels.Providers.Entities
{
    public class XAiProjectEntityHub : XBaseEntityHub<XAiProject, Guid>, IXAiProjectEntityHub
    {
        public XAiProjectEntityHub(
            ILogger<XAiProjectEntityHub> logger
        ) : base(logger)
        { }
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xAiModels\Providers\Entities\XAiProjectInMemoryRepository.cs

using System;
using xAiModels.Interfaces.Entities;
using xAiModels.Models.Entities;
using xDataService.Configuration;
using xDataService.Providers;

namespace xAiModels.Providers.Entities
{
    public class XAiProjectInMemoryRepository : XBaseInMemoryRepository<XAiProject, Guid>, IXAiProjectRepository
    {
        public XAiProjectInMemoryRepository(
            XDataServiceConfiguration configuration,
            IXAiProjectKeyGenerator keyGenerator = null,
            IXAiProjectRepositoryEvents baseRepositoryEvents = null
        ) : base(
            configuration,
            keyGenerator,
            baseRepositoryEvents
        )
        { }
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xAiModels\Providers\Entities\XAiProjectKeyGenerator.cs

using xAiModels.Interfaces.Entities;
using xAiModels.Models.Entities;
using xDataService.Providers;

namespace xAiModels.Providers.Entities
{
    public class XAiProjectKeyGenerator : XGuidKeyGenerator<XAiProject>, IXAiProjectKeyGenerator
    { }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xAiModels\Providers\Entities\XAiProjectMongoRepository.cs

using System;
using xAiModels.Interfaces.Entities;
using xAiModels.Models.Entities;
using xDataService.Configuration;
using xDataService.Providers;

namespace xAiModels.Providers.Entities
{
    public class XAiProjectMongoRepository : XBaseMongoRepository<XAiProject, Guid>, IXAiProjectRepository
    {
        public XAiProjectMongoRepository(
            XDataBaseConfiguration dbConfiguration,
            XDataServiceConfiguration configuration,
            string collectionName = null,
            IXAiProjectKeyGenerator keyGenerator = null,
            IXAiProjectRepositoryEvents baseRepositoryEvents = null
        ) : base(
            dbConfiguration,
            configuration,
            collectionName,
            keyGenerator,
            baseRepositoryEvents
        )
        { }
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xAiModels\Providers\Entities\XAiProjectRepositoryEvents.cs

using xAiModels.Interfaces.Entities;
using xAiModels.Models.Entities;
using xDataService.Providers;

namespace xAiModels.Providers.Entities
{
    public class XAiProjectRepositoryEvents : XBaseRepositoryEvents<XAiProject>, IXAiProjectRepositoryEvents
    { }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xAiModels\Providers\Entities\XAiProjectRepositoryProvider.cs

using System;
using Microsoft.AspNetCore.SignalR;
using xAiModels.Interfaces.Entities;
using xAiModels.Models.Entities;
using xDataService.Configuration;
using xIdentityService.Interfaces;
using xPushService.Base;

namespace xAiModels.Providers.Entities
{
    public class XAiProjectRepositoryProvider : XBaseEntityProvider<XAiProject, Guid, XAiProjectEntityHub>, IXAiProjectRepositoryProvider
    {
        public XAiProjectRepositoryProvider(
            IHubContext<XAiProjectEntityHub> hub,
            IXAiProjectRepository repository,
            XDataServiceConfiguration dataConfiguration,
            IXIdentityProvider identityProvider = null
        ) : base(
            hub,
            repository,
            dataConfiguration,
            identityProvider
        )
        { }
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xAiModels\Providers\Entities\XAiProjectSeederBase.cs

using System;
using xAiModels.Interfaces.Entities;
using xAiModels.Models.Entities;
using xDataService.Configuration;
using xDataService.Providers;

namespace xAiModels.Providers.Entities
{
    public abstract class XAiProjectSeederBase : XBaseDbSeeder<XAiProject, Guid>, IXAiProjectSeeder
    {
        protected XAiProjectSeederBase(
            string entity,
            string database,
            IXAiProjectRepository repository,
            XDataServiceConfiguration dataServiceConfiguration
        ) : base(
            entity,
            database,
            repository,
            dataServiceConfiguration
        )
        { }
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xAiModels\Providers\GraphQL\XAiConversationGraphQLTypeHelper.cs

using System;
using xAiModels.Constants;
using xAiModels.Interfaces.Entities;
using xAiModels.Models.Entities;
using xDataService.GraphQL;

namespace xAiModels.Providers.GraphQL
{
    public class XAiConversationGraphQLTypeHelper : XBaseGraphQLTypeHelper<XAiConversation, Guid>, IXAiConversationGraphQLTypeHelper
    {
        public override string GetInQueryCollectionName()
        {
            return XAiModelsConstants.XAiConversationCollectionName;
        }

        public override string GetInQuerySingleName()
        {
            return XAiModelsConstants.XAiConversationSignleName;
        }
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xAiModels\Providers\GraphQL\XAiConversationGraphQuery.cs

using System;
using GraphQL.Types;
using xAiModels.Interfaces.Entities;
using xAiModels.Models.Entities;
using xDataService.Configuration;
using xDataService.GraphQL;

namespace xAiModels.Providers.GraphQL
{
    public class XAiConversationGraphQuery : XBaseGraphQLQuery<XAiConversation, Guid, XAiConversationGraphType, GuidGraphType>
    {
        public XAiConversationGraphQuery(
            XDataServiceConfiguration configuration,
            IXAiConversationRepository repository,
            IXAiConversationGraphQLTypeHelper helper
        ) : base(
            configuration,
            repository,
            helper
        )
        { }
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xAiModels\Providers\GraphQL\XAiConversationGraphSchema.cs

using System;
using GraphQL.Types;

namespace xAiModels.Providers.GraphQL
{
    public class XAiConversationGraphSchema : Schema
    {
        public XAiConversationGraphSchema(IServiceProvider services) : base(services)
        {
            Query = (XAiConversationGraphQuery)services.GetService(typeof(XAiConversationGraphQuery));
        }
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xAiModels\Providers\GraphQL\XAiConversationGraphType.cs

using System;
using xAiModels.Models.Entities;
using xDataService.GraphQL;

namespace xAiModels.Providers.GraphQL
{
    public class XAiConversationGraphType : XBaseGraphObjectType<XAiConversation, Guid>
    {
        public XAiConversationGraphType() : base()
        {
            Field(x => x.Title);
            Field(x => x.OwnerId);
            Field(x => x.CreatedOn);
            Field(x => x.UpdatedAt);
            Field(x => x.ProjectId);
        }
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xAiModels\Providers\GraphQL\XAiMessageGraphQLTypeHelper.cs

using System;
using xAiModels.Constants;
using xAiModels.Interfaces.Entities;
using xAiModels.Models.Entities;
using xDataService.GraphQL;

namespace xAiModels.Providers.GraphQL
{
    public class XAiMessageGraphQLTypeHelper : XBaseGraphQLTypeHelper<XAiMessage, Guid>, IXAiMessageGraphQLTypeHelper
    {
        public override string GetInQueryCollectionName()
        {
            return XAiModelsConstants.XAiMessageCollectionName;
        }

        public override string GetInQuerySingleName()
        {
            return XAiModelsConstants.XAiMessageSingleName;
        }
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xAiModels\Providers\GraphQL\XAiMessageGraphQuery.cs

using System;
using GraphQL.Types;
using xAiModels.Interfaces.Entities;
using xAiModels.Models.Entities;
using xDataService.Configuration;
using xDataService.GraphQL;

namespace xAiModels.Providers.GraphQL
{
    public class XAiMessageGraphQuery : XBaseGraphQLQuery<XAiMessage, Guid, XAiMessageGraphType, GuidGraphType>
    {
        public XAiMessageGraphQuery(
            XDataServiceConfiguration configuration,
            IXAiMessageRepository repository,
            IXAiMessageGraphQLTypeHelper helper
        ) : base(
            configuration,
            repository,
            helper
        )
        { }
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xAiModels\Providers\GraphQL\XAiMessageGraphSchema.cs

using System;
using GraphQL.Types;

namespace xAiModels.Providers.GraphQL
{
    public class XAiMessageGraphSchema : Schema
    {
        public XAiMessageGraphSchema(IServiceProvider services) : base(services)
        {
            Query = (XAiMessageGraphQuery)services.GetService(typeof(XAiMessageGraphQuery));
        }
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xAiModels\Providers\GraphQL\XAiMessageGraphType.cs

using System;
using xAiModels.Models.Entities;
using xDataService.GraphQL;

namespace xAiModels.Providers.GraphQL
{
    public class XAiMessageGraphType: XBaseGraphObjectType<XAiMessage, Guid>
    {
        public XAiMessageGraphType() : base()
        {
            Field(x => x.Role);
            Field(x => x.OwnerId);
            Field(x => x.Content);
            Field(x => x.Metadata);
            Field(x => x.CreatedOn);
            Field(x => x.UpdatedAt);
            Field(x => x.ConversationId);
        }
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xAiModels\Providers\GraphQL\XAiProjectGraphQLTypeHelper.cs

using System;
using xAiModels.Constants;
using xAiModels.Interfaces.Entities;
using xAiModels.Models.Entities;
using xDataService.GraphQL;

namespace xAiModels.Providers.GraphQL
{
    public class XAiProjectGraphQLTypeHelper : XBaseGraphQLTypeHelper<XAiProject, Guid>, IXAiProjectGraphQLTypeHelper
    {
        public override string GetInQueryCollectionName()
        {
            return XAiModelsConstants.XAiProjectCollectionName;
        }

        public override string GetInQuerySingleName()
        {
            return XAiModelsConstants.XAiProjectSingleName;
        }
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xAiModels\Providers\GraphQL\XAiProjectGraphQuery.cs

using System;
using GraphQL.Types;
using xAiModels.Interfaces.Entities;
using xAiModels.Models.Entities;
using xDataService.Configuration;
using xDataService.GraphQL;

namespace xAiModels.Providers.GraphQL
{
    public class XAiProjectGraphQuery : XBaseGraphQLQuery<XAiProject, Guid, XAiProjectGraphType, GuidGraphType>
    {
        public XAiProjectGraphQuery(
            XDataServiceConfiguration configuration,
            IXAiProjectRepository repository,
            IXAiProjectGraphQLTypeHelper helper
        ) : base(
            configuration,
            repository,
            helper
        )
        { }
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xAiModels\Providers\GraphQL\XAiProjectGraphSchema.cs

using System;
using GraphQL.Types;

namespace xAiModels.Providers.GraphQL
{
    public class XAiProjectGraphSchema : Schema
    {
        public XAiProjectGraphSchema(IServiceProvider services) : base(services)
        {
            Query = (XAiProjectGraphQuery)services.GetService(typeof(XAiProjectGraphQuery));
        }
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xAiModels\Providers\GraphQL\XAiProjectGraphType.cs

using System;
using xAiModels.Models.Entities;
using xDataService.GraphQL;

namespace xAiModels.Providers.GraphQL
{
    public class XAiProjectGraphType : XBaseGraphObjectType<XAiProject, Guid>
    {
        public XAiProjectGraphType() : base()
        {
            Field(x => x.Title);
            Field(x => x.OwnerId);
            Field(x => x.Prompt);
            Field(x => x.CreatedOn);
            Field(x => x.UpdatedAt);
            Field(x => x.Description);
        }
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xAiModels\Providers\XAiConversationEntityRegisterar.cs

using System;
using Microsoft.EntityFrameworkCore;
using xAiModels.Configurations.Entities;
using xAiModels.Models.Entities;
using xDataService.Interfaces;
using xDataService.Providers;

namespace xAiModels.Providers
{
    public class XAiConversationEntityRegisterar : XBaseEntityRegisterar, IXEntityRegisterar
    {
        public XAiConversationEntityRegisterar()
        : base(nameof(XAiConversationEntityRegisterar))
        {
            //
            // Add Entity ...
            AddEntity<XAiConversation, Guid>();
        }

        /// <summary>
        /// Configure Entities ...
        /// </summary>
        /// <param name="modelBuilder"></param>
        public override void ConfigureEntities(ModelBuilder modelBuilder)
        {
            //
            // Configure Entity Using Provided ...
            modelBuilder
                .ApplyConfigurationsFromAssembly(typeof(XAiConversationEntityConfiguration).Assembly);

            //
            base.ConfigureEntities(modelBuilder);
        }
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xAiModels\Providers\XAiConversationTitleResourceProvider.cs

using xAiModels.Constants;
using xAiModels.Interfaces;
using xStringService.Interfaces.Dtos;
using xStringService.Providers;

namespace xAiModels.Providers
{
    public class XAiConversationTitleResourceProvider : XBaseItemResourceProvider, IXAiConversationTitleResourceProvider
    {
        public XAiConversationTitleResourceProvider(
            IXStringServiceProvider stringProvider
        ) : base(
            stringProvider: stringProvider,
            item: XAiModelsConstants.XAiConversationTitleIdentifier
        )
        { }
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xAiModels\Providers\XAiDataProvider.cs

using Microsoft.AspNetCore.SignalR;
using xAiModels.Interfaces;
using xAiModels.Interfaces.Entities;
using xAiModels.Providers.Dtos;
using xAiModels.Providers.Entities;

namespace xAiModels.Providers
{
    /// <summary>
    /// All Data Manipulation Requirements ...
    /// </summary>
    public class XAiDataProvider : IXAiDataProvider
    {
        private readonly IHubContext<XAiMessageDtoHub> messageDtoHub;
        private readonly IHubContext<XAiProjectDtoHub> projectDtoHub;
        private readonly IXAiMessageRepository messageRepositoryService;
        private readonly IXAiProjectRepository projectRepositoryService;
        private readonly IHubContext<XAiMessageEntityHub> messageEntityHub;
        private readonly IHubContext<XAiProjectEntityHub> projectEntityHub;
        private readonly IXAiConversationRepository conversationRepository;
        private readonly IHubContext<XAiConversationDtoHub> conversationDtoHub;
        private readonly IHubContext<XAiConversationEntityHub> conversationEntityHub;
        private readonly IXAiProjectTitleResourceProvider projectTitleResourceProvider;
        private readonly IXAiConversationTitleResourceProvider conversationTitleResourceProvider;
        private readonly IXAiProjectDescriptionResourceProvider projectDescriptionResourceProvider;

        public XAiDataProvider(
            IHubContext<XAiMessageDtoHub> messageDtoHub,
            IHubContext<XAiProjectDtoHub> projectDtoHub,
            IXAiMessageRepository messageRepositoryService,
            IXAiProjectRepository projectRepositoryService,
            IHubContext<XAiMessageEntityHub> messageEntityHub,
            IHubContext<XAiProjectEntityHub> projectEntityHub,
            IXAiConversationRepository conversationRepository,
            IHubContext<XAiConversationDtoHub> conversationDtoHub,
            IHubContext<XAiConversationEntityHub> conversationEntityHub,
            IXAiProjectTitleResourceProvider projectTitleResourceProvider,
            IXAiConversationTitleResourceProvider conversationTitleResourceProvider,
            IXAiProjectDescriptionResourceProvider projectDescriptionResourceProvider
        )
        {
            this.messageDtoHub = messageDtoHub;
            this.projectDtoHub = projectDtoHub;
            this.projectEntityHub = projectEntityHub;
            this.messageEntityHub = messageEntityHub;
            this.conversationDtoHub = conversationDtoHub;
            this.conversationEntityHub = conversationEntityHub;
            this.conversationRepository = conversationRepository;
            this.messageRepositoryService = messageRepositoryService;
            this.projectRepositoryService = projectRepositoryService;
            this.projectTitleResourceProvider = projectTitleResourceProvider;
            this.conversationTitleResourceProvider = conversationTitleResourceProvider;
            this.projectDescriptionResourceProvider = projectDescriptionResourceProvider;
        }
    
        
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xAiModels\Providers\XAiMessageEntityRegisterar.cs

using System;
using Microsoft.EntityFrameworkCore;
using xAiModels.Configurations.Entities;
using xAiModels.Models.Entities;
using xDataService.Interfaces;
using xDataService.Providers;

namespace xAiModels.Providers
{
    public class XAiMessageEntityRegisterar : XBaseEntityRegisterar, IXEntityRegisterar
    {
        public XAiMessageEntityRegisterar()
        : base(nameof(XAiMessageEntityRegisterar))
        {
            //
            // Add Entity ...
            AddEntity<XAiMessage, Guid>();
        }

        /// <summary>
        /// Configure Entities ...
        /// </summary>
        /// <param name="modelBuilder"></param>
        public override void ConfigureEntities(ModelBuilder modelBuilder)
        {
            //
            // Configure Entity Using Provided ...
            modelBuilder
                .ApplyConfigurationsFromAssembly(typeof(XAiMessageEntityConfiguration).Assembly);

            //
            base.ConfigureEntities(modelBuilder);
        }
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xAiModels\Providers\XAiProjectDescriptionResourceProvider.cs

using xAiModels.Constants;
using xAiModels.Interfaces;
using xStringService.Interfaces.Dtos;
using xStringService.Providers;

namespace xAiModels.Providers
{
    public class XAiProjectDescriptionResourceProvider : XBaseItemResourceProvider, IXAiProjectDescriptionResourceProvider
    {
        public XAiProjectDescriptionResourceProvider(
            IXStringServiceProvider stringProvider
        ) : base(
            stringProvider: stringProvider,
            item: XAiModelsConstants.XAiProjectDescriptionIdentifier
        )
        { }
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xAiModels\Providers\XAiProjectEntityRegisterar.cs

using System;
using Microsoft.EntityFrameworkCore;
using xAiModels.Configurations.Entities;
using xAiModels.Models.Entities;
using xDataService.Interfaces;
using xDataService.Providers;

namespace xAiModels.Providers
{
    public class XAiProjectEntityRegisterar : XBaseEntityRegisterar, IXEntityRegisterar
    {
        public XAiProjectEntityRegisterar()
        : base(nameof(XAiProjectEntityRegisterar))
        {
            //
            // Add Entity ...
            AddEntity<XAiProject, Guid>();
        }

        /// <summary>
        /// Configure Entities ...
        /// </summary>
        /// <param name="modelBuilder"></param>
        public override void ConfigureEntities(ModelBuilder modelBuilder)
        {
            //
            // Configure Entity Using Provided ...
            modelBuilder
                .ApplyConfigurationsFromAssembly(typeof(XAiProjectEntityConfiguration).Assembly);

            //
            base.ConfigureEntities(modelBuilder);
        }
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xAiModels\Providers\XAiProjectTitleResourceProvider.cs

using xAiModels.Constants;
using xAiModels.Interfaces;
using xStringService.Interfaces.Dtos;
using xStringService.Providers;

namespace xAiModels.Providers
{
    public class XAiProjectTitleResourceProvider : XBaseItemResourceProvider, IXAiProjectTitleResourceProvider
    {
        public XAiProjectTitleResourceProvider(
            IXStringServiceProvider stringProvider
        ) : base(
            stringProvider: stringProvider,
            item: XAiModelsConstants.XAiProjectTitleIdentifier
        )
        { }
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xAiService\Configurations\XAIServiceConfiguration.cs

namespace xAiService.Configurations
{
    public partial class XAIServiceConfiguration
    {
        public string Url { get; set; }
        public string XPoweredValue { get; set; }
        public int DefaultClientTimeout { get; set; } = 360;
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xAiService\Constants\ConfigurationNodeNames.cs

namespace xAiService.Constants
{
    public partial struct ConfigurationNodeNames
    {
        public const string AI_SERVICE_NODE = "AIServiceConfiguration";
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xAiService\Constants\XAiApiConstants.cs

namespace xAiService.Constants
{
    public struct XAiApiQueryParams
    {
        public const string Prompt = "prompt";
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xAiService\Constants\XAiApiEndpoint.cs

using xExceptions.Attributes;

namespace xAiService.Constants
{
    public enum XAiApiEndpoint
    {
        [StringValue("AskAI")]
        Ask,
        [StringValue("AskAIStream")]
        Stream,
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xAiService\DI\XDIHelperExtension.cs

using System;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using xAiService.Configurations;
using xAiService.Constants;
using xAiService.Extensions;
using xAiService.Interfaces;
using xAiService.Services;
using xCommons.Extensions;
using xExceptions.Constants;

namespace xAiService.DI
{
    public static partial class XDIHelperExtension
    {
        /// <summary>
        /// Extract AI Service Configuration ...
        /// </summary>
        /// <param name="source"></param>
        /// <returns></returns>
        public static XAIServiceConfiguration GetXAIServiceConfiguration(this IConfiguration source)
        {
            //
            XAIServiceConfiguration result = null;

            //
            var section = source.GetSection(ConfigurationNodeNames.AI_SERVICE_NODE);
            if (!section.IsNull())
            {
                result = section.Get<XAIServiceConfiguration>();
            }

            //
            return result;
        }

        /// <summary>
        /// Add AI Service Configuration ...
        /// </summary>
        /// <param name="source"></param>
        /// <param name="configuration"></param>
        public static void AddXAIServiceConfiguration(
            this IServiceCollection source,
            XAIServiceConfiguration configuration
        )
        {
            source.AddSingleton<XAIServiceConfiguration>(configuration);
        }

        /// <summary>
        /// Adding XAiService ...
        /// </summary>
        /// <param name="services"></param>
        /// <param name="configuration"></param>
        /// <param name="lifeTime"></param>
        public static void AddXAIService(
            this IServiceCollection services,
            IConfiguration configuration,
            ServiceLifetime lifeTime = ServiceLifetime.Scoped
        )
        {
            //
            var config = configuration.GetXAIServiceConfiguration();
            AddAIService(
                services,
                config,
                lifeTime
            );
        }

        /// <summary>
        /// Adding XAiService ...
        /// </summary>
        /// <param name="services"></param>
        /// <param name="configuration"></param>
        /// <param name="lifeTime"></param>
        public static void AddXAIService(
            this IServiceCollection services,
            XAIServiceConfiguration configuration,
            ServiceLifetime lifeTime = ServiceLifetime.Scoped
        )
        {
            //
            AddAIService(
                services,
                configuration,
                lifeTime
            );
        }

        //
        #region Private ...
        /// <summary>
        /// a LogTag for Service ...
        /// </summary>
        private static string XLogTag = "XFileService";

        /// <summary>
        /// print a log in Console ...
        /// </summary>
        /// <param name="message"></param>
        private static void Log(string message)
        {
            Console.WriteLine($"{XLogTag} => {message}");
        }

        /// <summary>
        /// Adding Ai Service ...
        /// </summary>
        /// <param name="services"></param>
        /// <param name="configuration"></param>
        /// <param name="lifeTime"></param>
        private static void AddAIService(
            this IServiceCollection services,
            XAIServiceConfiguration configuration,
            ServiceLifetime lifeTime = ServiceLifetime.Singleton
        )
        {
            //
            var exception = XException.InvalidArgs.ToException(); ;

            //
            // Services ...
            var isServicesExists = !services.IsNull();
            if (!isServicesExists)
            {
                //
                Log("AddAIService failed, services not provided ...");
                throw exception;
            }

            //
            // Lifetime ...
            var isLifetimeExists = !lifeTime.IsNull();
            if (!isLifetimeExists)
            {
                //
                Log("AddAIService failed, lifetime not provided ...");
                throw exception;
            }

            //
            // Check Dependencies Exists ...
            var isDependenciesPassed = true;
            if (!isDependenciesPassed)
            {
                //
                Log("AddAIService failed due Dependencies Issues, not provided ...");
                throw exception;
            }

            //
            // Validate Configurations ...
            var isConfigurationExists =
                !configuration.IsNull() &&
                configuration.IsValid();
            if (!isConfigurationExists)
            {
                //
                Log("AddAIService failed due InValid Service Configuration or not provided ...");
                throw exception;
            }

            //
            // Register Configurations ...
            services.AddXAIServiceConfiguration(configuration);

            //
            // Register Services ...
            services.Add(new ServiceDescriptor(typeof(IXAiService), typeof(XAiService), lifeTime));
        }
        #endregion
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xAiService\Extensions\ConfigurationExtensions.cs

using xAiService.Configurations;
using xCommons.Extensions;

namespace xAiService.Extensions
{
    public static class ModelExtensions
    {
        /// <summary>
        /// Validate XAiServiceConfiguration ...
        /// </summary>
        /// <param name="source"></param>
        /// <returns></returns>
        public static bool IsValid(this XAIServiceConfiguration source)
        {
            //
            bool result =
                !source.IsNull() &&
                !source.Url.IsNullOrEmpty() &&
                source.Url.IsValidUrl();

            //
            return result;
        }
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xAiService\Extensions\PromptExtensions.cs

using System.Collections.Generic;
using System.Linq;
using xAiService.Models.Dtos;
using xCommons.Extensions;

namespace xAiService.Extensions
{
    public static class PromptExtensions
    {
        /// <summary>
        /// Get Template Params Filled Prompt ...
        /// </summary>
        /// <param name="source"></param>
        /// <param name="params"></param>
        /// <returns></returns>
        public static string GetMessage(
            this XPromptDto source,
            IDictionary<string, string> @params = null
        )
        {
            //
            var result = string.Empty;

            //
            if (!source.IsNullOrDefault() &&
                !source.Prompt.IsNullOrEmpty()
            )
            {
                result = source.Prompt;
            }

            //
            // Check Params Conditions ...
            if (!source.Params.IsNullOrDefault() &&
                source.Params.HasChild() &&
                !@params.IsNullOrDefault() &&
                @params.HasChild()
            )
            {
                //
                // Select Params ...
                var existsParams = source.Params
                    .Where(p => @params.Any(pr => pr.Key == p.Name))
                    .Distinct()
                    .ToList();

                //
                // Replace Selected Params ...
                existsParams
                    .ForEach(pk =>
                    {
                        result = result.Replace(pk.Param, @params[pk.Name]);
                    });
            }

            //
            return result;
        }
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xAiService\Helpers\XPromptHelper.cs

using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text.Json;
using System.Text.Json.Serialization;
using xAiService.Models.Dtos;
using xCommons.Extensions;

namespace xAiService.Helpers
{
    public static class XPromptHelper
    {
        /// <summary>
        /// Holds Initialized Prompts ...
        /// </summary>
        private static XPromptsDto prompts;

        /// <summary>
        /// Initialize Prompt Helper ...
        /// </summary>
        /// <param name="path"></param>
        /// <exception cref="Exception"></exception>
        /// <exception cref="InvalidDataException"></exception>
        public static void Initialize(string path = "prompts.json")
        {
            //
            // Create full Path and Check File Exists ...
            var fullPath = Path.Combine(AppContext.BaseDirectory, path);
            if (!File.Exists(fullPath))
            {
                throw new Exception($"Prompts Resources not found: {fullPath}");
            }

            //
            // Read File as Json Text ...
            var json = File.ReadAllText(fullPath);
            var options = new JsonSerializerOptions
            {
                AllowTrailingCommas = true,
                PropertyNameCaseInsensitive = true,
                ReadCommentHandling = JsonCommentHandling.Skip,
                Converters =
                {
                    new JsonStringEnumConverter(
                        namingPolicy: null,
                        allowIntegerValues: false
                    )
                }
            };

            //
            // Serialized Root Object ...
            var root = JsonSerializer.Deserialize<XPromptsDto>(json, options);
            if (!root.IsNullOrDefault())
            {
                prompts = new XPromptsDto { Prompts = root.Prompts };
            }
        }

        /// <summary>
        /// Retrieve all Allowed Prompts as Enumerable ...
        /// </summary>
        /// <returns></returns>
        public static IEnumerable<XPromptDto> GetPrompts()
        {
            return prompts!.Prompts.AsEnumerable();
        }

        /// <summary>
        /// Get Specified Prompt ...
        /// </summary>
        /// <param name="name"></param>
        /// <returns></returns>
        /// <exception cref="Exception"></exception>
        public static XPromptDto GetPrompt(string name)
        {
            //
            return GetPrompts()
                .FirstOrDefault(p => p.Name == name);
        }
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xAiService\Interfaces\IXAiService.cs

using System.IO;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.Extensions.AI;
using xAiService.Configurations;
using xIdentityModels.Models;
using xIdentityService.Interfaces;

namespace xAiService.Interfaces
{
    public interface IXAiService : IXBaseIdentityHttpProvider
    {
        /// <summary>
        /// XAiService Configurations ...
        /// </summary>
        /// <value></value>
        XAIServiceConfiguration Configuration { get; }

        //
        #region Text Actions ...
        /// <summary>
        /// Generated Response ...
        /// </summary>
        /// <param name="prompt"></param>
        /// <param name="userInfo"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public Task<ChatResponse> GetResponseAsync(
            string prompt,
            XUserClaimsInfoDto userInfo,
            CancellationToken cancellationToken = default
        );

        /// <summary>
        /// Generated Response ...
        /// </summary>
        /// <param name="prompt"></param>
        /// <param name="userInfo"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public Task<string> GetTextResponseAsync(
            string prompt,
            XUserClaimsInfoDto userInfo,
            CancellationToken cancellationToken = default
        );

        /// <summary>
        /// Generate Text Response Stream ...
        /// </summary>
        /// <param name="prompt"></param>
        /// <param name="userInfo"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        Task<Stream> GetTextReponseStreamAsync(
            string prompt,
            XUserClaimsInfoDto userInfo,
            CancellationToken cancellationToken = default
        );
        #endregion
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xAiService\Interfaces\IXAiServiceControllerBase.cs

using System.Threading;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;

namespace xAiService.Interfaces
{
    public interface IXAiServiceControllerBase
    {
        Task<ActionResult<string>> Ask(
            [FromQuery] string prompt,
            CancellationToken cancellationToken = default
        );
        
        Task<ActionResult> AskStream(
            [FromQuery] string prompt,
            CancellationToken cancellationToken = default
        );        
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xAiService\Models\Dtos\XPromptsDto.cs

namespace xAiService.Models.Dtos
{
    /// <summary>
    /// Described Prompts in app ...
    /// </summary>
    public class XPromptsDto
    {
        public XPromptDto[] Prompts { get; set; } = [];
    }

    /// <summary>
    /// a Single Prompt Description ...
    /// </summary>
    public class XPromptDto
    {
        /// <summary>
        /// Prompt Name ...
        /// </summary>
        public string Name { get; set; }

        /// <summary>
        /// Prompt Template Message ...
        /// </summary>
        public string Prompt { get; set; }

        /// <summary>
        /// Prompt Description ...
        /// </summary>
        public string Description { get; set; }

        /// <summary>
        /// Describe Prompt Params ...
        /// </summary>
        public virtual XPromptParamDto[] Params { get; set; } = null;
    }

    /// <summary>
    /// Prompt Param used to Fill dynamic Datas to Specified Prompts ...
    /// </summary>
    public class XPromptParamDto
    {
        /// <summary>
        /// Param Name ...
        /// </summary>
        public string Name { get; set; }

        /// <summary>
        /// Parma Identifier ...
        /// </summary>
        public string Param { get; set; }

        /// <summary>
        /// Param Description ...
        /// </summary>
        public string Description { get; set; }
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xAiService\Services\XAiService.cs

using System.Collections.Generic;
using System.IO;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.Extensions.AI;
using Microsoft.Extensions.Logging;
using xAiService.Configurations;
using xAiService.Constants;
using xAiService.Interfaces;
using xCommons.Providers;
using xHttpService.Constants;
using xIdentityModels.Models;
using xIdentityService.Interfaces;
using xIdentityService.Providers;

namespace xAiService.Services
{
    public class XAiService : XBaseIdentityHttpProvider, IXAiService
    {
        /// <summary>
        /// XAiService Configurations ...
        /// </summary>
        /// <value></value>
        public XAIServiceConfiguration Configuration { get; }

        public XAiService(
            ILogger<XAiService> logger,
            IXTokenProvider tokenProvider,
            IXIdentityProvider identityProvider,
            XAIServiceConfiguration configuration,
            XValidationProvider validationProvider
        ) : base(
            configuration.Url,
            logger,
            configuration.XPoweredValue,
            configuration.DefaultClientTimeout,
            tokenProvider,
            identityProvider,
            validationProvider
        )
        { }

        //
        #region Text Actions ...
        /// <summary>
        /// Generated Response ...
        /// </summary>
        /// <param name="prompt"></param>
        /// <param name="userInfo"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public Task<ChatResponse> GetResponseAsync(
            string prompt,
            XUserClaimsInfoDto userInfo,
            CancellationToken cancellationToken = default
        )
        {
            throw new System.NotImplementedException();
        }

        /// <summary>
        /// Generated Response ...
        /// </summary>
        /// <param name="prompt"></param>
        /// <param name="userInfo"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public async Task<string> GetTextResponseAsync(
            string prompt,
            XUserClaimsInfoDto userInfo,
            CancellationToken cancellationToken = default
        )
        {
            //
            // Validate Args ...
            ValidationProvider.NotEmpty(prompt);

            //
            var client = GetRestClient(userInfo);
            var request = GetRestRequet(
                endpoint: XAiApiEndpoint.Ask,
                addXPoweredValue: true,
                queryStrings: new Dictionary<string, string>
                {
                    { XAiApiQueryParams.Prompt, prompt }
                }
            );

            //
            var response = await RunRestRequest<string>(
                client,
                request,
                XHttpMethod.GET,
                cancellationToken: cancellationToken
            );

            //
            return response;
        }

        /// <summary>
        /// Generate Text Response Stream ...
        /// </summary>
        /// <param name="prompt"></param>
        /// <param name="userInfo"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public async Task<Stream> GetTextReponseStreamAsync(
            string prompt,
            XUserClaimsInfoDto userInfo,
            CancellationToken cancellationToken = default
        )
        {
            //
            // Validate Args ...
            ValidationProvider
                .GroupValidationBuilder()
                .AddNotEmpty(prompt)
                .AddNotNull(userInfo)
                .AddNotZero(userInfo.ExpiresAt)
                .AddNotEmpty(userInfo.AccessToken)
                .AddNotEmpty(userInfo.RefreshToken)
                .ValidateGroup();

            //
            var tokens = ToTokenResponse(userInfo);
            var result = await StreamData(
                tokens: tokens,
                addXPoweredValue: true,
                endpoint: XAiApiEndpoint.Stream,
                cancellationToken: cancellationToken,
                queryStrings: new Dictionary<string, string>
                {
                    { XAiApiQueryParams.Prompt, prompt }
                }
            );

            //
            return result;
        }
        #endregion
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xCategoryService\Configurations\Entities\XCategoryEntityConfiguration.cs

using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Metadata.Builders;
using xCategoryService.Constants;
using xCategoryService.Models.Entities;
using xDataService.Providers;

namespace xCategoryService.Configurations.Entities
{
    public class XCategoryEntityConfiguration : XBaseEntityTypeConfiguration<XCategory, int>
    {
        public override void Configure(EntityTypeBuilder<XCategory> builder)
        {
            builder.ToTable(XCategoryServiceConstants.XCategoryTable);
        }
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xCategoryService\Configurations\Entities\XSubCategoryEntityConfiguration.cs

using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Metadata.Builders;
using xCategoryService.Constants;
using xCategoryService.Models.Entities;
using xDataService.Providers;

namespace xCategoryService.Configurations.Entities
{
    public class XSubCategoryEntityConfiguration : XBaseEntityTypeConfiguration<XSubCategory, int>
    {
        public override void Configure(EntityTypeBuilder<XSubCategory> builder)
        {
            builder.ToTable(XCategoryServiceConstants.XSubCategoryTable);
        }
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xCategoryService\Configurations\XCategoryServiceConfiguration.cs

using xCategoryService.Models.Dtos;

namespace xCategoryService.Configurations
{
    /// <summary>
    /// a Configuration Class for Providing Data to Configure XCategoryService ...
    /// </summary>
    public class XCategoryServiceConfiguration
    {
        /// <summary>
        /// a List of Categories for Seeding ...
        /// </summary>
        public XCategoryResourceDto[] Categories { get; set; } = [];

        /// <summary>
        /// a List of SubCategories for Seeding ...
        /// </summary>
        public XSubCategoryResourceDto[] SubCategories { get; set; } = [];
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xCategoryService\Constants\ConfigurationNodeNames.cs

namespace xCategoryService.Constants
{
    public partial struct ConfigurationNodeNames
    {
        public const string CATEGORY_SERVICE_NODE = "CategoryServiceConfiguration";
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xCategoryService\Constants\XCategoryServiceConstants.cs

namespace xCategoryService.Constants
{
    public struct XCategoryServiceConstants
    {
        //
        // Service Extensions Log Tag ...
        public const string XCategoryServiceDILogTag = "XCategoryService";

        //
        // Table Mapping Identifiers ...
        public const string XCategoryTable = "Categories";
        public const string XSubCategoryTable = "SubCategories";

        //
        // GraphQL Collection Mappings ...
        public const string XCategorySingleName = "category";
        public const string XCategoryCollectionName = "categories";
        public const string XSubCategorySingleName = "subCategory";
        public const string XSubCategoryCollectionName = "subCategories";

        //
        // Hubs ...
        public const string XCategoryDtoHub = "categoryDto";
        public const string XCategoryEntityHub = "categoryEntity";
        public const string XSubCategoryDtoHub = "subCategoryDto";
        public const string XSubCategoryEntityHub = "subCategoryEntity";

        //
        // Custome Constants ...
        public const string SubCategoryReference = "SubCat";
        public const string CategoryTitleResourceIdentifier = "CatT";
        public const string CategoryDescriptionResourceIdentifier = "CatD";
        public const string SubCategoryTitleResourceIdentifier = "SubCatT";
        public const string SubCategoryDescriptionResourceIdentifier = "SubCatD";

        //
        // EF Repositories Helper Extensions ...
        public const string GetXCategoryEFRepositoryDescriptor = "GetXCategoryEFRepositoryDescriptor";
        public const string GetXSubCategoryEFRepositoryDescriptor = "GetXSubCategoryEFRepositoryDescriptor";
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xCategoryService\Controllers\XCategoryProviderControllerBase.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore.Query;
using Microsoft.Extensions.Logging;
using xCategoryService.Interfaces;
using xCategoryService.Models.Dtos;
using xCategoryService.Models.Entities;
using xCategoryService.Providers.Dtos;
using xCommons.Configurations;
using xCommons.Extensions;
using xCommons.Providers;
using xExceptions.Constants;
using xIdentityService.Interfaces;
using xModels.Dtos;
using xPushService.Controllers;

namespace xCategoryService.Controllers
{
    public abstract class XCategoryProviderControllerBase : XBaseProvidedController<XCategory, XCategoryDto, int, XCategoryDtoHub>, IXCategoryProviderController
    {
        private readonly IXCategoryProvider provider;

        protected XCategoryProviderControllerBase(
            ILogger<XCategoryProviderControllerBase> logger,
            XAppConfiguration appConfiguration,
            IXIdentityProvider identityProvider,
            XValidationProvider validationProvider,
            IXCategoryProvider provider,
            Func<IQueryable<XCategory>, IOrderedQueryable<XCategory>> defaultOrderBuilder = null,
            Func<IQueryable<XCategory>, IIncludableQueryable<XCategory, object>> defaultIncludeBuilder = null
        ) : base(
            logger,
            appConfiguration,
            identityProvider,
            validationProvider,
            provider,
            defaultOrderBuilder,
            defaultIncludeBuilder
        )
        {
            this.provider = provider;
        }

        //
        #region Overrides ...
        [NonAction]
        [HttpGet("{id}")]
        public override async Task<ActionResult<XCategoryDto>> Get(
            [FromRoute] int id,
            [FromQuery] bool useDefaultIncludes = false,
            CancellationToken cancellationToken = default
        )
        {
            //
            return await base.Get(
                id: id,
                useDefaultIncludes: useDefaultIncludes,
                cancellationToken: cancellationToken
            );
        }

        [NonAction]
        [HttpGet("")]
        public override async Task<ActionResult<IEnumerable<XCategoryDto>>> GetAll(
            [FromQuery] bool useDefaultOrders = false,
            [FromQuery] bool useDefaultIncludes = false,
            CancellationToken cancellationToken = default
        )
        {
            //
            return await base.GetAll(
                useDefaultOrders: useDefaultOrders,
                cancellationToken: cancellationToken,
                useDefaultIncludes: useDefaultIncludes
            );
        }

        [NonAction]
        [HttpGet("Find/One")]
        public override async Task<ActionResult<XCategoryDto>> FindOne(
            [FromRoute] string query,
            [FromQuery] bool useDefaultIncludes = false,
            CancellationToken cancellationToken = default
        )
        {
            //
            return await base.FindOne(
                query: query,
                cancellationToken: cancellationToken,
                useDefaultIncludes: useDefaultIncludes
            );
        }

        [NonAction]
        [HttpGet("Find/Many")]
        public override async Task<ActionResult<IEnumerable<XCategoryDto>>> FindMany(
            [FromRoute] string query,
            [FromQuery] bool useDefaultOrders = false,
            [FromQuery] bool useDefaultIncludes = false,
            CancellationToken cancellationToken = default
        )
        {
            //
            return await base.FindMany(
                query: query,
                useDefaultOrders: useDefaultOrders,
                cancellationToken: cancellationToken,
                useDefaultIncludes: useDefaultIncludes
            );
        }

        [NonAction]
        [HttpGet("Query")]
        public override async Task<ActionResult<XQueryResult<XCategoryDto>>> Query(
            [FromQuery] XQuery query,
            [FromQuery] bool useDefaultOrders = false,
            [FromQuery] bool useDefaultIncludes = false,
            CancellationToken cancellationToken = default
        )
        {
            //
            return await base.Query(
                query: query,
                useDefaultOrders: useDefaultOrders,
                cancellationToken: cancellationToken,
                useDefaultIncludes: useDefaultIncludes
            );
        }

        [NonAction]
        [HttpGet("Query/Owned")]
        public override async Task<ActionResult<XQueryResult<XCategoryDto>>> QueryOwned(
            [FromQuery] XQuery query,
            [FromQuery] bool useDefaultOrders = false,
            [FromQuery] bool useDefaultIncludes = false,
            CancellationToken cancellationToken = default
        )
        {
            //
            return await base.QueryOwned(
                query: query,
                useDefaultOrders: useDefaultOrders,
                cancellationToken: cancellationToken,
                useDefaultIncludes: useDefaultIncludes
            );
        }

        [NonAction]
        [HttpPost("")]
        public override async Task<ActionResult<XCategoryDto>> Add(
            [FromBody] XCategoryDto item,
            CancellationToken cancellationToken = default
        )
        {
            //
            return await base.Add(
                item: item,
                cancellationToken: cancellationToken
            );
        }

        [NonAction]
        [HttpPut("{id}")]
        public override async Task<ActionResult<XCategoryDto>> Update(
            [FromRoute] int id,
            [FromBody] XCategoryDto item,
            CancellationToken cancellationToken = default
        )
        {
            //
            return await base.Update(
                id: id,
                item: item,
                cancellationToken: cancellationToken
            );
        }

        [NonAction]
        [HttpDelete("{id}")]
        public override async Task<ActionResult<XCategoryDto>> Remove(
            [FromRoute] int id,
            CancellationToken cancellationToken = default
        )
        {
            //
            return await base.Remove(
                id: id,
                cancellationToken: cancellationToken
            );
        }
        #endregion

        //
        #region Actions ...
        /// <summary>
        /// Check Has Specified Locale or not ...
        /// </summary>
        /// <param name="id"></param>
        /// <param name="language"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        [HttpGet("Resources/{id}/HasLocale")]
        public virtual async Task<ActionResult<bool>> HasLocale(
            [FromRoute] int id,
            [FromQuery] string language,
            CancellationToken cancellationToken = default
        )
        {
            //
            try
            {
                //
                // Validate ...
                if (!ModelState.IsValid ||
                    !id.IsValidIntId())
                {
                    XException.InvalidArgs.Throw();
                }
                ValidationProvider.NotEmpty(language);

                //
                var result = await provider.HasLocale(
                    id: id,
                    language: language,
                    cancellationToken: cancellationToken
                );

                //
                return Ok(result);
            }
            catch (Exception ex)
            {
                //
                var result = GetExceptionActionResult(ex);
                return result;
            }
        }

        /// <summary>
        /// Load an Item by all of it's Related Translations ...
        /// </summary>
        /// <param name="id"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        [HttpGet("Resources/{id}")]
        public virtual async Task<ActionResult<XCategoryResourceDto>> GetResource(
            [FromRoute] int id,
            CancellationToken cancellationToken = default
        )
        {
            //
            try
            {
                //
                // Validate ...
                if (!ModelState.IsValid ||
                    !id.IsValidIntId())
                {
                    XException.InvalidArgs.Throw();
                }

                //
                var result = await provider.GetResource(
                    id: id,
                    cancellationToken: cancellationToken
                );

                //
                return Ok(result.ToDynamicObject());
            }
            catch (Exception ex)
            {
                //
                var result = GetExceptionActionResult(ex);
                return result;
            }
        }

        /// <summary>
        /// Add Category Item for Specified Language ...
        /// </summary>
        /// <param name="item"></param>
        /// <param name="language"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        [HttpPost("Resources")]
        public virtual async Task<ActionResult<XCategoryResourceDto>> Add(
            [FromBody] XCategoryDto item,
            [FromQuery] string language = null,
            CancellationToken cancellationToken = default
        )
        {
            //
            try
            {
                //
                // Validate ...
                if (!ModelState.IsValid)
                {
                    XException.InvalidArgs.Throw();
                }
                await ValidationProvider
                    .GroupValidationBuilder()
                    .AddNotNull(item)
                    .AddNotEmpty(language)
                    .AddNotEmpty(item.Title)
                    .AddNotEmpty(item.Description)
                    .ValidateGroupAsync();

                //
                // Reading Requirements ...
                var userInfo = await GetUserInfo();
                var connectionId = GetConnectionId();

                //
                var result = await provider.Add(
                    item: item,
                    language: language,
                    userInfo: userInfo,
                    connectionId: connectionId,
                    cancellationToken: cancellationToken
                );

                //
                return Ok(result.ToDynamicObject());
            }
            catch (Exception ex)
            {
                //
                var result = GetExceptionActionResult(ex);
                return result;
            }
        }

        /// <summary>
        /// Add Category Item for by It's Locales ...
        /// </summary>
        /// <param name="item"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        [HttpPost("Resources/AddResource")]
        public virtual async Task<ActionResult<XCategoryResourceDto>> AddResource(
            [FromBody] XCategoryResourceDto item,
            CancellationToken cancellationToken = default
        )
        {
            //
            try
            {
                //
                // Validate ...
                if (!ModelState.IsValid)
                {
                    XException.InvalidArgs.Throw();
                }
                await ValidationProvider
                    .GroupValidationBuilder()
                    .AddNotNull(item)
                    .AddNotNull(item.Titles)
                    .AddNotZeroChilds(item.Titles.Locales)
                    .ValidateGroupAsync();

                //
                // Reading Requirements ...
                var userInfo = await GetUserInfo();
                var connectionId = GetConnectionId();

                //
                var result = await provider.AddResource(
                    item: item,
                    userInfo: userInfo,
                    connectionId: connectionId,
                    cancellationToken: cancellationToken
                );

                //
                return Ok(result.ToDynamicObject());
            }
            catch (Exception ex)
            {
                //
                var result = GetExceptionActionResult(ex);
                return result;
            }
        }

        /// <summary>
        /// Remove Item for Specified Language ...
        /// </summary>
        /// <param name="id"></param>
        /// <param name="language">if null, Remove All</param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        [HttpDelete("Resources/{id}")]
        public virtual async Task<ActionResult<XCategoryResourceDto>> Remove(
            [FromRoute] int id,
            [FromQuery] string language = null,
            CancellationToken cancellationToken = default
        )
        {
            //
            try
            {
                //
                // Validate ...
                if (!ModelState.IsValid ||
                    !id.IsValidIntId())
                {
                    XException.InvalidArgs.Throw();
                }

                //
                // Reading Requirements ...
                var userInfo = await GetUserInfo();
                var connectionId = GetConnectionId();

                //
                var result = await provider.Remove(
                    id: id,
                    language: language,
                    userInfo: userInfo,
                    connectionId: connectionId,
                    cancellationToken: cancellationToken
                );

                //
                return Ok(result.ToDynamicObject());
            }
            catch (Exception ex)
            {
                //
                var result = GetExceptionActionResult(ex);
                return result;
            }            
        }

        /// <summary>
        /// Update a Category Item for Specified Language ...
        /// </summary>
        /// <param name="id"></param>
        /// <param name="item"></param>
        /// <param name="language"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        [HttpPut("Resources/{id}")]
        public virtual async Task<ActionResult<XCategoryResourceDto>> Update(
            [FromRoute] int id,
            [FromBody] XCategoryDto item,
            [FromQuery] string language = null,
            CancellationToken cancellationToken = default
        )
        {
            //
            try
            {
                //
                // Validate ...
                if (!ModelState.IsValid ||
                    !id.IsValidIntId())
                {
                    XException.InvalidArgs.Throw();
                }
                await ValidationProvider
                    .GroupValidationBuilder()
                    .AddNotNull(item)
                    .AddNotEmpty(language)
                    .AddNotEmpty(item.Title)
                    .AddNotEmpty(item.Description)
                    .ValidateGroupAsync();

                //
                // Reading Requirements ...
                var userInfo = await GetUserInfo();
                var connectionId = GetConnectionId();

                //
                var result = await provider.Update(
                    id: id,
                    item: item,
                    language: language,
                    userInfo: userInfo,
                    connectionId: connectionId,
                    cancellationToken: cancellationToken
                );

                //
                return Ok(result.ToDynamicObject());
            }
            catch (Exception ex)
            {
                //
                var result = GetExceptionActionResult(ex);
                return result;
            }
        }

        /// <summary>
        /// Refresh a Resource ...
        /// </summary>
        /// <param name="resource"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        [HttpPost("Resources/Refresh")]
        public virtual async Task<ActionResult<XCategoryResourceDto>> Refresh(
            [FromBody] XCategoryResourceDto resource,
            CancellationToken cancellationToken = default
        )
        {
            //
            try
            {
                //
                // Validate ...
                if (!ModelState.IsValid)
                {
                    XException.InvalidArgs.Throw();
                }
                await ValidationProvider
                    .GroupValidationBuilder()
                    .AddNotNull(resource)
                    .AddNotNull(resource.Item)
                    .ValidateGroupAsync();

                //
                // Reading Requirements ...
                var userInfo = await GetUserInfo();
                var connectionId = GetConnectionId();

                //
                var result = await provider.Refresh(
                    resource: resource,
                    userInfo: userInfo,
                    connectionId: connectionId,
                    cancellationToken: cancellationToken
                );

                //
                return Ok(result.ToDynamicObject());
            }
            catch (Exception ex)
            {
                //
                var result = GetExceptionActionResult(ex);
                return result;
            }
        }

        /// <summary>
        /// Get All Resources ...
        /// </summary>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        [HttpGet("Resources/All")]
        public virtual async Task<ActionResult<IEnumerable<XCategoryResourceDto>>> GetAllResources(
            CancellationToken cancellationToken = default
        )
        {
            //
            try
            {
                //
                // Validate ...
                if (!ModelState.IsValid)
                {
                    XException.InvalidArgs.Throw();
                }

                //
                var result = await provider.GetAllResources(
                    cancellationToken: cancellationToken
                );

                //
                return Ok(result.ToDynamicObject());
            }
            catch (Exception ex)
            {
                //
                var result = GetExceptionActionResult(ex);
                return result;
            }
        }

        /// <summary>
        /// Find One Resource ...
        /// </summary>
        /// <param name="query"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        [HttpGet("Resources/Find/One")]
        public virtual async Task<ActionResult<XCategoryResourceDto>> FindOneResource(
            [FromQuery] string query,
            CancellationToken cancellationToken = default
        )
        {
            //
            try
            {
                //
                // Validate ...
                if (!ModelState.IsValid)
                {
                    XException.InvalidArgs.Throw();
                }
                await ValidationProvider
                    .GroupValidationBuilder()
                    .AddNotEmpty(query)
                    .ValidateGroupAsync();

                //
                var result = await provider.FindOneResource(
                    cancellationToken: cancellationToken,
                    predicate: x => x.PropValuesContains(query)
                );

                //
                return Ok(result.ToDynamicObject());
            }
            catch (Exception ex)
            {
                //
                var result = GetExceptionActionResult(ex);
                return result;
            }
        }

        /// <summary>
        /// Find Many Resource ...
        /// </summary>
        /// <param name="query"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        [HttpGet("Resources/Find/Many")]
        public virtual async Task<ActionResult<IEnumerable<XCategoryResourceDto>>> FindManyResource(
            [FromQuery] string query,
            CancellationToken cancellationToken = default
        )
        {
            //
            try
            {
                //
                // Validate ...
                if (!ModelState.IsValid)
                {
                    XException.InvalidArgs.Throw();
                }
                await ValidationProvider
                    .GroupValidationBuilder()
                    .AddNotEmpty(query)
                    .ValidateGroupAsync();

                //
                var result = await provider.FindManyResource(
                    cancellationToken: cancellationToken,
                    predicate: x => x.PropValuesContains(query),
                    orderBuilder: x => x.OrderBy(y => y.Item.Id)
                );

                //
                return Ok(result.ToDynamicObject());
            }
            catch (Exception ex)
            {
                //
                var result = GetExceptionActionResult(ex);
                return result;
            }
        }

        /// <summary>
        /// Retrieve Resources by Query Pattern ...
        /// </summary>
        /// <param name="query"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        [HttpGet("Resources/Query")]
        public virtual async Task<ActionResult<XQueryResult<XCategoryResourceDto>>> QueryResources(
            [FromQuery] XQuery query = null,
            CancellationToken cancellationToken = default
        )
        {
            //
            try
            {
                //
                // Validate ...
                if (!ModelState.IsValid)
                {
                    XException.InvalidArgs.Throw();
                }
                await ValidationProvider
                    .GroupValidationBuilder()
                    .AddNotNull(query)
                    .ValidateGroupAsync();

                //
                var result = await provider.QueryResources(
                    query: query,
                    predicate: null,
                    cancellationToken: cancellationToken,
                    orderBuilder: x => x.OrderBy(y => y.Item.Id)
                );

                //
                return Ok(result.ToDynamicObject());
            }
            catch (Exception ex)
            {
                //
                var result = GetExceptionActionResult(ex);
                return result;
            }
        }
        #endregion
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xCategoryService\Controllers\XCategoryRepositoryControllerBase.cs

using System;
using System.Linq;
using Microsoft.EntityFrameworkCore.Query;
using Microsoft.Extensions.Logging;
using xCategoryService.Interfaces.Entities;
using xCategoryService.Models.Entities;
using xCommons.Configurations;
using xCommons.Providers;
using xDataService.Controllers;
using xDataService.Interfaces;

namespace xCategoryService.Controllers
{
    public abstract class XCategoryRepositoryControllerBase : XBaseRepositoryController<XCategory, int>, IXBaseRepositoryController<XCategory, int>
    {
        protected XCategoryRepositoryControllerBase(
            ILogger<XCategoryRepositoryControllerBase> logger,
            XAppConfiguration appConfiguration,
            XValidationProvider validationProvider,
            IXCategoryRepository repository,
            Func<IQueryable<XCategory>, IOrderedQueryable<XCategory>> defaultOrderBuilder = null,
            Func<IQueryable<XCategory>, IIncludableQueryable<XCategory, object>> defaultIncludeBuilder = null
        ) : base(
            logger,
            appConfiguration,
            validationProvider,
            repository,
            defaultOrderBuilder,
            defaultIncludeBuilder
        )
        { }
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xCategoryService\Controllers\XCategoryRepositoryProviderControllerBase.cs

using System;
using System.Linq;
using Microsoft.EntityFrameworkCore.Query;
using Microsoft.Extensions.Logging;
using xCategoryService.Interfaces.Entities;
using xCategoryService.Models.Entities;
using xCategoryService.Providers.Entities;
using xCommons.Configurations;
using xCommons.Providers;
using xIdentityService.Interfaces;
using xPushService.Controllers;
using xPushService.Interfaces;

namespace xCategoryService.Controllers
{
    public abstract class XCategoryRepositoryProviderControllerBase : XBaseRepositoryProviderController<XCategory, int, XCategoryEntityHub>, IXBaseRepositoryProviderController<XCategory, int, XCategoryEntityHub>
    {
        protected XCategoryRepositoryProviderControllerBase(
            ILogger<XCategoryRepositoryProviderControllerBase> logger,
            XAppConfiguration appConfiguration,
            IXIdentityProvider identityProvider,
            XValidationProvider validationProvider,
            IXCategoryRepositoryProvider provider,
            Func<IQueryable<XCategory>, IOrderedQueryable<XCategory>> defaultOrderBuilder = null,
            Func<IQueryable<XCategory>, IIncludableQueryable<XCategory, object>> defaultIncludeBuilder = null
        ) : base(
            logger,
            appConfiguration,
            identityProvider,
            validationProvider,
            provider,
            defaultOrderBuilder,
            defaultIncludeBuilder
        )
        { }
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xCategoryService\Controllers\XCategoryServiceControllerBase.cs

using System;
using System.Linq;
using Microsoft.EntityFrameworkCore.Query;
using Microsoft.Extensions.Logging;
using xCategoryService.Interfaces.Dtos;
using xCategoryService.Models.Dtos;
using xCategoryService.Models.Entities;
using xCommons.Configurations;
using xCommons.Providers;
using xDataService.Controllers;
using xDataService.Interfaces;

namespace xCategoryService.Controllers
{
    public abstract class XCategoryServiceControllerBase : XBaseServiceController<XCategory, XCategoryDto, int>, IXBaseServiceController<XCategory, XCategoryDto, int>
    {
        protected XCategoryServiceControllerBase(
            ILogger<XCategoryServiceControllerBase> logger,
            XAppConfiguration appConfiguration,
            XValidationProvider validationProvider,
            IXCategoryRepositoryService repositoryService,
            Func<IQueryable<XCategory>, IOrderedQueryable<XCategory>> defaultOrderBuilder = null,
            Func<IQueryable<XCategory>, IIncludableQueryable<XCategory, object>> defaultIncludeBuilder = null
        ) : base(
            logger,
            appConfiguration,
            validationProvider,
            repositoryService,
            defaultOrderBuilder,
            defaultIncludeBuilder
        )
        { }
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xCategoryService\Controllers\XCategoryServiceProviderControllerBase.cs

using System;
using System.Linq;
using Microsoft.EntityFrameworkCore.Query;
using Microsoft.Extensions.Logging;
using xCategoryService.Interfaces.Dtos;
using xCategoryService.Models.Dtos;
using xCategoryService.Models.Entities;
using xCategoryService.Providers.Dtos;
using xCommons.Configurations;
using xCommons.Providers;
using xIdentityService.Interfaces;
using xPushService.Controllers;
using xPushService.Interfaces;

namespace xCategoryService.Controllers
{
    public abstract class XCategoryServiceProviderControllerBase : XBaseServiceProviderController<XCategory, XCategoryDto, int, XCategoryDtoHub>, IXBaseServiceProviderController<XCategory, XCategoryDto, int, XCategoryDtoHub>
    {
        protected XCategoryServiceProviderControllerBase(
            ILogger<XCategoryServiceProviderControllerBase> logger,
            XAppConfiguration appConfiguration,
            IXIdentityProvider identityProvider,
            XValidationProvider validationProvider,
            IXCategoryServiceProvider provider,
            Func<IQueryable<XCategory>, IOrderedQueryable<XCategory>> defaultOrderBuilder = null,
            Func<IQueryable<XCategory>, IIncludableQueryable<XCategory, object>> defaultIncludeBuilder = null
        ) : base(
            logger,
            appConfiguration,
            identityProvider,
            validationProvider,
            provider,
            defaultOrderBuilder,
            defaultIncludeBuilder
        )
        { }
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xCategoryService\Controllers\XSubCategoryProviderControllerBase.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore.Query;
using Microsoft.Extensions.Logging;
using xCategoryService.Interfaces;
using xCategoryService.Models.Dtos;
using xCategoryService.Models.Entities;
using xCategoryService.Providers.Dtos;
using xCommons.Configurations;
using xCommons.Extensions;
using xCommons.Providers;
using xExceptions.Constants;
using xIdentityService.Interfaces;
using xModels.Dtos;
using xPushService.Controllers;

namespace xCategoryService.Controllers
{
    public abstract class XSubCategoryProviderControllerBase : XBaseProvidedController<XSubCategory, XSubCategoryDto, int, XSubCategoryDtoHub>, IXSubCategoryProviderController
    {
        private readonly IXSubCategoryProvider provider;

        protected XSubCategoryProviderControllerBase(
            ILogger<XSubCategoryProviderControllerBase> logger,
            XAppConfiguration appConfiguration,
            IXIdentityProvider identityProvider,
            XValidationProvider validationProvider,
            IXSubCategoryProvider provider,
            Func<IQueryable<XSubCategory>, IOrderedQueryable<XSubCategory>> defaultOrderBuilder = null,
            Func<IQueryable<XSubCategory>, IIncludableQueryable<XSubCategory, object>> defaultIncludeBuilder = null
        ) : base(
            logger,
            appConfiguration,
            identityProvider,
            validationProvider,
            provider,
            defaultOrderBuilder,
            defaultIncludeBuilder
        )
        {
            this.provider = provider;
        }

        //
        #region Overrides ...
        [NonAction]
        [HttpGet("{id}")]
        public override async Task<ActionResult<XSubCategoryDto>> Get(
            [FromRoute] int id,
            [FromQuery] bool useDefaultIncludes = false,
            CancellationToken cancellationToken = default
        )
        {
            //
            return await base.Get(
                id: id,
                useDefaultIncludes: useDefaultIncludes,
                cancellationToken: cancellationToken
            );
        }

        [NonAction]
        [HttpGet("")]
        public override async Task<ActionResult<IEnumerable<XSubCategoryDto>>> GetAll(
            [FromQuery] bool useDefaultOrders = false,
            [FromQuery] bool useDefaultIncludes = false,
            CancellationToken cancellationToken = default
        )
        {
            //
            return await base.GetAll(
                useDefaultOrders: useDefaultOrders,
                cancellationToken: cancellationToken,
                useDefaultIncludes: useDefaultIncludes
            );
        }

        [NonAction]
        [HttpGet("Find/One")]
        public override async Task<ActionResult<XSubCategoryDto>> FindOne(
            [FromRoute] string query,
            [FromQuery] bool useDefaultIncludes = false,
            CancellationToken cancellationToken = default
        )
        {
            //
            return await base.FindOne(
                query: query,
                cancellationToken: cancellationToken,
                useDefaultIncludes: useDefaultIncludes
            );
        }

        [NonAction]
        [HttpGet("Find/Many")]
        public override async Task<ActionResult<IEnumerable<XSubCategoryDto>>> FindMany(
            [FromRoute] string query,
            [FromQuery] bool useDefaultOrders = false,
            [FromQuery] bool useDefaultIncludes = false,
            CancellationToken cancellationToken = default
        )
        {
            //
            return await base.FindMany(
                query: query,
                useDefaultOrders: useDefaultOrders,
                cancellationToken: cancellationToken,
                useDefaultIncludes: useDefaultIncludes
            );
        }

        [NonAction]
        [HttpGet("Query")]
        public override async Task<ActionResult<XQueryResult<XSubCategoryDto>>> Query(
            [FromQuery] XQuery query,
            [FromQuery] bool useDefaultOrders = false,
            [FromQuery] bool useDefaultIncludes = false,
            CancellationToken cancellationToken = default
        )
        {
            //
            return await base.Query(
                query: query,
                useDefaultOrders: useDefaultOrders,
                cancellationToken: cancellationToken,
                useDefaultIncludes: useDefaultIncludes
            );
        }

        [NonAction]
        [HttpGet("Query/Owned")]
        public override async Task<ActionResult<XQueryResult<XSubCategoryDto>>> QueryOwned(
            [FromQuery] XQuery query,
            [FromQuery] bool useDefaultOrders = false,
            [FromQuery] bool useDefaultIncludes = false,
            CancellationToken cancellationToken = default
        )
        {
            //
            return await base.QueryOwned(
                query: query,
                useDefaultOrders: useDefaultOrders,
                cancellationToken: cancellationToken,
                useDefaultIncludes: useDefaultIncludes
            );
        }

        [NonAction]
        [HttpPost("")]
        public override async Task<ActionResult<XSubCategoryDto>> Add(
            [FromBody] XSubCategoryDto item,
            CancellationToken cancellationToken = default
        )
        {
            //
            return await base.Add(
                item: item,
                cancellationToken: cancellationToken
            );
        }

        [NonAction]
        [HttpPut("{id}")]
        public override async Task<ActionResult<XSubCategoryDto>> Update(
            [FromRoute] int id,
            [FromBody] XSubCategoryDto item,
            CancellationToken cancellationToken = default
        )
        {
            //
            return await base.Update(
                id: id,
                item: item,
                cancellationToken: cancellationToken
            );
        }

        [NonAction]
        [HttpDelete("{id}")]
        public override async Task<ActionResult<XSubCategoryDto>> Remove(
            [FromRoute] int id,
            CancellationToken cancellationToken = default
        )
        {
            //
            return await base.Remove(
                id: id,
                cancellationToken: cancellationToken
            );
        }
        #endregion

        //
        #region Actions ...
        /// <summary>
        /// Check Has Specified Locale or not ...
        /// </summary>
        /// <param name="id"></param>
        /// <param name="language"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        [HttpGet("Resources/{id}/HasLocale")]
        public virtual async Task<ActionResult<bool>> HasLocale(
            [FromRoute] int id,
            [FromQuery] string language,
            CancellationToken cancellationToken = default
        )
        {
            //
            try
            {
                //
                // Validate ...
                if (!ModelState.IsValid ||
                    !id.IsValidIntId())
                {
                    XException.InvalidArgs.Throw();
                }
                ValidationProvider.NotEmpty(language);

                //
                var result = await provider.HasLocale(
                    id: id,
                    language: language,
                    cancellationToken: cancellationToken
                );

                //
                return Ok(result);
            }
            catch (Exception ex)
            {
                //
                var result = GetExceptionActionResult(ex);
                return result;
            }
        }

        /// <summary>
        /// Load an Item by all of it's Related Translations ...
        /// </summary>
        /// <param name="id"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        [HttpGet("Resources/{id}")]
        public virtual async Task<ActionResult<XSubCategoryResourceDto>> GetResource(
            [FromRoute] int id,
            CancellationToken cancellationToken = default
        )
        {
            //
            try
            {
                //
                // Validate ...
                if (!ModelState.IsValid ||
                    !id.IsValidIntId())
                {
                    XException.InvalidArgs.Throw();
                }

                //
                var result = await provider.GetResource(
                    id: id,
                    cancellationToken: cancellationToken
                );

                //
                return Ok(result.ToDynamicObject());
            }
            catch (Exception ex)
            {
                //
                var result = GetExceptionActionResult(ex);
                return result;
            }
        }

        /// <summary>
        /// Add Category Item for Specified Language ...
        /// </summary>
        /// <param name="item"></param>
        /// <param name="language"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        [HttpPost("Resources")]
        public virtual async Task<ActionResult<XSubCategoryResourceDto>> Add(
            [FromBody] XSubCategoryDto item,
            [FromQuery] string language = null,
            CancellationToken cancellationToken = default
        )
        {
            //
            try
            {
                //
                // Validate ...
                if (!ModelState.IsValid)
                {
                    XException.InvalidArgs.Throw();
                }
                await ValidationProvider
                    .GroupValidationBuilder()
                    .AddNotNull(item)
                    .AddNotEmpty(language)
                    .AddNotEmpty(item.Title)
                    .AddNotEmpty(item.Description)
                    .ValidateGroupAsync();

                //
                // Reading Requirements ...
                var userInfo = await GetUserInfo();
                var connectionId = GetConnectionId();

                //
                var result = await provider.Add(
                    item: item,
                    language: language,
                    userInfo: userInfo,
                    connectionId: connectionId,
                    cancellationToken: cancellationToken
                );

                //
                return Ok(result.ToDynamicObject());
            }
            catch (Exception ex)
            {
                //
                var result = GetExceptionActionResult(ex);
                return result;
            }
        }

        /// <summary>
        /// Add Item by it's Locales and Reference ...
        /// </summary>
        /// <param name="item"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        [HttpPost("Resources/AddResource")]
        public virtual async Task<ActionResult<XSubCategoryResourceDto>> AddResource(
            [FromBody] XSubCategoryResourceDto item,
            CancellationToken cancellationToken = default
        )
        {
            //
            try
            {
                //
                // Validate ...
                if (!ModelState.IsValid)
                {
                    XException.InvalidArgs.Throw();
                }
                await ValidationProvider
                    .GroupValidationBuilder()
                    .AddNotNull(item)
                    .AddNotNull(item.Titles)
                    .AddNotZeroChilds(item.Titles.Locales)
                    .ValidateGroupAsync();

                //
                // Reading Requirements ...
                var userInfo = await GetUserInfo();
                var connectionId = GetConnectionId();

                //
                var result = await provider.AddResource(
                    item: item,
                    userInfo: userInfo,
                    connectionId: connectionId,
                    cancellationToken: cancellationToken
                );

                //
                return Ok(result.ToDynamicObject());
            }
            catch (Exception ex)
            {
                //
                var result = GetExceptionActionResult(ex);
                return result;
            }
        }

        /// <summary>
        /// Remove Item for Specified Language ...
        /// </summary>
        /// <param name="id"></param>
        /// <param name="language">if null, Remove All</param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        [HttpDelete("Resources/{id}")]
        public virtual async Task<ActionResult<XSubCategoryResourceDto>> Remove(
            [FromRoute] int id,
            [FromQuery] string language = null,
            CancellationToken cancellationToken = default
        )
        {
            //
            try
            {
                //
                // Validate ...
                if (!ModelState.IsValid ||
                    !id.IsValidIntId())
                {
                    XException.InvalidArgs.Throw();
                }

                //
                // Reading Requirements ...
                var userInfo = await GetUserInfo();
                var connectionId = GetConnectionId();

                //
                var result = await provider.Remove(
                    id: id,
                    language: language,
                    userInfo: userInfo,
                    connectionId: connectionId,
                    cancellationToken: cancellationToken
                );

                //
                return Ok(result.ToDynamicObject());
            }
            catch (Exception ex)
            {
                //
                var result = GetExceptionActionResult(ex);
                return result;
            }
        }

        /// <summary>
        /// Update a Category Item for Specified Language ...
        /// </summary>
        /// <param name="id"></param>
        /// <param name="item"></param>
        /// <param name="language"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        [HttpPut("Resources/{id}")]
        public virtual async Task<ActionResult<XSubCategoryResourceDto>> Update(
            [FromRoute] int id,
            [FromBody] XSubCategoryDto item,
            [FromQuery] string language = null,
            CancellationToken cancellationToken = default
        )
        {
            //
            try
            {
                //
                // Validate ...
                if (!ModelState.IsValid ||
                    !id.IsValidIntId())
                {
                    XException.InvalidArgs.Throw();
                }
                await ValidationProvider
                    .GroupValidationBuilder()
                    .AddNotNull(item)
                    .AddNotEmpty(language)
                    .AddNotEmpty(item.Title)
                    .AddNotEmpty(item.Description)
                    .ValidateGroupAsync();

                //
                // Reading Requirements ...
                var userInfo = await GetUserInfo();
                var connectionId = GetConnectionId();

                //
                var result = await provider.Update(
                    id: id,
                    item: item,
                    language: language,
                    userInfo: userInfo,
                    connectionId: connectionId,
                    cancellationToken: cancellationToken
                );

                //
                return Ok(result.ToDynamicObject());
            }
            catch (Exception ex)
            {
                //
                var result = GetExceptionActionResult(ex);
                return result;
            }
        }

        /// <summary>
        /// Refresh a Resource ...
        /// </summary>
        /// <param name="resource"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        [HttpPost("Resources/Refresh")]
        public virtual async Task<ActionResult<XSubCategoryResourceDto>> Refresh(
            [FromBody] XSubCategoryResourceDto resource,
            CancellationToken cancellationToken = default
        )
        {
            //
            try
            {
                //
                // Validate ...
                if (!ModelState.IsValid)
                {
                    XException.InvalidArgs.Throw();
                }
                await ValidationProvider
                    .GroupValidationBuilder()
                    .AddNotNull(resource)
                    .AddNotNull(resource.Item)
                    .ValidateGroupAsync();

                //
                // Reading Requirements ...
                var userInfo = await GetUserInfo();
                var connectionId = GetConnectionId();

                //
                var result = await provider.Refresh(
                    resource: resource,
                    userInfo: userInfo,
                    connectionId: connectionId,
                    cancellationToken: cancellationToken
                );

                //
                return Ok(result.ToDynamicObject());
            }
            catch (Exception ex)
            {
                //
                var result = GetExceptionActionResult(ex);
                return result;
            }
        }

        /// <summary>
        /// Get All Resources ...
        /// </summary>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        [HttpGet("Resources/All")]
        public virtual async Task<ActionResult<IEnumerable<XSubCategoryResourceDto>>> GetAllResources(
            CancellationToken cancellationToken = default
        )
        {
            //
            try
            {
                //
                // Validate ...
                if (!ModelState.IsValid)
                {
                    XException.InvalidArgs.Throw();
                }

                //
                var result = await provider.GetAllResources(
                    cancellationToken: cancellationToken
                );

                //
                return Ok(result.ToDynamicObject());
            }
            catch (Exception ex)
            {
                //
                var result = GetExceptionActionResult(ex);
                return result;
            }
        }

        /// <summary>
        /// Find One Resource ...
        /// </summary>
        /// <param name="query"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        [HttpGet("Resources/Find/One")]
        public virtual async Task<ActionResult<XSubCategoryResourceDto>> FindOneResource(
            [FromQuery] string query,
            CancellationToken cancellationToken = default
        )
        {
            //
            try
            {
                //
                // Validate ...
                if (!ModelState.IsValid)
                {
                    XException.InvalidArgs.Throw();
                }
                await ValidationProvider
                    .GroupValidationBuilder()
                    .AddNotEmpty(query)
                    .ValidateGroupAsync();

                //
                var result = await provider.FindOneResource(
                    cancellationToken: cancellationToken,
                    predicate: x => x.PropValuesContains(query)
                );

                //
                return Ok(result.ToDynamicObject());
            }
            catch (Exception ex)
            {
                //
                var result = GetExceptionActionResult(ex);
                return result;
            }
        }

        /// <summary>
        /// Find Many Resource ...
        /// </summary>
        /// <param name="query"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        [HttpGet("Resources/Find/Many")]
        public virtual async Task<ActionResult<IEnumerable<XSubCategoryResourceDto>>> FindManyResource(
            [FromQuery] string query,
            CancellationToken cancellationToken = default
        )
        {
            //
            try
            {
                //
                // Validate ...
                if (!ModelState.IsValid)
                {
                    XException.InvalidArgs.Throw();
                }
                await ValidationProvider
                    .GroupValidationBuilder()
                    .AddNotEmpty(query)
                    .ValidateGroupAsync();

                //
                var result = await provider.FindManyResource(
                    cancellationToken: cancellationToken,
                    predicate: x => x.PropValuesContains(query),
                    orderBuilder: x => x.OrderBy(y => y.Item.Id)
                );

                //
                return Ok(result.ToDynamicObject());
            }
            catch (Exception ex)
            {
                //
                var result = GetExceptionActionResult(ex);
                return result;
            }
        }

        /// <summary>
        /// Retrieve Resources by Query Pattern ...
        /// </summary>
        /// <param name="query"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        [HttpGet("Resources/Query")]
        public virtual async Task<ActionResult<XQueryResult<XSubCategoryResourceDto>>> QueryResources(
            [FromQuery] XQuery query = null,
            CancellationToken cancellationToken = default
        )
        {
            //
            try
            {
                //
                // Validate ...
                if (!ModelState.IsValid)
                {
                    XException.InvalidArgs.Throw();
                }
                await ValidationProvider
                    .GroupValidationBuilder()
                    .AddNotNull(query)
                    .ValidateGroupAsync();

                //
                var result = await provider.QueryResources(
                    query: query,
                    predicate: null,
                    cancellationToken: cancellationToken,
                    orderBuilder: x => x.OrderBy(y => y.Item.Id)
                );

                //
                return Ok(result.ToDynamicObject());
            }
            catch (Exception ex)
            {
                //
                var result = GetExceptionActionResult(ex);
                return result;
            }
        }
        #endregion
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xCategoryService\Controllers\XSubCategoryRepositoryControllerBase.cs

using System;
using System.Linq;
using Microsoft.EntityFrameworkCore.Query;
using Microsoft.Extensions.Logging;
using xCategoryService.Interfaces.Entities;
using xCategoryService.Models.Entities;
using xCommons.Configurations;
using xCommons.Providers;
using xDataService.Controllers;
using xDataService.Interfaces;

namespace xCategoryService.Controllers
{
    public abstract class XSubCategoryRepositoryControllerBase : XBaseRepositoryController<XSubCategory, int>, IXBaseRepositoryController<XSubCategory, int>
    {
        protected XSubCategoryRepositoryControllerBase(
            ILogger<XSubCategoryRepositoryControllerBase> logger,
            XAppConfiguration appConfiguration,
            XValidationProvider validationProvider,
            IXSubCategoryRepository repository,
            Func<IQueryable<XSubCategory>, IOrderedQueryable<XSubCategory>> defaultOrderBuilder = null,
            Func<IQueryable<XSubCategory>, IIncludableQueryable<XSubCategory, object>> defaultIncludeBuilder = null
        ) : base(
            logger,
            appConfiguration,
            validationProvider,
            repository,
            defaultOrderBuilder,
            defaultIncludeBuilder
        )
        { }
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xCategoryService\Controllers\XSubCategoryRepositoryProviderControllerBase.cs

using System;
using System.Linq;
using Microsoft.EntityFrameworkCore.Query;
using Microsoft.Extensions.Logging;
using xCategoryService.Interfaces.Entities;
using xCategoryService.Models.Entities;
using xCategoryService.Providers.Entities;
using xCommons.Configurations;
using xCommons.Providers;
using xIdentityService.Interfaces;
using xPushService.Controllers;
using xPushService.Interfaces;

namespace xCategoryService.Controllers
{
    public abstract class XSubCategoryRepositoryProviderControllerBase : XBaseRepositoryProviderController<XSubCategory, int, XSubCategoryEntityHub>, IXBaseRepositoryProviderController<XSubCategory, int, XSubCategoryEntityHub>
    {
        protected XSubCategoryRepositoryProviderControllerBase(
            ILogger<XSubCategoryRepositoryProviderControllerBase> logger,
            XAppConfiguration appConfiguration,
            IXIdentityProvider identityProvider,
            XValidationProvider validationProvider,
            IXSubCategoryRepositoryProvider provider,
            Func<IQueryable<XSubCategory>, IOrderedQueryable<XSubCategory>> defaultOrderBuilder = null,
            Func<IQueryable<XSubCategory>, IIncludableQueryable<XSubCategory, object>> defaultIncludeBuilder = null
        ) : base(
            logger,
            appConfiguration,
            identityProvider,
            validationProvider,
            provider,
            defaultOrderBuilder,
            defaultIncludeBuilder
        )
        { }
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xCategoryService\Controllers\XSubCategoryServiceControllerBase.cs

using System;
using System.Linq;
using Microsoft.EntityFrameworkCore.Query;
using Microsoft.Extensions.Logging;
using xCategoryService.Interfaces.Dtos;
using xCategoryService.Models.Dtos;
using xCategoryService.Models.Entities;
using xCommons.Configurations;
using xCommons.Providers;
using xDataService.Controllers;
using xDataService.Interfaces;

namespace xCategoryService.Controllers
{
    public abstract class XSubCategoryServiceControllerBase : XBaseServiceController<XSubCategory, XSubCategoryDto, int>, IXBaseServiceController<XSubCategory, XSubCategoryDto, int>
    {
        protected XSubCategoryServiceControllerBase(
            ILogger<XSubCategoryServiceControllerBase> logger,
            XAppConfiguration appConfiguration,
            XValidationProvider validationProvider,
            IXSubCategoryRepositoryService repositoryService,
            Func<IQueryable<XSubCategory>, IOrderedQueryable<XSubCategory>> defaultOrderBuilder = null,
            Func<IQueryable<XSubCategory>, IIncludableQueryable<XSubCategory, object>> defaultIncludeBuilder = null
        ) : base(
            logger,
            appConfiguration,
            validationProvider,
            repositoryService,
            defaultOrderBuilder,
            defaultIncludeBuilder
        )
        { }
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xCategoryService\Controllers\XSubCategoryServiceProviderControllerBase.cs

using System;
using System.Linq;
using Microsoft.EntityFrameworkCore.Query;
using Microsoft.Extensions.Logging;
using xCategoryService.Interfaces.Dtos;
using xCategoryService.Models.Dtos;
using xCategoryService.Models.Entities;
using xCategoryService.Providers.Dtos;
using xCommons.Configurations;
using xCommons.Providers;
using xIdentityService.Interfaces;
using xPushService.Controllers;
using xPushService.Interfaces;

namespace xCategoryService.Controllers
{
    public abstract class XSubCategoryServiceProviderControllerBase : XBaseServiceProviderController<XSubCategory, XSubCategoryDto, int, XSubCategoryDtoHub>, IXBaseServiceProviderController<XSubCategory, XSubCategoryDto, int, XSubCategoryDtoHub>
    {
        protected XSubCategoryServiceProviderControllerBase(
            ILogger<XSubCategoryServiceProviderControllerBase> logger,
            XAppConfiguration appConfiguration,
            IXIdentityProvider identityProvider,
            XValidationProvider validationProvider,
            IXSubCategoryServiceProvider provider,
            Func<IQueryable<XSubCategory>, IOrderedQueryable<XSubCategory>> defaultOrderBuilder = null,
            Func<IQueryable<XSubCategory>, IIncludableQueryable<XSubCategory, object>> defaultIncludeBuilder = null
        ) : base(
            logger,
            appConfiguration,
            identityProvider,
            validationProvider,
            provider,
            defaultOrderBuilder,
            defaultIncludeBuilder
        )
        { }
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xCategoryService\DI\XDIHelperExtension.cs

using System;
using System.Linq;
using Microsoft.AspNetCore.Builder;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using xCategoryService.Configurations;
using xCategoryService.Constants;
using xCategoryService.Helpers;
using xCategoryService.Interfaces;
using xCategoryService.Interfaces.Dtos;
using xCategoryService.Interfaces.Entities;
using xCategoryService.Providers;
using xCategoryService.Providers.Dtos;
using xCategoryService.Providers.Entities;
using xCommons.Extensions;
using xCommons.Helpers;
using xDataService.Constants;
using xDataService.Db;
using xDataService.DI;
using xDataService.Models;
using xExceptions.Constants;
using xPushService.DI;
using xPushService.Helpers;

namespace xCategoryService.DI
{
    public static class XDIHelperExtension
    {
        /// <summary>
        /// Extract Service Configurations ...
        /// </summary>
        /// <param name="source"></param>
        /// <returns></returns>
        public static XCategoryServiceConfiguration GetXCategoryServiceConfigurations(
            this IConfiguration source
        )
        {
            //
            XCategoryServiceConfiguration result = null;

            //
            var section = source.GetSection(Constants.ConfigurationNodeNames.CATEGORY_SERVICE_NODE);
            var sectionJson = source.GetSectionAsJson(Constants.ConfigurationNodeNames.CATEGORY_SERVICE_NODE);
            if (!section.IsNull())
            {
                result = sectionJson.FromJSON<XCategoryServiceConfiguration>();
            }

            //
            return result;
        }

        /// <summary>
        /// Register Service Configuration ... 
        /// </summary>
        /// <param name="source"></param>
        /// <param name="configuration"></param>
        public static void AddXCategoryServiceConfiguration(
            this IServiceCollection source,
            IConfiguration configuration
        )
        {
            //
            // Extract Configuration Class ...
            var config = configuration.GetXCategoryServiceConfigurations();

            //
            // Register Class as Service ...
            source.AddXCategoryServiceConfiguration(config);
        }

        /// <summary>
        /// Register Service Configuration ... 
        /// </summary>
        /// <param name="source"></param>
        /// <param name="configuration"></param>
        public static void AddXCategoryServiceConfiguration(
            this IServiceCollection source,
            XCategoryServiceConfiguration configuration
        )
        {
            //
            // Normalize Configuration Class ...
            if (configuration.IsNull())
            {
                configuration = new XCategoryServiceConfiguration();
            }

            //
            // Register ...
            source.AddSingleton(configuration);
        }

        /// <summary>
        /// Register Service ...
        /// </summary>
        /// <param name="services"></param>
        /// <param name="repositoryType"></param>
        /// <param name="lifeTime"></param>
        public static void AddXCategoryService(
            this IServiceCollection services,
            XRepositoryType repositoryType,
            ServiceLifetime lifeTime = ServiceLifetime.Scoped
        )
        {
            AddCategoryService(
                contextType: null,
                services: services,
                lifeTime: lifeTime,
                repositoryType: repositoryType
            );
        }

        /// <summary>
        /// Register Service ...
        /// </summary>
        /// <typeparam name="TContext"></typeparam>
        /// <param name="services"></param>
        /// <param name="repositoryType"></param>
        /// <param name="lifeTime"></param>
        public static void AddXCategoryService<TContext>(
            this IServiceCollection services,
            XRepositoryType repositoryType,
            ServiceLifetime lifeTime = ServiceLifetime.Scoped
        )
        where TContext : XDbContext
        {
            AddCategoryService(
                services: services,
                lifeTime: lifeTime,
                contextType: typeof(TContext),
                repositoryType: repositoryType
            );
        }

        /// <summary>
        /// Use XSubCategoryService Middleware ... 
        /// </summary>
        /// <param name="app"></param>
        /// <param name="isDevelopmentEnvironment"></param>
        public static void UseXCategoryService(
            this IApplicationBuilder app,
            bool isDevelopmentEnvironment = false
        )
        {
            //
            #region Using Hubs ...
            //
            var pushHelper = new XPushServiceHelper();

            //
            // Category ...
            pushHelper.AddHub<XCategoryDtoHub>(XCategoryServiceConstants.XCategoryDtoHub);
            pushHelper.AddHub<XCategoryEntityHub>(XCategoryServiceConstants.XCategoryEntityHub);

            //
            // SubCategory ...
            pushHelper.AddHub<XSubCategoryDtoHub>(XCategoryServiceConstants.XSubCategoryDtoHub);
            pushHelper.AddHub<XSubCategoryEntityHub>(XCategoryServiceConstants.XSubCategoryEntityHub);

            //
            app.UseXPushService(pushHelper);
            #endregion

            //
            // Using XCategory Repository Descriptor ...
            if (!categoryDescriptor.IsNull())
            {
                //
                app.UseXRepository(
                    descriptor: categoryDescriptor,
                    isDevelopmentEnvironment: isDevelopmentEnvironment
                );
            }

            //
            // Using XSubCategory Repository Descriptor ...
            if (!subCategoryDescriptor.IsNull())
            {
                //
                app.UseXRepository(
                    descriptor: subCategoryDescriptor,
                    isDevelopmentEnvironment: isDevelopmentEnvironment
                );
            }

            //
            // Create an Scope for Services Acces ...
            // Handle Seeding Category/SubCategory Resources ...
            using (var scope = app.ApplicationServices.CreateScope())
            {
                //
                // Retrieve Configuratuions ...
                var categoryProvider = scope.ServiceProvider.GetService<IXCategoryProvider>();
                var subCategoryProvider = scope.ServiceProvider.GetService<IXSubCategoryProvider>();
                var configuration = scope.ServiceProvider.GetService<XCategoryServiceConfiguration>();
                if (!configuration.IsNullOrDefault() &&
                    !categoryProvider.IsNullOrDefault() &&
                    !subCategoryDescriptor.IsNullOrDefault()
                )
                {
                    //
                    // Logging ...
                    Log("Start Seeding ...");

                    //
                    // Count Data in Category ...
                    var hasCategory = categoryProvider.Count().GetAwaiter().GetResult() > 0;
                    var hasSubCategory = subCategoryProvider.Count().GetAwaiter().GetResult() > 0;

                    //
                    // Seed Category Resources ...
                    var canSeed =
                        !hasCategory &&
                        configuration.Categories.HasChild();
                    if (canSeed)
                    {
                        //
                        // Loop through Provided items ...
                        foreach (var cat in configuration.Categories)
                        {
                            //
                            try
                            {
                                //
                                Log($"Start Seeding Category: {cat.Titles.Locales.ToArray()[0].Value} ...");

                                //
                                categoryProvider.Refresh(
                                    resource: cat,
                                    userInfo: null,
                                    connectionId: null,
                                    cancellationToken: default
                                )
                                .GetAwaiter()
                                .GetResult();

                                //
                                Log($"Seeding Category: {cat.Titles.Locales.ToArray()[0].Value} Finished Successfully ...");
                            }
                            catch (Exception ex)
                            {
                                Log($"Seeding Category: {cat.Titles.Locales.ToArray()[0].Value} Failed due: {ex.Message} ...");
                            }
                        }
                    }

                    //
                    // Seed SubCategory Resources ...
                    canSeed =
                        !hasSubCategory &&
                        configuration.SubCategories.HasChild();
                    if (canSeed)
                    {
                        //
                        // Loop through Provided items ...
                        foreach (var subcat in configuration.SubCategories)
                        {
                            //
                            try
                            {
                                //
                                Log($"Start Seeding SubCategory: {subcat.Titles.Locales.ToArray()[0].Value} ...");

                                //
                                subCategoryProvider.Refresh(
                                    userInfo: null,
                                    resource: subcat,
                                    connectionId: null,
                                    cancellationToken: default
                                )
                                .GetAwaiter()
                                .GetResult();

                                //
                                Log($"Seeding SubCategory: {subcat.Titles.Locales.ToArray()[0].Value} Finished Successfully ...");
                            }
                            catch (Exception ex)
                            {
                                Log($"Seeding SubCategory: {subcat.Titles.Locales.ToArray()[0].Value} Failed due: {ex.Message} ...");
                            }
                        }
                    }

                    //
                    Log("Finish Seeding ...");
                }
            }
        }

        //
        #region Private ...
        private static XRepositoryDescriptor categoryDescriptor = null;
        private static XRepositoryDescriptor subCategoryDescriptor = null;

        /// <summary>
        /// a LogTag for Service ...
        /// </summary>
        private static string XLogTag = XCategoryServiceConstants.XCategoryServiceDILogTag;

        /// <summary>
        /// print a log in Console ...
        /// </summary>
        /// <param name="message"></param>
        private static void Log(string message)
        {
            Console.WriteLine($"{XLogTag} => {message}");
        }

        /// <summary>
        /// Register Service ...
        /// </summary>
        /// <param name="services"></param>
        /// <param name="repositoryType"></param>
        /// <param name="contextType"></param>
        /// <param name="lifeTime"></param>
        private static void AddCategoryService(
            IServiceCollection services,
            XRepositoryType repositoryType,
            Type contextType = null,
            ServiceLifetime lifeTime = ServiceLifetime.Scoped
        )
        {
            //
            var exception = XException.InvalidArgs.ToException(); ;

            //
            // Services ...
            var isServicesExists = !services.IsNull();
            if (!isServicesExists)
            {
                //
                Log("Service Registration failed, services not provided ...");
                throw exception;
            }

            //
            // Lifetime ...
            var isLifetimeExists = !lifeTime.IsNull();
            if (!isLifetimeExists)
            {
                //
                Log("Service Registration failed, lifetime not provided ...");
                throw exception;
            }

            //
            // Validate Repository Type ...
            var isRepositoryTypeValid =
                (repositoryType == XRepositoryType.EF &&
                !contextType.IsNull()) ||
                ((repositoryType == XRepositoryType.Mongo ||
                    repositoryType == XRepositoryType.InMemory) &&
                contextType.IsNull());
            if (!isRepositoryTypeValid)
            {
                //
                Log("Service Registration failed, Invalid Repository Type and Context Type ...");
                throw exception;
            }

            //
            // Maske Instance of Repository Descriptor 
            // Based on Provided Type ...
            switch (repositoryType)
            {
                //
                case XRepositoryType.EF:
                    //
                    // Category ...
                    categoryDescriptor = typeof(XCategoryServiceHelper)
                        .InvokeGenericMethod<XRepositoryDescriptor>(
                            args: null,
                            runtimeType: contextType,
                            methodName: XCategoryServiceConstants.GetXCategoryEFRepositoryDescriptor
                    );

                    //
                    // SubCategory ...
                    subCategoryDescriptor = typeof(XCategoryServiceHelper)
                        .InvokeGenericMethod<XRepositoryDescriptor>(
                            args: null,
                            runtimeType: contextType,
                            methodName: XCategoryServiceConstants.GetXSubCategoryEFRepositoryDescriptor
                    );
                    break;

                //
                case XRepositoryType.Mongo:
                    //
                    // Category ...
                    categoryDescriptor = XCategoryServiceHelper.GetXCategoryMongoRepositoryDescriptor();

                    //
                    // SubCategory ...
                    subCategoryDescriptor = XCategoryServiceHelper.GetXSubCategoryMongoRepositoryDescriptor();
                    break;

                //
                case XRepositoryType.InMemory:
                    //
                    // Category ...
                    categoryDescriptor = XCategoryServiceHelper.GetXCategoryInMemoryRepositoryDescriptor();

                    //
                    // SubCategory ...
                    subCategoryDescriptor = XCategoryServiceHelper.GetXSubCategoryInMemoryRepositoryDescriptor();
                    break;
            }

            //
            // Register Category Repository Descriptor ...
            if (!categoryDescriptor.IsNull())
            {
                //
                services.AddXRepository(
                    lifeTime: lifeTime,
                    descriptor: categoryDescriptor
                );
            }

            //
            // Register SubCategory Repository Descriptor ...
            if (!subCategoryDescriptor.IsNull())
            {
                //
                services.AddXRepository(
                    lifeTime: lifeTime,
                    descriptor: subCategoryDescriptor
                );
            }

            //
            #region Register Services ...
            //
            #region Category ...
            //
            // Models ...
            services.Add(
                new ServiceDescriptor(typeof(IXCategoryServiceProvider), typeof(XCategoryServiceProvider), lifeTime)
            );
            services.Add(
                new ServiceDescriptor(typeof(IXCategoryRepositoryService), typeof(XCategoryRepositoryService), lifeTime)
            );
            services.Add(
                new ServiceDescriptor(typeof(IXCategoryRepositoryProvider), typeof(XCategoryRepositoryProvider), lifeTime)
            );

            //
            // Resource Providers ...
            services.Add(
                new ServiceDescriptor(typeof(IXCategoryTitleResourceProvider), typeof(XCategoryTitleResourceProvider), lifeTime)
            );
            services.Add(
                new ServiceDescriptor(typeof(IXCategoryDescriptionResourceProvider), typeof(XCategoryDescriptionResourceProvider), lifeTime)
            );

            //
            // Reference Providers ...
            services.Add(
                new ServiceDescriptor(typeof(IXCategorySubCategoryReferenceProvider), typeof(XCategorySubCategoryReferenceProvider), lifeTime)
            );

            //
            // Provider ...
            services.Add(
                new ServiceDescriptor(typeof(IXCategoryProvider), typeof(XCategoryProvider), lifeTime)
            );
            #endregion

            //
            #region SubCategory ...
            //
            // Models ...
            services.Add(
                new ServiceDescriptor(typeof(IXSubCategoryServiceProvider), typeof(XSubCategoryServiceProvider), lifeTime)
            );
            services.Add(
                new ServiceDescriptor(typeof(IXSubCategoryRepositoryService), typeof(XSubCategoryRepositoryService), lifeTime)
            );
            services.Add(
                new ServiceDescriptor(typeof(IXSubCategoryRepositoryProvider), typeof(XSubCategoryRepositoryProvider), lifeTime)
            );

            //
            // Resource Providers ...
            services.Add(
                new ServiceDescriptor(typeof(IXSubCategoryTitleResourceProvider), typeof(XSubCategoryTitleResourceProvider), lifeTime)
            );
            services.Add(
                new ServiceDescriptor(typeof(IXSubCategoryDescriptionResourceProvider), typeof(XSubCategoryDescriptionResourceProvider), lifeTime)
            );

            //
            // Provider ...
            services.Add(
                new ServiceDescriptor(typeof(IXSubCategoryProvider), typeof(XSubCategoryProvider), lifeTime)
            );
            #endregion
            #endregion

            //
            // Register Service Main Provider ...
            services.Add(
                new ServiceDescriptor(typeof(IXCategoryService), typeof(XCategoryService), lifeTime)
            );

            //
            Log("Service Regitration Succeed ...");
        }
        #endregion        
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xCategoryService\Extensions\XCategoryResourceExtensions.cs

using System.Linq;
using xCategoryService.Models.Dtos;
using xCategoryService.Providers.Dtos;
using xCommons.Extensions;

namespace xCategoryService.Extensions
{
    /// <summary>
    /// Extensions Method Related to XCategoryResourceDto ...
    /// </summary>
    public static class XCategoryResourceExtensions
    {
        /// <summary>
        /// Extract Available Languages ...
        /// </summary>
        /// <param name="source"></param>
        /// <returns></returns>
        public static string[] ExtractLanguages(
            this XCategoryResourceDto source
        )
        {
            //
            var result = new string[] { };

            //
            // Validate ...
            if (!source.IsNullOrDefault())
            {
                return result;
            }

            //
            result =
                source.Titles.Locales.Select(x => x.Language)
                .Union(source.Descriptions.Locales.Select(x => x.Language))
                .Distinct()
                .ToArray();

            //
            return result;
        }

        /// <summary>
        /// Check Has Locale or not ...
        /// </summary>
        /// <param name="source"></param>
        /// <param name="language"></param>
        /// <returns></returns>
        public static bool HasLocale(
            this XCategoryResourceDto source,
            string language
        )
        {
            //
            var result =
                !language.IsNullOrEmpty() &&
                !source.IsNullOrDefault() &&
                source.Titles.Locales
                    .Any(l => l.Language
                        .Equals(
                            language,
                            System.StringComparison.InvariantCultureIgnoreCase));

            //
            return result;
        }

        /// <summary>
        /// Get Item Translation ...
        /// </summary>
        /// <param name="source"></param>
        /// <param name="language"></param>
        /// <returns></returns>
        public static XCategoryDto GetTranslate(
            this XCategoryResourceDto source,
            string language
        )
        {
            //
            XCategoryDto result = null;

            //
            var isValid = source
                .HasLocale(language);
            if (!isValid)
            {
                return result;
            }

            //
            var titleLocale = source.Titles.Locales
                .FirstOrDefault(l => l.Language
                    .Equals(
                        language,
                        System.StringComparison.InvariantCultureIgnoreCase));
            var descriptionLocale = source.Descriptions.Locales
                .FirstOrDefault(l => l.Language
                    .Equals(
                        language,
                        System.StringComparison.InvariantCultureIgnoreCase));

            //
            isValid = !titleLocale.IsNullOrDefault();
            if (!isValid)
            {
                return result;
            }

            //
            result = source.Item;
            result.Title = titleLocale.Value;
            result.Description =
                descriptionLocale.IsNullOrDefault()
                ? string.Empty
                : descriptionLocale.Value;

            //
            return result;
        }
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xCategoryService\Extensions\XModelExtensions.cs

using System.Collections.Generic;
using System.Linq;
using xCategoryService.Models.Dtos;
using xCategoryService.Models.Entities;
using xCommons.Extensions;
using xDataService.Extensions;
using xDataService.Models;

namespace xCategoryService.Extensions
{
    public static class XModelExtensions
    {
        /// <summary>
        /// Extract References of a Model ...
        /// </summary>
        /// <param name="source"></param>
        /// <returns></returns>
        public static IList<XReference<string>> GetReferences(
            this XCategory source
        )
        {
            //
            var result = new List<XReference<string>>();

            //
            if (
                !source.IsNullOrDefault() &&
                !source.References.IsNullOrEmpty()
            )
            {
                //  
                result = source.References
                    .ParseXReferenceList<string>()
                    .ToList();
            }

            //
            return result;
        }

        /// <summary>
        /// Extract References of a Model ...
        /// </summary>
        /// <param name="source"></param>
        /// <returns></returns>
        public static IList<XReference<string>> GetReferences(
            this XCategoryDto source
        )
        {
            //
            var result = new List<XReference<string>>();

            //
            if (
                !source.IsNullOrDefault() &&
                !source.References.IsNullOrEmpty()
            )
            {
                //  
                result = source.References
                    .ParseXReferenceList<string>()
                    .ToList();
            }

            //
            return result;
        }

        /// <summary>
        /// Update a Model's References by Providing References List ...
        /// </summary>
        /// <param name="source"></param>
        /// <param name="references"></param>
        /// <param name="forceClean"></param>
        /// <returns></returns>
        public static XCategory UpdateReferences(
            this XCategory source,
            IList<XReference<string>> references,
            bool forceClean = true
        )
        {
            //
            XCategory result = source;

            //
            if (!source.IsNullOrDefault())
            {
                //
                result = source;
                
                //
                if (forceClean)
                {
                    result.References = string.Empty;
                }

                //
                if (!references.IsNull() && 
                    references.HasChild())
                {
                    result.References = references.ToXReferenceString();
                }
            }

            //
            return result;
        }

        /// <summary>
        /// Update a Model's References by Providing References List ...
        /// </summary>
        /// <param name="source"></param>
        /// <param name="references"></param>
        /// <param name="forceClean"></param>
        /// <returns></returns>
        public static XCategoryDto UpdateReferences(
            this XCategoryDto source,
            IList<XReference<string>> references,
            bool forceClean = true
        )
        {
            //
            XCategoryDto result = source;

            //
            if (!source.IsNullOrDefault())
            {
                //
                result = source;
                
                //
                if (forceClean)
                {
                    result.References = string.Empty;
                }

                //
                if (!references.IsNull() && 
                    references.HasChild())
                {
                    result.References = references.ToXReferenceString();
                }
            }

            //
            return result;
        }
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xCategoryService\Extensions\XSubCategoryResourceExtensions.cs

using System.Linq;
using xCategoryService.Models.Dtos;
using xCategoryService.Providers.Dtos;
using xCommons.Extensions;

namespace xCategoryService.Extensions
{
    /// <summary>
    /// Extensions Method Related to XSubCategoryResourceDto ...
    /// </summary>
    public static class XSubCategoryResourceExtensions
    {
        /// <summary>
        /// Extract Available Languages ...
        /// </summary>
        /// <param name="source"></param>
        /// <returns></returns>
        public static string[] ExtractLanguages(
            this XSubCategoryResourceDto source
        )
        {
            //
            var result = new string[] { };

            //
            // Validate ...
            if (!source.IsNullOrDefault())
            {
                return result;
            }

            //
            result =
                source.Titles.Locales.Select(x => x.Language)
                .Union(source.Descriptions.Locales.Select(x => x.Language))
                .Distinct()
                .ToArray();

            //
            return result;
        }

        /// <summary>
        /// Check Has Locale or not ...
        /// </summary>
        /// <param name="source"></param>
        /// <param name="language"></param>
        /// <returns></returns>
        public static bool HasLocale(
            this XSubCategoryResourceDto source,
            string language
        )
        {
            //
            var result =
                !language.IsNullOrEmpty() &&
                !source.IsNullOrDefault() &&
                source.Titles.Locales
                    .Any(l => l.Language
                        .Equals(
                            language,
                            System.StringComparison.InvariantCultureIgnoreCase));

            //
            return result;
        }

        /// <summary>
        /// Get Item Translation ...
        /// </summary>
        /// <param name="source"></param>
        /// <param name="language"></param>
        /// <returns></returns>
        public static XSubCategoryDto GetTranslate(
            this XSubCategoryResourceDto source,
            string language
        )
        {
            //
            XSubCategoryDto result = null;

            //
            var isValid = source
                .HasLocale(language);
            if (!isValid)
            {
                return result;
            }

            //
            var titleLocale = source.Titles.Locales
                .FirstOrDefault(l => l.Language
                    .Equals(
                        language,
                        System.StringComparison.InvariantCultureIgnoreCase));
            var descriptionLocale = source.Descriptions.Locales
                .FirstOrDefault(l => l.Language
                    .Equals(
                        language,
                        System.StringComparison.InvariantCultureIgnoreCase));

            //
            isValid = !titleLocale.IsNullOrDefault();
            if (!isValid)
            {
                return result;
            }

            //
            result = source.Item;
            result.Title = titleLocale.Value;
            result.Description =
                descriptionLocale.IsNullOrDefault()
                ? string.Empty
                : descriptionLocale.Value;

            //
            return result;
        }
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xCategoryService\Helpers\XCategoryServiceHelper.cs

using GraphQL.Types;
using xCategoryService.Interfaces;
using xCategoryService.Interfaces.Entities;
using xCategoryService.Models.Entities;
using xCategoryService.Providers.Entities;
using xCategoryService.Providers.GraphQL;
using xDataService.Db;
using xDataService.Models;
using xDataService.Providers;

namespace xCategoryService.Helpers
{
    public static class XCategoryServiceHelper
    {
        //
        #region EF Repository Descriptor Provider(s) ...
        //
        #region Category
        public static XEFRepositoryDescriptor<
            XCategory,
            int,
            IXCategoryKeyGenerator,
            XCategoryKeyGenerator,
            IXCategoryRepositoryEvents,
            XCategoryRepositoryEvents,
            XCategoryGraphType,
            IntGraphType,
            XCategoryGraphQuery,
            IXCategoryGraphQLTypeHelper,
            XCategoryGraphQLTypeHelper,
            XCategoryGraphSchema,
            IXCategoryRepository,
            XCategoryEFRepository<TContext>,
            TContext
        > GetXCategoryEFRepositoryDescriptor<TContext>()
        where TContext : XDbContext
        {
            //
            var result = new XEFRepositoryDescriptor<
                XCategory,
                int,
                IXCategoryKeyGenerator,
                XCategoryKeyGenerator,
                IXCategoryRepositoryEvents,
                XCategoryRepositoryEvents,
                XCategoryGraphType,
                IntGraphType,
                XCategoryGraphQuery,
                IXCategoryGraphQLTypeHelper,
                XCategoryGraphQLTypeHelper,
                XCategoryGraphSchema,
                IXCategoryRepository,
                XCategoryEFRepository<TContext>,
                TContext
            >();

            //
            return result;
        }

        public static XEFRepositoryDescriptor<
            XCategory,
            int,
            IXCategoryKeyGenerator,
            XCategoryKeyGenerator,
            IXCategoryRepositoryEvents,
            XCategoryRepositoryEvents,
            XCategoryGraphType,
            IntGraphType,
            XCategoryGraphQuery,
            IXCategoryGraphQLTypeHelper,
            XCategoryGraphQLTypeHelper,
            XCategoryGraphSchema,
            IXCategoryRepository,
            XCategoryEFRepository<TContext>,
            TContext,
            IXCategorySeeder,
            TSeederImplementation
        > GetXCategoryEFRepositoryDescriptor<TContext, TSeederImplementation>()
        where TContext : XDbContext
        where TSeederImplementation : XBaseDbSeeder<XCategory, int>
        {
            //
            var result = new XEFRepositoryDescriptor<
                XCategory,
                int,
                IXCategoryKeyGenerator,
                XCategoryKeyGenerator,
                IXCategoryRepositoryEvents,
                XCategoryRepositoryEvents,
                XCategoryGraphType,
                IntGraphType,
                XCategoryGraphQuery,
                IXCategoryGraphQLTypeHelper,
                XCategoryGraphQLTypeHelper,
                XCategoryGraphSchema,
                IXCategoryRepository,
                XCategoryEFRepository<TContext>,
                TContext,
                IXCategorySeeder,
                TSeederImplementation
            >();

            //
            return result;
        }
        #endregion

        //
        #region SubCategory
        public static XEFRepositoryDescriptor<
            XSubCategory,
            int,
            IXSubCategoryKeyGenerator,
            XSubCategoryKeyGenerator,
            IXSubCategoryRepositoryEvents,
            XSubCategoryRepositoryEvents,
            XSubCategoryGraphType,
            IntGraphType,
            XSubCategoryGraphQuery,
            IXSubCategoryGraphQLTypeHelper,
            XSubCategoryGraphQLTypeHelper,
            XSubCategoryGraphSchema,
            IXSubCategoryRepository,
            XSubCategoryEFRepository<TContext>,
            TContext
        > GetXSubCategoryEFRepositoryDescriptor<TContext>()
        where TContext : XDbContext
        {
            //
            var result = new XEFRepositoryDescriptor<
                XSubCategory,
                int,
                IXSubCategoryKeyGenerator,
                XSubCategoryKeyGenerator,
                IXSubCategoryRepositoryEvents,
                XSubCategoryRepositoryEvents,
                XSubCategoryGraphType,
                IntGraphType,
                XSubCategoryGraphQuery,
                IXSubCategoryGraphQLTypeHelper,
                XSubCategoryGraphQLTypeHelper,
                XSubCategoryGraphSchema,
                IXSubCategoryRepository,
                XSubCategoryEFRepository<TContext>,
                TContext
            >();

            //
            return result;
        }

        public static XEFRepositoryDescriptor<
            XSubCategory,
            int,
            IXSubCategoryKeyGenerator,
            XSubCategoryKeyGenerator,
            IXSubCategoryRepositoryEvents,
            XSubCategoryRepositoryEvents,
            XSubCategoryGraphType,
            IntGraphType,
            XSubCategoryGraphQuery,
            IXSubCategoryGraphQLTypeHelper,
            XSubCategoryGraphQLTypeHelper,
            XSubCategoryGraphSchema,
            IXSubCategoryRepository,
            XSubCategoryEFRepository<TContext>,
            TContext,
            IXSubCategorySeeder,
            TSeederImplementation
        > GetXSubCategoryEFRepositoryDescriptor<TContext, TSeederImplementation>()
        where TContext : XDbContext
        where TSeederImplementation : XBaseDbSeeder<XSubCategory, int>
        {
            //
            var result = new XEFRepositoryDescriptor<
                XSubCategory,
                int,
                IXSubCategoryKeyGenerator,
                XSubCategoryKeyGenerator,
                IXSubCategoryRepositoryEvents,
                XSubCategoryRepositoryEvents,
                XSubCategoryGraphType,
                IntGraphType,
                XSubCategoryGraphQuery,
                IXSubCategoryGraphQLTypeHelper,
                XSubCategoryGraphQLTypeHelper,
                XSubCategoryGraphSchema,
                IXSubCategoryRepository,
                XSubCategoryEFRepository<TContext>,
                TContext,
                IXSubCategorySeeder,
                TSeederImplementation
            >();

            //
            return result;
        }
        #endregion
        #endregion

        //
        #region Mongo Repository Descriptor Provider(s) ...
        //
        #region Category
        public static XMongoRepositoryDescriptor<
            XCategory,
            int,
            IXCategoryKeyGenerator,
            XCategoryKeyGenerator,
            IXCategoryRepositoryEvents,
            XCategoryRepositoryEvents,
            XCategoryGraphType,
            IntGraphType,
            XCategoryGraphQuery,
            IXCategoryGraphQLTypeHelper,
            XCategoryGraphQLTypeHelper,
            XCategoryGraphSchema,
            IXCategoryRepository,
            XCategoryMongoRepository
        > GetXCategoryMongoRepositoryDescriptor()
        {
            //
            var result = new XMongoRepositoryDescriptor<
                XCategory,
                int,
                IXCategoryKeyGenerator,
                XCategoryKeyGenerator,
                IXCategoryRepositoryEvents,
                XCategoryRepositoryEvents,
                XCategoryGraphType,
                IntGraphType,
                XCategoryGraphQuery,
                IXCategoryGraphQLTypeHelper,
                XCategoryGraphQLTypeHelper,
                XCategoryGraphSchema,
                IXCategoryRepository,
                XCategoryMongoRepository
            >();

            //
            return result;
        }

        public static XMongoRepositoryDescriptor<
            XCategory,
            int,
            IXCategoryKeyGenerator,
            XCategoryKeyGenerator,
            IXCategoryRepositoryEvents,
            XCategoryRepositoryEvents,
            XCategoryGraphType,
            IntGraphType,
            XCategoryGraphQuery,
            IXCategoryGraphQLTypeHelper,
            XCategoryGraphQLTypeHelper,
            XCategoryGraphSchema,
            IXCategoryRepository,
            XCategoryMongoRepository,
            IXCategorySeeder,
            TSeederImplementation
        > GetXCategoryMongoRepositoryDescriptor<TSeederImplementation>()
        where TSeederImplementation : XBaseDbSeeder<XCategory, int>
        {
            //
            var result = new XMongoRepositoryDescriptor<
                XCategory,
                int,
                IXCategoryKeyGenerator,
                XCategoryKeyGenerator,
                IXCategoryRepositoryEvents,
                XCategoryRepositoryEvents,
                XCategoryGraphType,
                IntGraphType,
                XCategoryGraphQuery,
                IXCategoryGraphQLTypeHelper,
                XCategoryGraphQLTypeHelper,
                XCategoryGraphSchema,
                IXCategoryRepository,
                XCategoryMongoRepository,
                IXCategorySeeder,
                TSeederImplementation
            >();

            //
            return result;
        }
        #endregion

        //
        #region SubCategory
        public static XMongoRepositoryDescriptor<
            XSubCategory,
            int,
            IXSubCategoryKeyGenerator,
            XSubCategoryKeyGenerator,
            IXSubCategoryRepositoryEvents,
            XSubCategoryRepositoryEvents,
            XSubCategoryGraphType,
            IntGraphType,
            XSubCategoryGraphQuery,
            IXSubCategoryGraphQLTypeHelper,
            XSubCategoryGraphQLTypeHelper,
            XSubCategoryGraphSchema,
            IXSubCategoryRepository,
            XSubCategoryMongoRepository
        > GetXSubCategoryMongoRepositoryDescriptor()
        {
            //
            var result = new XMongoRepositoryDescriptor<
                XSubCategory,
                int,
                IXSubCategoryKeyGenerator,
                XSubCategoryKeyGenerator,
                IXSubCategoryRepositoryEvents,
                XSubCategoryRepositoryEvents,
                XSubCategoryGraphType,
                IntGraphType,
                XSubCategoryGraphQuery,
                IXSubCategoryGraphQLTypeHelper,
                XSubCategoryGraphQLTypeHelper,
                XSubCategoryGraphSchema,
                IXSubCategoryRepository,
                XSubCategoryMongoRepository
            >();

            //
            return result;
        }

        public static XMongoRepositoryDescriptor<
            XSubCategory,
            int,
            IXSubCategoryKeyGenerator,
            XSubCategoryKeyGenerator,
            IXSubCategoryRepositoryEvents,
            XSubCategoryRepositoryEvents,
            XSubCategoryGraphType,
            IntGraphType,
            XSubCategoryGraphQuery,
            IXSubCategoryGraphQLTypeHelper,
            XSubCategoryGraphQLTypeHelper,
            XSubCategoryGraphSchema,
            IXSubCategoryRepository,
            XSubCategoryMongoRepository,
            IXSubCategorySeeder,
            TSeederImplementation
        > GetXSubCategoryMongoRepositoryDescriptor<TSeederImplementation>()
        where TSeederImplementation : XBaseDbSeeder<XSubCategory, int>
        {
            //
            var result = new XMongoRepositoryDescriptor<
                XSubCategory,
                int,
                IXSubCategoryKeyGenerator,
                XSubCategoryKeyGenerator,
                IXSubCategoryRepositoryEvents,
                XSubCategoryRepositoryEvents,
                XSubCategoryGraphType,
                IntGraphType,
                XSubCategoryGraphQuery,
                IXSubCategoryGraphQLTypeHelper,
                XSubCategoryGraphQLTypeHelper,
                XSubCategoryGraphSchema,
                IXSubCategoryRepository,
                XSubCategoryMongoRepository,
                IXSubCategorySeeder,
                TSeederImplementation
            >();

            //
            return result;
        }
        #endregion
        #endregion

        //
        #region InMemory Repository Descriptor Provider(s) ...
        //
        #region Category
        public static XInMemoryRepositoryDescriptor<
            XCategory,
            int,
            IXCategoryKeyGenerator,
            XCategoryKeyGenerator,
            IXCategoryRepositoryEvents,
            XCategoryRepositoryEvents,
            XCategoryGraphType,
            IntGraphType,
            XCategoryGraphQuery,
            IXCategoryGraphQLTypeHelper,
            XCategoryGraphQLTypeHelper,
            XCategoryGraphSchema,
            IXCategoryRepository,
            XCategoryInMemoryRepository
        > GetXCategoryInMemoryRepositoryDescriptor()
        {
            //
            var result = new XInMemoryRepositoryDescriptor<
                XCategory,
                int,
                IXCategoryKeyGenerator,
                XCategoryKeyGenerator,
                IXCategoryRepositoryEvents,
                XCategoryRepositoryEvents,
                XCategoryGraphType,
                IntGraphType,
                XCategoryGraphQuery,
                IXCategoryGraphQLTypeHelper,
                XCategoryGraphQLTypeHelper,
                XCategoryGraphSchema,
                IXCategoryRepository,
                XCategoryInMemoryRepository
            >();

            //
            return result;
        }

        public static XInMemoryRepositoryDescriptor<
            XCategory,
            int,
            IXCategoryKeyGenerator,
            XCategoryKeyGenerator,
            IXCategoryRepositoryEvents,
            XCategoryRepositoryEvents,
            XCategoryGraphType,
            IntGraphType,
            XCategoryGraphQuery,
            IXCategoryGraphQLTypeHelper,
            XCategoryGraphQLTypeHelper,
            XCategoryGraphSchema,
            IXCategoryRepository,
            XCategoryInMemoryRepository,
            IXCategorySeeder,
            TSeederImplementation
        > GetXCategoryInMemoryRepositoryDescriptor<TSeederImplementation>()
        where TSeederImplementation : XBaseDbSeeder<XCategory, int>
        {
            //
            var result = new XInMemoryRepositoryDescriptor<
                XCategory,
                int,
                IXCategoryKeyGenerator,
                XCategoryKeyGenerator,
                IXCategoryRepositoryEvents,
                XCategoryRepositoryEvents,
                XCategoryGraphType,
                IntGraphType,
                XCategoryGraphQuery,
                IXCategoryGraphQLTypeHelper,
                XCategoryGraphQLTypeHelper,
                XCategoryGraphSchema,
                IXCategoryRepository,
                XCategoryInMemoryRepository,
                IXCategorySeeder,
                TSeederImplementation
            >();

            //
            return result;
        }
        #endregion

        //
        #region SubCategory
        public static XInMemoryRepositoryDescriptor<
            XSubCategory,
            int,
            IXSubCategoryKeyGenerator,
            XSubCategoryKeyGenerator,
            IXSubCategoryRepositoryEvents,
            XSubCategoryRepositoryEvents,
            XSubCategoryGraphType,
            IntGraphType,
            XSubCategoryGraphQuery,
            IXSubCategoryGraphQLTypeHelper,
            XSubCategoryGraphQLTypeHelper,
            XSubCategoryGraphSchema,
            IXSubCategoryRepository,
            XSubCategoryInMemoryRepository
        > GetXSubCategoryInMemoryRepositoryDescriptor()
        {
            //
            var result = new XInMemoryRepositoryDescriptor<
                XSubCategory,
                int,
                IXSubCategoryKeyGenerator,
                XSubCategoryKeyGenerator,
                IXSubCategoryRepositoryEvents,
                XSubCategoryRepositoryEvents,
                XSubCategoryGraphType,
                IntGraphType,
                XSubCategoryGraphQuery,
                IXSubCategoryGraphQLTypeHelper,
                XSubCategoryGraphQLTypeHelper,
                XSubCategoryGraphSchema,
                IXSubCategoryRepository,
                XSubCategoryInMemoryRepository
            >();

            //
            return result;
        }

        public static XInMemoryRepositoryDescriptor<
            XSubCategory,
            int,
            IXSubCategoryKeyGenerator,
            XSubCategoryKeyGenerator,
            IXSubCategoryRepositoryEvents,
            XSubCategoryRepositoryEvents,
            XSubCategoryGraphType,
            IntGraphType,
            XSubCategoryGraphQuery,
            IXSubCategoryGraphQLTypeHelper,
            XSubCategoryGraphQLTypeHelper,
            XSubCategoryGraphSchema,
            IXSubCategoryRepository,
            XSubCategoryInMemoryRepository,
            IXSubCategorySeeder,
            TSeederImplementation
        > GetXSubCategoryInMemoryRepositoryDescriptor<TSeederImplementation>()
        where TSeederImplementation : XBaseDbSeeder<XSubCategory, int>
        {
            //
            var result = new XInMemoryRepositoryDescriptor<
                XSubCategory,
                int,
                IXSubCategoryKeyGenerator,
                XSubCategoryKeyGenerator,
                IXSubCategoryRepositoryEvents,
                XSubCategoryRepositoryEvents,
                XSubCategoryGraphType,
                IntGraphType,
                XSubCategoryGraphQuery,
                IXSubCategoryGraphQLTypeHelper,
                XSubCategoryGraphQLTypeHelper,
                XSubCategoryGraphSchema,
                IXSubCategoryRepository,
                XSubCategoryInMemoryRepository,
                IXSubCategorySeeder,
                TSeederImplementation
            >();

            //
            return result;
        }
        #endregion
        #endregion                
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xCategoryService\Interfaces\Dtos\IXCategoryDtoHub.cs

using xCategoryService.Models.Dtos;
using xCategoryService.Models.Entities;
using xPushService.Interfaces;

namespace xCategoryService.Interfaces.Dtos
{
    public interface IXCategoryDtoHub : IXBaseDtoHub<XCategory, XCategoryDto, int>
    { }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xCategoryService\Interfaces\Dtos\IXCategoryRepositoryService.cs

using xCategoryService.Models.Dtos;
using xCategoryService.Models.Entities;
using xDataService.Interfaces;

namespace xCategoryService.Interfaces.Dtos
{
    public interface IXCategoryRepositoryService : IXBaseRepositoryService<XCategory, XCategoryDto, int>
    { }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xCategoryService\Interfaces\Dtos\IXCategoryServiceProvider.cs

using xCategoryService.Models.Dtos;
using xCategoryService.Models.Entities;
using xCategoryService.Providers.Dtos;
using xPushService.Interfaces;

namespace xCategoryService.Interfaces.Dtos
{
    public interface IXCategoryServiceProvider : IXBaseDtoProvider<XCategory, XCategoryDto, int, XCategoryDtoHub>
    { }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xCategoryService\Interfaces\Dtos\IXSubCategoryDtoHub.cs

using xCategoryService.Models.Dtos;
using xCategoryService.Models.Entities;
using xPushService.Interfaces;

namespace xCategoryService.Interfaces.Dtos
{
    public interface IXSubCategoryDtoHub : IXBaseDtoHub<XSubCategory, XSubCategoryDto, int>
    { }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xCategoryService\Interfaces\Dtos\IXSubCategoryRepositoryService.cs

using xCategoryService.Models.Dtos;
using xCategoryService.Models.Entities;
using xDataService.Interfaces;

namespace xCategoryService.Interfaces.Dtos
{
    public interface IXSubCategoryRepositoryService : IXBaseRepositoryService<XSubCategory, XSubCategoryDto, int>
    { }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xCategoryService\Interfaces\Dtos\IXSubCategoryServiceProvider.cs

using xCategoryService.Models.Dtos;
using xCategoryService.Models.Entities;
using xCategoryService.Providers.Dtos;
using xPushService.Interfaces;

namespace xCategoryService.Interfaces.Dtos
{
    public interface IXSubCategoryServiceProvider : IXBaseDtoProvider<XSubCategory, XSubCategoryDto, int, XSubCategoryDtoHub>
    { }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xCategoryService\Interfaces\Entities\IXCategoryEntityHub.cs

using xCategoryService.Models.Entities;
using xPushService.Interfaces;

namespace xCategoryService.Interfaces.Entities
{
    public interface IXCategoryEntityHub : IXBaseEntityHub<XCategory, int>
    { }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xCategoryService\Interfaces\Entities\IXCategoryGraphQLTypeHelper.cs

using xCategoryService.Models.Entities;
using xDataService.Interfaces;

namespace xCategoryService.Interfaces.Entities
{
    public interface IXCategoryGraphQLTypeHelper : IXBaseGraphQLTypeHelper<XCategory, int>
    { }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xCategoryService\Interfaces\Entities\IXCategoryKeyGenerator.cs

using xCategoryService.Models.Entities;
using xDataService.Interfaces;

namespace xCategoryService.Interfaces.Entities
{
    public interface IXCategoryKeyGenerator : IXKeyGenerator<XCategory, int>
    { }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xCategoryService\Interfaces\Entities\IXCategoryRepository.cs

using xCategoryService.Models.Entities;
using xDataService.Interfaces;

namespace xCategoryService.Interfaces.Entities
{
    public interface IXCategoryRepository : IXBaseRepository<XCategory, int>
    { }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xCategoryService\Interfaces\Entities\IXCategoryRepositoryEvents.cs

using xCategoryService.Models.Entities;
using xDataService.Interfaces;

namespace xCategoryService.Interfaces.Entities
{
    public interface IXCategoryRepositoryEvents : IXBaseRepositoryEvents<XCategory>
    { }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xCategoryService\Interfaces\Entities\IXCategoryRepositoryProvider.cs

using xCategoryService.Models.Entities;
using xCategoryService.Providers.Entities;
using xPushService.Interfaces;

namespace xCategoryService.Interfaces.Entities
{
    public interface IXCategoryRepositoryProvider : IXBaseEntityProvider<XCategory, int, XCategoryEntityHub>
    { }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xCategoryService\Interfaces\Entities\IXCategorySeeder.cs

using xCategoryService.Models.Entities;
using xDataService.Interfaces;

namespace xCategoryService.Interfaces.Entities
{
    public interface IXCategorySeeder : IXBaseDbSeeder<XCategory, int>
    { }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xCategoryService\Interfaces\Entities\IXSubCategoryEntityHub.cs

using xCategoryService.Models.Entities;
using xPushService.Interfaces;

namespace xCategoryService.Interfaces.Entities
{
    public interface IXSubCategoryEntityHub : IXBaseEntityHub<XSubCategory, int>
    { }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xCategoryService\Interfaces\Entities\IXSubCategoryGraphQLTypeHelper.cs

using xCategoryService.Models.Entities;
using xDataService.Interfaces;

namespace xCategoryService.Interfaces.Entities
{
    public interface IXSubCategoryGraphQLTypeHelper : IXBaseGraphQLTypeHelper<XSubCategory, int>
    { }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xCategoryService\Interfaces\Entities\IXSubCategoryKeyGenerator.cs

using xCategoryService.Models.Entities;
using xDataService.Interfaces;

namespace xCategoryService.Interfaces.Entities
{
    public interface IXSubCategoryKeyGenerator : IXKeyGenerator<XSubCategory, int>
    { }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xCategoryService\Interfaces\Entities\IXSubCategoryRepository.cs

using xCategoryService.Models.Entities;
using xDataService.Interfaces;

namespace xCategoryService.Interfaces.Entities
{
    public interface IXSubCategoryRepository : IXBaseRepository<XSubCategory, int>
    { }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xCategoryService\Interfaces\Entities\IXSubCategoryRepositoryEvents.cs

using xCategoryService.Models.Entities;
using xDataService.Interfaces;

namespace xCategoryService.Interfaces.Entities
{
    public interface IXSubCategoryRepositoryEvents : IXBaseRepositoryEvents<XSubCategory>
    { }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xCategoryService\Interfaces\Entities\IXSubCategoryRepositoryProvider.cs

using xCategoryService.Models.Entities;
using xCategoryService.Providers.Entities;
using xPushService.Interfaces;

namespace xCategoryService.Interfaces.Entities
{
    public interface IXSubCategoryRepositoryProvider : IXBaseEntityProvider<XSubCategory, int, XSubCategoryEntityHub>
    { }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xCategoryService\Interfaces\Entities\IXSubCategorySeeder.cs

using xCategoryService.Models.Entities;
using xDataService.Interfaces;

namespace xCategoryService.Interfaces.Entities
{
    public interface IXSubCategorySeeder : IXBaseDbSeeder<XSubCategory, int>
    { }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xCategoryService\Interfaces\IXBaseCategoryProvider.cs

using xCategoryService.Models.Dtos;
using xDataService.Interfaces;

namespace xCategoryService.Interfaces
{
    public interface IXBaseCategoryProvider<TKey> : IXBaseReferencedProvider<XCategoryDto, TKey>
    {}
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xCategoryService\Interfaces\IXCategoryDescriptionResourceProvider.cs

using xStringService.Interfaces;

namespace xCategoryService.Interfaces
{
    public interface IXCategoryDescriptionResourceProvider : IXItemResourceProvider
    { }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xCategoryService\Interfaces\IXCategoryProvider.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Threading;
using System.Threading.Tasks;
using xCategoryService.Models.Dtos;
using xCategoryService.Models.Entities;
using xCategoryService.Providers.Dtos;
using xIdentityModels.Models;
using xModels.Dtos;
using xPushService.Interfaces;

namespace xCategoryService.Interfaces
{
    public interface IXCategoryProvider : IXBaseProvided<XCategory, XCategoryDto, int, XCategoryDtoHub>, IXCategorySubCategoryReferenceProvider
    {
        /// <summary>
        /// Check Has Specified Locale or not ...
        /// </summary>
        /// <param name="id"></param>
        /// <param name="language"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        Task<bool> HasLocale(
            int id,
            string language,
            CancellationToken cancellationToken = default
        );

        /// <summary>
        /// Load an Item by all of it's Related Translations ...
        /// </summary>
        /// <param name="id"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>        
        Task<XCategoryResourceDto> GetResource(
            int id,
            CancellationToken cancellationToken = default
        );

        /// <summary>
        /// Add Item for Specified Language ...
        /// </summary>
        /// <param name="item"></param>
        /// <param name="language"></param>
        /// <param name="connectionId"></param>
        /// <param name="userInfo"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        Task<XCategoryResourceDto> Add(
            XCategoryDto item,
            string language = null,
            string connectionId = null,
            XUserClaimsInfoDto userInfo = null,
            CancellationToken cancellationToken = default
        );

        /// <summary>
        /// Add Item by It's Locales ...
        /// </summary>
        /// <param name="item"></param>
        /// <param name="connectionId"></param>
        /// <param name="userInfo"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        Task<XCategoryResourceDto> AddResource(
            XCategoryResourceDto item,
            string connectionId = null,
            XUserClaimsInfoDto userInfo = null,
            CancellationToken cancellationToken = default
        );

        /// <summary>
        /// Remove Item for Specified Language ...
        /// </summary>
        /// <param name="id"></param>
        /// <param name="language">if null, Remove All</param>
        /// <param name="connectionId"></param>
        /// <param name="userInfo"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        Task<XCategoryResourceDto> Remove(
            int id,
            string language = null,
            string connectionId = null,
            XUserClaimsInfoDto userInfo = null,
            CancellationToken cancellationToken = default
        );

        /// <summary>
        /// Update an Item for Specified Language ...
        /// </summary>
        /// <param name="id"></param>
        /// <param name="item"></param>
        /// <param name="language"></param>
        /// <param name="connectionId"></param>
        /// <param name="userInfo"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        Task<XCategoryResourceDto> Update(
            int id,
            XCategoryDto item,
            string language = null,
            string connectionId = null,
            XUserClaimsInfoDto userInfo = null,
            CancellationToken cancellationToken = default
        );

        /// <summary>
        /// Refresh a Resource ...
        /// </summary>
        /// <param name="resource"></param>
        /// <param name="connectionId"></param>
        /// <param name="userInfo"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        Task<XCategoryResourceDto> Refresh(
            XCategoryResourceDto resource,
            string connectionId = null,
            XUserClaimsInfoDto userInfo = null,
            CancellationToken cancellationToken = default
        );

        /// <summary>
        /// Get All Resources ...
        /// </summary>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        Task<IEnumerable<XCategoryResourceDto>> GetAllResources(
            CancellationToken cancellationToken = default
        );

        /// <summary>
        /// Find One Resource ...
        /// </summary>
        /// <param name="predicate"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        Task<XCategoryResourceDto> FindOneResource(
            Expression<Func<XCategoryResourceDto, bool>> predicate = null,
            CancellationToken cancellationToken = default
        );

        /// <summary>
        /// Find Many Resource ...
        /// </summary>
        /// <param name="predicate"></param>
        /// <param name="orderBuilder"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        Task<IEnumerable<XCategoryResourceDto>> FindManyResource(
            Expression<Func<XCategoryResourceDto, bool>> predicate = null,
            Func<IQueryable<XCategoryResourceDto>, IOrderedQueryable<XCategoryResourceDto>> orderBuilder = null,
            CancellationToken cancellationToken = default
        );

        /// <summary>
        /// Retrieve Resources by Query Pattern ...
        /// </summary>
        /// <param name="query"></param>
        /// <param name="predicate"></param>
        /// <param name="orderBuilder"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        Task<XQueryResult<XCategoryResourceDto>> QueryResources(
            XQuery query = null,
            Expression<Func<XCategoryResourceDto, bool>> predicate = null,
            Func<IQueryable<XCategoryResourceDto>, IOrderedQueryable<XCategoryResourceDto>> orderBuilder = null,
            CancellationToken cancellationToken = default
        );

        /// <summary>
        /// Get All Resources as Async Enumerable ... 
        /// </summary>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        IAsyncEnumerable<XCategoryResourceDto> GetAllResourcesAsAsyncEnumerable(
            CancellationToken cancellationToken = default
        );
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xCategoryService\Interfaces\IXCategoryProviderController.cs

using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
using xCategoryService.Models.Dtos;
using xCategoryService.Models.Entities;
using xCategoryService.Providers.Dtos;
using xModels.Dtos;
using xPushService.Interfaces;

namespace xCategoryService.Interfaces
{
    public interface IXCategoryProviderController : IXBaseProvidedController<XCategory, XCategoryDto, int, XCategoryDtoHub>
    {
        /// <summary>
        /// Check Has Specified Locale or not ...
        /// </summary>
        /// <param name="id"></param>
        /// <param name="language"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        [HttpGet("Resources/{id}/HasLocale")]
        Task<ActionResult<bool>> HasLocale(
            [FromRoute] int id,
            [FromQuery] string language,
            CancellationToken cancellationToken = default
        );

        /// <summary>
        /// Load an Item by all of it's Related Translations ...
        /// </summary>
        /// <param name="id"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        [HttpGet("Resources/{id}")]
        Task<ActionResult<XCategoryResourceDto>> GetResource(
            [FromRoute] int id,
            CancellationToken cancellationToken = default
        );

        /// <summary>
        /// Add Item for Specified Language ...
        /// </summary>
        /// <param name="item"></param>
        /// <param name="language"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        [HttpPost("Resources")]
        Task<ActionResult<XCategoryResourceDto>> Add(
            [FromBody] XCategoryDto item,
            [FromQuery] string language = null,
            CancellationToken cancellationToken = default
        );

        /// <summary>
        /// Add Item by It's Locales ...
        /// </summary>
        /// <param name="item"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        [HttpPost("Resources/AddResource")]
        Task<ActionResult<XCategoryResourceDto>> AddResource(
            [FromBody] XCategoryResourceDto item,
            CancellationToken cancellationToken = default
        );

        /// <summary>
        /// Remove Item for Specified Language ...
        /// </summary>
        /// <param name="id"></param>
        /// <param name="language">if null, Remove All</param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        [HttpDelete("Resources/{id}")]
        Task<ActionResult<XCategoryResourceDto>> Remove(
            [FromRoute] int id,
            [FromQuery] string language = null,
            CancellationToken cancellationToken = default
        );

        /// <summary>
        /// Update an Item for Specified Language ...
        /// </summary>
        /// <param name="id"></param>
        /// <param name="item"></param>
        /// <param name="language"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        [HttpPut("Resources/{id}")]
        Task<ActionResult<XCategoryResourceDto>> Update(
            [FromRoute] int id,
            [FromBody] XCategoryDto item,
            [FromQuery] string language = null,
            CancellationToken cancellationToken = default
        );

        /// <summary>
        /// Refresh a Resource ...
        /// </summary>
        /// <param name="resource"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        [HttpPost("Resources/Refresh")]
        Task<ActionResult<XCategoryResourceDto>> Refresh(
            [FromBody] XCategoryResourceDto resource,
            CancellationToken cancellationToken = default
        );

        /// <summary>
        /// Get All Resources ...
        /// </summary>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        [HttpGet("Resources/All")]
        Task<ActionResult<IEnumerable<XCategoryResourceDto>>> GetAllResources(
            CancellationToken cancellationToken = default
        );

        /// <summary>
        /// Find One Resource ...
        /// </summary>
        /// <param name="query"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        [HttpGet("Resources/Find/One")]
        Task<ActionResult<XCategoryResourceDto>> FindOneResource(
            [FromQuery] string query,
            CancellationToken cancellationToken = default
        );

        /// <summary>
        /// Find Many Resource ...
        /// </summary>
        /// <param name="query"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        [HttpGet("Resources/Find/Many")]
        Task<ActionResult<IEnumerable<XCategoryResourceDto>>> FindManyResource(
            [FromQuery] string query,
            CancellationToken cancellationToken = default
        );

        /// <summary>
        /// Retrieve Resources by Query Pattern ...
        /// </summary>
        /// <param name="query"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        [HttpGet("Resources/Query")]
        Task<ActionResult<XQueryResult<XCategoryResourceDto>>> QueryResources(
            [FromQuery] XQuery query = null,
            CancellationToken cancellationToken = default
        );
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xCategoryService\Interfaces\IXCategoryService.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Threading;
using System.Threading.Tasks;
using xCategoryService.Models.Dtos;
using xIdentityModels.Models;
using xModels.Dtos;

namespace xCategoryService.Interfaces
{
    /// <summary>
    /// Completely Exported Service ...
    /// </summary>
    public interface IXCategoryService
    {
        //
        #region Category Provider ...
        /// <summary>
        /// Check Has Specified Locale or not ...
        /// </summary>
        /// <param name="id"></param>
        /// <param name="language"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        Task<bool> CategoryHasLocale(
            int id,
            string language,
            CancellationToken cancellationToken = default
        );

        /// <summary>
        /// Load an Item by all of it's Related Translations ...
        /// </summary>
        /// <param name="id"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>        
        Task<XCategoryResourceDto> GetCategoryResource(
            int id,
            CancellationToken cancellationToken = default
        );

        /// <summary>
        /// Add Item for Specified Language ...
        /// </summary>
        /// <param name="item"></param>
        /// <param name="language"></param>
        /// <param name="connectionId"></param>
        /// <param name="userInfo"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        Task<XCategoryResourceDto> AddCategory(
            XCategoryDto item,
            string language = null,
            string connectionId = null,
            XUserClaimsInfoDto userInfo = null,
            CancellationToken cancellationToken = default
        );

        /// <summary>
        /// Add Item by It's Locales ...
        /// </summary>
        /// <param name="item"></param>
        /// <param name="connectionId"></param>
        /// <param name="userInfo"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        Task<XCategoryResourceDto> AddCategoryResource(
            XCategoryResourceDto item,
            string connectionId = null,
            XUserClaimsInfoDto userInfo = null,
            CancellationToken cancellationToken = default
        );

        /// <summary>
        /// Remove Item for Specified Language ...
        /// </summary>
        /// <param name="id"></param>
        /// <param name="language">if null, Remove All</param>
        /// <param name="connectionId"></param>
        /// <param name="userInfo"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        Task<XCategoryResourceDto> RemoveCategory(
            int id,
            string language = null,
            string connectionId = null,
            XUserClaimsInfoDto userInfo = null,
            CancellationToken cancellationToken = default
        );

        /// <summary>
        /// Update an Item for Specified Language ...
        /// </summary>
        /// <param name="id"></param>
        /// <param name="item"></param>
        /// <param name="language"></param>
        /// <param name="connectionId"></param>
        /// <param name="userInfo"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        Task<XCategoryResourceDto> UpdateCategory(
            int id,
            XCategoryDto item,
            string language = null,
            string connectionId = null,
            XUserClaimsInfoDto userInfo = null,
            CancellationToken cancellationToken = default
        );

        /// <summary>
        /// Refresh a Resource ...
        /// </summary>
        /// <param name="resource"></param>
        /// <param name="connectionId"></param>
        /// <param name="userInfo"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        Task<XCategoryResourceDto> RefreshCategory(
            XCategoryResourceDto resource,
            string connectionId = null,
            XUserClaimsInfoDto userInfo = null,
            CancellationToken cancellationToken = default
        );

        /// <summary>
        /// Get All Resources ...
        /// </summary>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        Task<IEnumerable<XCategoryResourceDto>> GetAllCategoryResources(
            CancellationToken cancellationToken = default
        );

        /// <summary>
        /// Find One Resource ...
        /// </summary>
        /// <param name="predicate"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        Task<XCategoryResourceDto> FindOneCategoryResource(
            Expression<Func<XCategoryResourceDto, bool>> predicate = null,
            CancellationToken cancellationToken = default
        );

        /// <summary>
        /// Find Many Resource ...
        /// </summary>
        /// <param name="predicate"></param>
        /// <param name="orderBuilder"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        Task<IEnumerable<XCategoryResourceDto>> FindManyCategoryResource(
            Expression<Func<XCategoryResourceDto, bool>> predicate = null,
            Func<IQueryable<XCategoryResourceDto>, IOrderedQueryable<XCategoryResourceDto>> orderBuilder = null,
            CancellationToken cancellationToken = default
        );

        /// <summary>
        /// Retrieve Resources by Query Pattern ...
        /// </summary>
        /// <param name="query"></param>
        /// <param name="predicate"></param>
        /// <param name="orderBuilder"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        Task<XQueryResult<XCategoryResourceDto>> QueryCategoryResources(
            XQuery query = null,
            Expression<Func<XCategoryResourceDto, bool>> predicate = null,
            Func<IQueryable<XCategoryResourceDto>, IOrderedQueryable<XCategoryResourceDto>> orderBuilder = null,
            CancellationToken cancellationToken = default
        );

        /// <summary>
        /// Get All Resources as Async Enumerable ... 
        /// </summary>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        IAsyncEnumerable<XCategoryResourceDto> GetAllCategoryResourcesAsAsyncEnumerable(
            CancellationToken cancellationToken = default
        );
        #endregion

        //
        #region SubCategory Provider ...
        /// <summary>
        /// Check Has Specified Locale or not ...
        /// </summary>
        /// <param name="id"></param>
        /// <param name="language"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        Task<bool> SubCategoryHasLocale(
            int id,
            string language,
            CancellationToken cancellationToken = default
        );

        /// <summary>
        /// Load an Item by all of it's Related Translations ...
        /// </summary>
        /// <param name="id"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>        
        Task<XSubCategoryResourceDto> GetSubCategoryResource(
            int id,
            CancellationToken cancellationToken = default
        );

        /// <summary>
        /// Add Item for Specified Language ...
        /// </summary>
        /// <param name="item"></param>
        /// <param name="language"></param>
        /// <param name="connectionId"></param>
        /// <param name="userInfo"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        Task<XSubCategoryResourceDto> AddSubCategory(
            XSubCategoryDto item,
            string language = null,
            string connectionId = null,
            XUserClaimsInfoDto userInfo = null,
            CancellationToken cancellationToken = default
        );

        /// <summary>
        /// Add Item by it's Locales and Reference ...
        /// </summary>
        /// <param name="item"></param>
        /// <param name="connectionId"></param>
        /// <param name="userInfo"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        Task<XSubCategoryResourceDto> AddSubCategoryResource(
            XSubCategoryResourceDto item,
            string connectionId = null,
            XUserClaimsInfoDto userInfo = null,
            CancellationToken cancellationToken = default
        );

        /// <summary>
        /// Remove Item for Specified Language ...
        /// </summary>
        /// <param name="id"></param>
        /// <param name="language">if null, Remove All</param>
        /// <param name="connectionId"></param>
        /// <param name="userInfo"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        Task<XSubCategoryResourceDto> RemoveSubCategory(
            int id,
            string language = null,
            string connectionId = null,
            XUserClaimsInfoDto userInfo = null,
            CancellationToken cancellationToken = default
        );

        /// <summary>
        /// Update an Item for Specified Language ...
        /// </summary>
        /// <param name="id"></param>
        /// <param name="item"></param>
        /// <param name="language"></param>
        /// <param name="connectionId"></param>
        /// <param name="userInfo"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        Task<XSubCategoryResourceDto> UpdateSubCategory(
            int id,
            XSubCategoryDto item,
            string language = null,
            string connectionId = null,
            XUserClaimsInfoDto userInfo = null,
            CancellationToken cancellationToken = default
        );

        /// <summary>
        /// Refresh a Resource ...
        /// </summary>
        /// <param name="resource"></param>
        /// <param name="connectionId"></param>
        /// <param name="userInfo"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        Task<XSubCategoryResourceDto> RefreshSubCategory(
            XSubCategoryResourceDto resource,
            string connectionId = null,
            XUserClaimsInfoDto userInfo = null,
            CancellationToken cancellationToken = default
        );

        /// <summary>
        /// Get All Resources ...
        /// </summary>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        Task<IEnumerable<XSubCategoryResourceDto>> GetAllSubCategoryResources(
            CancellationToken cancellationToken = default
        );

        /// <summary>
        /// Find One Resource ...
        /// </summary>
        /// <param name="predicate"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        Task<XSubCategoryResourceDto> FindOneSubCategoryResource(
            Expression<Func<XSubCategoryResourceDto, bool>> predicate = null,
            CancellationToken cancellationToken = default
        );

        /// <summary>
        /// Find Many Resource ...
        /// </summary>
        /// <param name="predicate"></param>
        /// <param name="orderBuilder"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        Task<IEnumerable<XSubCategoryResourceDto>> FindManySubCategoryResource(
            Expression<Func<XSubCategoryResourceDto, bool>> predicate = null,
            Func<IQueryable<XSubCategoryResourceDto>, IOrderedQueryable<XSubCategoryResourceDto>> orderBuilder = null,
            CancellationToken cancellationToken = default
        );

        /// <summary>
        /// Retrieve Resources by Query Pattern ...
        /// </summary>
        /// <param name="query"></param>
        /// <param name="predicate"></param>
        /// <param name="orderBuilder"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        Task<XQueryResult<XSubCategoryResourceDto>> QuerySubCategoryResources(
            XQuery query = null,
            Expression<Func<XSubCategoryResourceDto, bool>> predicate = null,
            Func<IQueryable<XSubCategoryResourceDto>, IOrderedQueryable<XSubCategoryResourceDto>> orderBuilder = null,
            CancellationToken cancellationToken = default
        );

        /// <summary>
        /// Get All Resources as Async Enumerable ... 
        /// </summary>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        IAsyncEnumerable<XSubCategoryResourceDto> GetAllSubCategoryResourcesAsAsyncEnumerable(
            CancellationToken cancellationToken = default
        );
        #endregion
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xCategoryService\Interfaces\IXCategorySubCategoryReferenceProvider.cs

namespace xCategoryService.Interfaces
{
    /// <summary>
    /// a Service for SubCategory Referencing on Category ...
    /// </summary>
    public interface IXCategorySubCategoryReferenceProvider : IXBaseCategoryProvider<int>
    { }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xCategoryService\Interfaces\IXCategoryTitleResourceProvider.cs

using xStringService.Interfaces;

namespace xCategoryService.Interfaces
{
    public interface IXCategoryTitleResourceProvider : IXItemResourceProvider
    { }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xCategoryService\Interfaces\IXSubCategoryDescriptionResourceProvider.cs

using xStringService.Interfaces;

namespace xCategoryService.Interfaces
{
    public interface IXSubCategoryDescriptionResourceProvider : IXItemResourceProvider
    { }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xCategoryService\Interfaces\IXSubCategoryProvider.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Threading;
using System.Threading.Tasks;
using xCategoryService.Models.Dtos;
using xCategoryService.Models.Entities;
using xCategoryService.Providers.Dtos;
using xIdentityModels.Models;
using xModels.Dtos;
using xPushService.Interfaces;

namespace xCategoryService.Interfaces
{
    public interface IXSubCategoryProvider : IXBaseProvided<XSubCategory, XSubCategoryDto, int, XSubCategoryDtoHub>
    {
        /// <summary>
        /// Check Has Specified Locale or not ...
        /// </summary>
        /// <param name="id"></param>
        /// <param name="language"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        Task<bool> HasLocale(
            int id,
            string language,
            CancellationToken cancellationToken = default
        );

        /// <summary>
        /// Load an Item by all of it's Related Translations ...
        /// </summary>
        /// <param name="id"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>        
        Task<XSubCategoryResourceDto> GetResource(
            int id,
            CancellationToken cancellationToken = default
        );

        /// <summary>
        /// Add Item for Specified Language ...
        /// </summary>
        /// <param name="item"></param>
        /// <param name="language"></param>
        /// <param name="connectionId"></param>
        /// <param name="userInfo"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        Task<XSubCategoryResourceDto> Add(
            XSubCategoryDto item,
            string language = null,
            string connectionId = null,
            XUserClaimsInfoDto userInfo = null,
            CancellationToken cancellationToken = default
        );

        /// <summary>
        /// Add Item by it's Locales and Reference ...
        /// </summary>
        /// <param name="item"></param>
        /// <param name="connectionId"></param>
        /// <param name="userInfo"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        Task<XSubCategoryResourceDto> AddResource(
            XSubCategoryResourceDto item,
            string connectionId = null,
            XUserClaimsInfoDto userInfo = null,
            CancellationToken cancellationToken = default
        );

        /// <summary>
        /// Remove Item for Specified Language ...
        /// </summary>
        /// <param name="id"></param>
        /// <param name="language">if null, Remove All</param>
        /// <param name="connectionId"></param>
        /// <param name="userInfo"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        Task<XSubCategoryResourceDto> Remove(
            int id,
            string language = null,
            string connectionId = null,
            XUserClaimsInfoDto userInfo = null,
            CancellationToken cancellationToken = default
        );

        /// <summary>
        /// Update an Item for Specified Language ...
        /// </summary>
        /// <param name="id"></param>
        /// <param name="item"></param>
        /// <param name="language"></param>
        /// <param name="connectionId"></param>
        /// <param name="userInfo"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        Task<XSubCategoryResourceDto> Update(
            int id,
            XSubCategoryDto item,
            string language = null,
            string connectionId = null,
            XUserClaimsInfoDto userInfo = null,
            CancellationToken cancellationToken = default
        );

        /// <summary>
        /// Refresh a Resource ...
        /// </summary>
        /// <param name="resource"></param>
        /// <param name="connectionId"></param>
        /// <param name="userInfo"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        Task<XSubCategoryResourceDto> Refresh(
            XSubCategoryResourceDto resource,
            string connectionId = null,
            XUserClaimsInfoDto userInfo = null,
            CancellationToken cancellationToken = default
        );

        /// <summary>
        /// Get All Resources ...
        /// </summary>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        Task<IEnumerable<XSubCategoryResourceDto>> GetAllResources(
            CancellationToken cancellationToken = default
        );

        /// <summary>
        /// Find One Resource ...
        /// </summary>
        /// <param name="predicate"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        Task<XSubCategoryResourceDto> FindOneResource(
            Expression<Func<XSubCategoryResourceDto, bool>> predicate = null,
            CancellationToken cancellationToken = default
        );
        
        /// <summary>
        /// Find Many Resource ...
        /// </summary>
        /// <param name="predicate"></param>
        /// <param name="orderBuilder"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        Task<IEnumerable<XSubCategoryResourceDto>> FindManyResource(
            Expression<Func<XSubCategoryResourceDto, bool>> predicate = null,
            Func<IQueryable<XSubCategoryResourceDto>, IOrderedQueryable<XSubCategoryResourceDto>> orderBuilder = null,
            CancellationToken cancellationToken = default
        );

        /// <summary>
        /// Retrieve Resources by Query Pattern ...
        /// </summary>
        /// <param name="query"></param>
        /// <param name="predicate"></param>
        /// <param name="orderBuilder"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        Task<XQueryResult<XSubCategoryResourceDto>> QueryResources(
            XQuery query = null,
            Expression<Func<XSubCategoryResourceDto, bool>> predicate = null,
            Func<IQueryable<XSubCategoryResourceDto>, IOrderedQueryable<XSubCategoryResourceDto>> orderBuilder = null,
            CancellationToken cancellationToken = default
        );        

        /// <summary>
        /// Get All Resources as Async Enumerable ... 
        /// </summary>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        IAsyncEnumerable<XSubCategoryResourceDto> GetAllResourcesAsAsyncEnumerable(
            CancellationToken cancellationToken = default
        );        
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xCategoryService\Interfaces\IXSubCategoryProviderController.cs

using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
using xCategoryService.Models.Dtos;
using xCategoryService.Models.Entities;
using xCategoryService.Providers.Dtos;
using xModels.Dtos;
using xPushService.Interfaces;

namespace xCategoryService.Interfaces
{
    public interface IXSubCategoryProviderController : IXBaseProvidedController<XSubCategory, XSubCategoryDto, int, XSubCategoryDtoHub>
    {
        /// <summary>
        /// Check Has Specified Locale or not ...
        /// </summary>
        /// <param name="id"></param>
        /// <param name="language"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        [HttpGet("Resources/{id}/HasLocale")]
        Task<ActionResult<bool>> HasLocale(
            [FromRoute] int id,
            [FromQuery] string language,
            CancellationToken cancellationToken = default
        );

        /// <summary>
        /// Load an Item by all of it's Related Translations ...
        /// </summary>
        /// <param name="id"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        [HttpGet("Resources/{id}")]
        Task<ActionResult<XSubCategoryResourceDto>> GetResource(
            [FromRoute] int id,
            CancellationToken cancellationToken = default
        );

        /// <summary>
        /// Add Item for Specified Language ...
        /// </summary>
        /// <param name="item"></param>
        /// <param name="language"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        [HttpPost("Resources")]
        Task<ActionResult<XSubCategoryResourceDto>> Add(
            [FromBody] XSubCategoryDto item,
            [FromQuery] string language = null,
            CancellationToken cancellationToken = default
        );

        /// <summary>
        /// Add Item by it's Locales and Reference ...
        /// </summary>
        /// <param name="item"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        [HttpPost("Resources/AddResource")]
        Task<ActionResult<XSubCategoryResourceDto>> AddResource(
            [FromBody] XSubCategoryResourceDto item,
            CancellationToken cancellationToken = default
        );

        /// <summary>
        /// Remove Item for Specified Language ...
        /// </summary>
        /// <param name="id"></param>
        /// <param name="language">if null, Remove All</param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        [HttpDelete("Resources/{id}")]
        Task<ActionResult<XSubCategoryResourceDto>> Remove(
            [FromRoute] int id,
            [FromQuery] string language = null,
            CancellationToken cancellationToken = default
        );

        /// <summary>
        /// Update an Item for Specified Language ...
        /// </summary>
        /// <param name="id"></param>
        /// <param name="item"></param>
        /// <param name="language"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        [HttpPut("Resources/{id}")]
        Task<ActionResult<XSubCategoryResourceDto>> Update(
            [FromRoute] int id,
            [FromBody] XSubCategoryDto item,
            [FromQuery] string language = null,
            CancellationToken cancellationToken = default
        );

        /// <summary>
        /// Refresh a Resource ...
        /// </summary>
        /// <param name="resource"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        [HttpPost("Resources/Refresh")]
        Task<ActionResult<XSubCategoryResourceDto>> Refresh(
            [FromBody] XSubCategoryResourceDto resource,
            CancellationToken cancellationToken = default
        );

        /// <summary>
        /// Get All Resources ...
        /// </summary>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        [HttpGet("Resources/All")]
        Task<ActionResult<IEnumerable<XSubCategoryResourceDto>>> GetAllResources(
            CancellationToken cancellationToken = default
        );

        /// <summary>
        /// Find One Resource ...
        /// </summary>
        /// <param name="query"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        [HttpGet("Resources/Find/One")]
        Task<ActionResult<XSubCategoryResourceDto>> FindOneResource(
            [FromQuery] string query,
            CancellationToken cancellationToken = default
        );

        /// <summary>
        /// Find Many Resource ...
        /// </summary>
        /// <param name="query"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        [HttpGet("Resources/Find/Many")]
        Task<ActionResult<IEnumerable<XSubCategoryResourceDto>>> FindManyResource(
            [FromQuery] string query,
            CancellationToken cancellationToken = default
        );

        /// <summary>
        /// Retrieve Resources by Query Pattern ...
        /// </summary>
        /// <param name="query"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        [HttpGet("Resources/Query")]
        Task<ActionResult<XQueryResult<XSubCategoryResourceDto>>> QueryResources(
            [FromQuery] XQuery query = null,
            CancellationToken cancellationToken = default
        );
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xCategoryService\Interfaces\IXSubCategoryTitleResourceProvider.cs

using xStringService.Interfaces;

namespace xCategoryService.Interfaces
{
    public interface IXSubCategoryTitleResourceProvider : IXItemResourceProvider
    { }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xCategoryService\Models\Dtos\XCategoryDto.cs

using xModels.Base;

namespace xCategoryService.Models.Dtos
{
    public class XCategoryDto : XBaseIntIDEntityDto
    {
        /// <summary>
        /// Title of SubCategory ...
        /// this is a Resource Title ...
        /// </summary>
        /// <value></value>
        public string Title { get; set; }

        /// <summary>
        /// Description of SubCategory ...
        /// this is a Resource Title ...
        /// </summary>
        /// <value></value>
        public string Description { get; set; }

        /// <summary>
        /// References List String Representation ...
        /// each SubCategory Referenced to Category ID which List here ...
        /// </summary>
        /// <value></value>
        public string References { get; set; }
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xCategoryService\Models\Dtos\XCategoryResourceDto.cs

using xModels.Base;
using xModels.Dtos;

namespace xCategoryService.Models.Dtos
{
    /// <summary>
    /// Represent a Category by all of it's Resources ...
    /// </summary>
    public class XCategoryResourceDto : XBaseDto
    {
        /// <summary>
        /// Category Dto Item for Add or Update ...
        /// </summary>
        public XCategoryDto Item { get; set; }

        /// <summary>
        /// Exists Category Titles ...
        /// </summary>
        public XResourceDto Titles { get; set; }

        /// <summary>
        /// Exists Category Description ...
        /// </summary>
        public XResourceDto Descriptions { get; set; }
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xCategoryService\Models\Dtos\XSubCategoryDto.cs

using xModels.Base;

namespace xCategoryService.Models.Dtos
{
    public class XSubCategoryDto : XBaseIntIDEntityDto
    {
        /// <summary>
        /// Title of SubCategory ...
        /// this is a Resource Title ...
        /// </summary>
        /// <value></value>
        public string Title { get; set; }

        /// <summary>
        /// Description of SubCategory ...
        /// this is a Resource Title ...
        /// </summary>
        /// <value></value>
        public string Description { get; set; }

        /// <summary>
        /// References List String Representation ...
        /// each SubCategory Referenced to Category ID which List here ...
        /// </summary>
        /// <value></value>
        public string References { get; set; }
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xCategoryService\Models\Dtos\XSubCategoryResourceDto.cs

using xModels.Base;
using xModels.Dtos;

namespace xCategoryService.Models.Dtos
{
    public class XSubCategoryResourceDto : XBaseDto
    {
        /// <summary>
        /// SubCategory Dto Item for Add or Update ...
        /// </summary>
        public XSubCategoryDto Item { get; set; }

        /// <summary>
        /// Exists SubCategory Titles ...
        /// </summary>
        public XResourceDto Titles { get; set; }

        /// <summary>
        /// Exists SubCategory Description ...
        /// </summary>
        public XResourceDto Descriptions { get; set; }

        /// <summary>
        /// Exists Category Resource Dto for Add or Update Category or 
        /// Related Categopry ...
        /// </summary>
        public XCategoryResourceDto Category { get; set; }
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xCategoryService\Models\Entities\XCategory.cs

using xModels.Base;

namespace xCategoryService.Models.Entities
{
    public class XCategory : XBaseIntIDEntity
    {
        /// <summary>
        /// Title of SubCategory ...
        /// this is a Resource Title ...
        /// </summary>
        /// <value></value>
        public string Title { get; set; }

        /// <summary>
        /// Description of SubCategory ...
        /// this is a Resource Title ...
        /// </summary>
        /// <value></value>
        public string Description { get; set; }

        /// <summary>
        /// References List String Representation ...
        /// each SubCategory Referenced to Category ID which List here ...
        /// </summary>
        /// <value></value>
        public string References { get; set; }
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xCategoryService\Models\Entities\XSubCategory.cs

using xModels.Base;

namespace xCategoryService.Models.Entities
{
    public class XSubCategory : XBaseIntIDEntity
    {
        /// <summary>
        /// Title of SubCategory ...
        /// this is a Resource Title ...
        /// </summary>
        /// <value></value>
        public string Title { get; set; }

        /// <summary>
        /// Description of SubCategory ...
        /// this is a Resource Title ...
        /// </summary>
        /// <value></value>
        public string Description { get; set; }

        /// <summary>
        /// References List String Representation ...
        /// each SubCategory Referenced to Category ID which List here ...
        /// </summary>
        /// <value></value>
        public string References { get; set; }
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xCategoryService\Providers\Dtos\XCategoryDtoHub.cs

using Microsoft.Extensions.Logging;
using xCategoryService.Interfaces.Dtos;
using xCategoryService.Models.Dtos;
using xCategoryService.Models.Entities;
using xPushService.Base;

namespace xCategoryService.Providers.Dtos
{
    public class XCategoryDtoHub : XBaseDtoHub<XCategory, XCategoryDto, int>, IXCategoryDtoHub
    {
        public XCategoryDtoHub(
            ILogger<XCategoryDtoHub> logger
        ) : base(logger)
        { }
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xCategoryService\Providers\Dtos\XCategoryRepositoryService.cs

using System.Collections.Generic;
using AutoMapper;
using xCategoryService.Interfaces.Dtos;
using xCategoryService.Interfaces.Entities;
using xCategoryService.Models.Dtos;
using xCategoryService.Models.Entities;
using xDataService.Providers;

namespace xCategoryService.Providers.Dtos
{
    public class XCategoryRepositoryService : XBaseRepositoryService<XCategory, XCategoryDto, int>, IXCategoryRepositoryService
    {
        public XCategoryRepositoryService(
            IXCategoryRepository repository,
            IEnumerable<Profile> mapperProfiles = null
        ) : base(
            repository,
            mapperProfiles
        )
        { }
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xCategoryService\Providers\Dtos\XCategoryServiceProvider.cs

using Microsoft.AspNetCore.SignalR;
using xCategoryService.Interfaces.Dtos;
using xCategoryService.Models.Dtos;
using xCategoryService.Models.Entities;
using xDataService.Configuration;
using xIdentityService.Interfaces;
using xPushService.Base;

namespace xCategoryService.Providers.Dtos
{
    public class XCategoryServiceProvider : XBaseDtoProvider<XCategory, XCategoryDto, int, XCategoryDtoHub>, IXCategoryServiceProvider
    {
        public XCategoryServiceProvider(
            IHubContext<XCategoryDtoHub> hub,
            XDataServiceConfiguration dataConfiguration,
            IXCategoryRepositoryService service,
            IXIdentityProvider identityProvider = null
        ) : base(
            hub,
            dataConfiguration,
            service,
            identityProvider
        )
        { }
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xCategoryService\Providers\Dtos\XSubCategoryDtoHub.cs

using Microsoft.Extensions.Logging;
using xCategoryService.Interfaces.Dtos;
using xCategoryService.Models.Dtos;
using xCategoryService.Models.Entities;
using xPushService.Base;

namespace xCategoryService.Providers.Dtos
{
    public class XSubCategoryDtoHub : XBaseDtoHub<XSubCategory, XSubCategoryDto, int>, IXSubCategoryDtoHub
    {
        public XSubCategoryDtoHub(
            ILogger<XSubCategoryDtoHub> logger
        ) : base(logger)
        { }
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xCategoryService\Providers\Dtos\XSubCategoryRepositoryService.cs

using System.Collections.Generic;
using AutoMapper;
using xCategoryService.Interfaces.Dtos;
using xCategoryService.Interfaces.Entities;
using xCategoryService.Models.Dtos;
using xCategoryService.Models.Entities;
using xDataService.Providers;

namespace xCategoryService.Providers.Dtos
{
    public class XSubCategoryRepositoryService : XBaseRepositoryService<XSubCategory, XSubCategoryDto, int>, IXSubCategoryRepositoryService
    {
        public XSubCategoryRepositoryService(
            IXSubCategoryRepository repository, 
            IEnumerable<Profile> mapperProfiles = null
        ) : base(
            repository, 
            mapperProfiles
        )
        { }
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xCategoryService\Providers\Dtos\XSubCategoryServiceProvider.cs

using Microsoft.AspNetCore.SignalR;
using xCategoryService.Interfaces.Dtos;
using xCategoryService.Models.Dtos;
using xCategoryService.Models.Entities;
using xDataService.Configuration;
using xIdentityService.Interfaces;
using xPushService.Base;

namespace xCategoryService.Providers.Dtos
{
    public class XSubCategoryServiceProvider : XBaseDtoProvider<XSubCategory, XSubCategoryDto, int, XSubCategoryDtoHub>, IXSubCategoryServiceProvider
    {
        public XSubCategoryServiceProvider(
            IHubContext<XSubCategoryDtoHub> hub,
            XDataServiceConfiguration dataConfiguration,
            IXSubCategoryRepositoryService service,
            IXIdentityProvider identityProvider = null
        ) : base(
            hub,
            dataConfiguration,
            service,
            identityProvider
        )
        { }
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xCategoryService\Providers\Entities\XCategoryEFRepository.cs

using xCategoryService.Interfaces.Entities;
using xCategoryService.Models.Entities;
using xDataService.Configuration;
using xDataService.Db;
using xDataService.Interfaces;
using xDataService.Providers;

namespace xCategoryService.Providers.Entities
{
    public class XCategoryEFRepository<TContext> : XBaseEFRepository<XCategory, int, TContext>, IXCategoryRepository
    where TContext : XDbContext
    {
        public XCategoryEFRepository(
            IXUnitOfWorks<TContext> unitOfWorks,
            XDataServiceConfiguration configuration,
            IXCategoryKeyGenerator keyGenerator = null,
            IXCategoryRepositoryEvents baseRepositoryEvents = null
        ) : base(
            unitOfWorks,
            configuration,
            keyGenerator,
            baseRepositoryEvents
        )
        { }
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xCategoryService\Providers\Entities\XCategoryEntityHub.cs

using Microsoft.Extensions.Logging;
using xCategoryService.Interfaces.Entities;
using xCategoryService.Models.Entities;
using xPushService.Base;

namespace xCategoryService.Providers.Entities
{
    public class XCategoryEntityHub : XBaseEntityHub<XCategory, int>, IXCategoryEntityHub
    {
        public XCategoryEntityHub(
            ILogger<XCategoryEntityHub> logger
        ) : base(logger)
        { }
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xCategoryService\Providers\Entities\XCategoryInMemoryRepository.cs

using xCategoryService.Interfaces.Entities;
using xCategoryService.Models.Entities;
using xDataService.Configuration;
using xDataService.Providers;

namespace xCategoryService.Providers.Entities
{
    public class XCategoryInMemoryRepository : XBaseInMemoryRepository<XCategory, int>, IXCategoryRepository
    {
        public XCategoryInMemoryRepository(
            XDataServiceConfiguration configuration,
            IXCategoryKeyGenerator keyGenerator = null,
            IXCategoryRepositoryEvents baseRepositoryEvents = null
        ) : base(
            configuration,
            keyGenerator,
            baseRepositoryEvents
        )
        { }
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xCategoryService\Providers\Entities\XCategoryKeyGenerator.cs

using xCategoryService.Interfaces.Entities;
using xCategoryService.Models.Entities;
using xDataService.Providers;

namespace xCategoryService.Providers.Entities
{
    public class XCategoryKeyGenerator : XIntKeyGenerator<XCategory>, IXCategoryKeyGenerator
    { }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xCategoryService\Providers\Entities\XCategoryMongoRepository.cs

using xCategoryService.Interfaces.Entities;
using xCategoryService.Models.Entities;
using xDataService.Configuration;
using xDataService.Providers;

namespace xCategoryService.Providers.Entities
{
    public class XCategoryMongoRepository : XBaseMongoRepository<XCategory, int>, IXCategoryRepository
    {
        public XCategoryMongoRepository(
            XDataBaseConfiguration dbConfiguration,
            XDataServiceConfiguration configuration,
            string collectionName = null,
            IXCategoryKeyGenerator keyGenerator = null,
            IXCategoryRepositoryEvents baseRepositoryEvents = null
        ) : base(
            dbConfiguration,
            configuration,
            collectionName,
            keyGenerator,
            baseRepositoryEvents
        )
        { }
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xCategoryService\Providers\Entities\XCategoryRepositoryEvents.cs

using xCategoryService.Interfaces.Entities;
using xCategoryService.Models.Entities;
using xDataService.Providers;

namespace xCategoryService.Providers.Entities
{
    public class XCategoryRepositoryEvents : XBaseRepositoryEvents<XCategory>, IXCategoryRepositoryEvents
    { }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xCategoryService\Providers\Entities\XCategoryRepositoryProvider.cs

using Microsoft.AspNetCore.SignalR;
using xCategoryService.Interfaces.Entities;
using xCategoryService.Models.Entities;
using xDataService.Configuration;
using xIdentityService.Interfaces;
using xPushService.Base;

namespace xCategoryService.Providers.Entities
{
    public class XCategoryRepositoryProvider : XBaseEntityProvider<XCategory, int, XCategoryEntityHub>, IXCategoryRepositoryProvider
    {
        public XCategoryRepositoryProvider(
            IHubContext<XCategoryEntityHub> hub,
            IXCategoryRepository repository,
            XDataServiceConfiguration dataConfiguration,
            IXIdentityProvider identityProvider = null
        ) : base(
            hub,
            repository,
            dataConfiguration,
            identityProvider
        )
        { }
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xCategoryService\Providers\Entities\XCategorySeederBase.cs

using xCategoryService.Interfaces.Entities;
using xCategoryService.Models.Entities;
using xDataService.Configuration;
using xDataService.Providers;

namespace xCategoryService.Providers.Entities
{
    public abstract class XCategorySeederBase : XBaseDbSeeder<XCategory, int>, IXCategorySeeder
    {
        protected XCategorySeederBase(
            string entity,
            string database,
            IXCategoryRepository repository,
            XDataServiceConfiguration dataServiceConfiguration
        ) : base(
            entity,
            database,
            repository,
            dataServiceConfiguration
        )
        { }
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xCategoryService\Providers\Entities\XSubCategoryEFRepository.cs

using xCategoryService.Interfaces.Entities;
using xCategoryService.Models.Entities;
using xDataService.Configuration;
using xDataService.Db;
using xDataService.Interfaces;
using xDataService.Providers;

namespace xCategoryService.Providers.Entities
{
    public class XSubCategoryEFRepository<TContext> : XBaseEFRepository<XSubCategory, int, TContext>, IXSubCategoryRepository
    where TContext : XDbContext
    {
        public XSubCategoryEFRepository(
            IXUnitOfWorks<TContext> unitOfWorks,
            XDataServiceConfiguration configuration,
            IXSubCategoryKeyGenerator keyGenerator = null,
            IXSubCategoryRepositoryEvents baseRepositoryEvents = null
        ) : base(
            unitOfWorks,
            configuration,
            keyGenerator,
            baseRepositoryEvents
        )
        { }
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xCategoryService\Providers\Entities\XSubCategoryEntityHub.cs

using Microsoft.Extensions.Logging;
using xCategoryService.Interfaces.Entities;
using xCategoryService.Models.Entities;
using xPushService.Base;

namespace xCategoryService.Providers.Entities
{
    public class XSubCategoryEntityHub : XBaseEntityHub<XSubCategory, int>, IXSubCategoryEntityHub
    {
        public XSubCategoryEntityHub(
            ILogger<XSubCategoryEntityHub> logger
        ) : base(logger)
        { }
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xCategoryService\Providers\Entities\XSubCategoryInMemoryRepository.cs

using xCategoryService.Interfaces.Entities;
using xCategoryService.Models.Entities;
using xDataService.Configuration;
using xDataService.Providers;

namespace xCategoryService.Providers.Entities
{
    public class XSubCategoryInMemoryRepository : XBaseInMemoryRepository<XSubCategory, int>, IXSubCategoryRepository
    {
        public XSubCategoryInMemoryRepository(
            XDataServiceConfiguration configuration,
            IXSubCategoryKeyGenerator keyGenerator = null,
            IXSubCategoryRepositoryEvents baseRepositoryEvents = null
        ) : base(
            configuration,
            keyGenerator,
            baseRepositoryEvents
        )
        { }
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xCategoryService\Providers\Entities\XSubCategoryKeyGenerator.cs

using xCategoryService.Interfaces.Entities;
using xCategoryService.Models.Entities;
using xDataService.Providers;

namespace xCategoryService.Providers.Entities
{
    public class XSubCategoryKeyGenerator : XIntKeyGenerator<XSubCategory>, IXSubCategoryKeyGenerator
    { }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xCategoryService\Providers\Entities\XSubCategoryMongoRepository.cs

using xCategoryService.Interfaces.Entities;
using xCategoryService.Models.Entities;
using xDataService.Configuration;
using xDataService.Providers;

namespace xCategoryService.Providers.Entities
{
    public class XSubCategoryMongoRepository : XBaseMongoRepository<XSubCategory, int>, IXSubCategoryRepository
    {
        public XSubCategoryMongoRepository(
            XDataBaseConfiguration dbConfiguration,
            XDataServiceConfiguration configuration,
            string collectionName = null,
            IXSubCategoryKeyGenerator keyGenerator = null,
            IXSubCategoryRepositoryEvents baseRepositoryEvents = null
        ) : base(
            dbConfiguration,
            configuration,
            collectionName,
            keyGenerator,
            baseRepositoryEvents
        )
        { }
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xCategoryService\Providers\Entities\XSubCategoryRepositoryEvents.cs

using xCategoryService.Interfaces.Entities;
using xCategoryService.Models.Entities;
using xDataService.Providers;

namespace xCategoryService.Providers.Entities
{
    public class XSubCategoryRepositoryEvents : XBaseRepositoryEvents<XSubCategory>, IXSubCategoryRepositoryEvents
    { }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xCategoryService\Providers\Entities\XSubCategoryRepositoryProvider.cs

using Microsoft.AspNetCore.SignalR;
using xCategoryService.Interfaces.Entities;
using xCategoryService.Models.Entities;
using xDataService.Configuration;
using xIdentityService.Interfaces;
using xPushService.Base;

namespace xCategoryService.Providers.Entities
{
    public class XSubCategoryRepositoryProvider : XBaseEntityProvider<XSubCategory, int, XSubCategoryEntityHub>, IXSubCategoryRepositoryProvider
    {
        public XSubCategoryRepositoryProvider(
            IHubContext<XSubCategoryEntityHub> hub,
            IXSubCategoryRepository repository,
            XDataServiceConfiguration dataConfiguration,
            IXIdentityProvider identityProvider = null
        ) : base(
            hub,
            repository,
            dataConfiguration,
            identityProvider
        )
        { }
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xCategoryService\Providers\Entities\XSubCategorySeederBase.cs

using xCategoryService.Interfaces.Entities;
using xCategoryService.Models.Entities;
using xDataService.Configuration;
using xDataService.Providers;

namespace xCategoryService.Providers.Entities
{
    public abstract class XSubCategorySeederBase : XBaseDbSeeder<XSubCategory, int>, IXSubCategorySeeder
    {
        protected XSubCategorySeederBase(
            string entity,
            string database,
            IXSubCategoryRepository repository,
            XDataServiceConfiguration dataServiceConfiguration
        ) : base(
            entity,
            database,
            repository,
            dataServiceConfiguration
        )
        { }
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xCategoryService\Providers\GraphQL\XCategoryGraphQLTypeHelper.cs

using xCategoryService.Constants;
using xCategoryService.Interfaces.Entities;
using xCategoryService.Models.Entities;
using xDataService.Configuration;
using xDataService.GraphQL;

namespace xCategoryService.Providers.GraphQL
{
    public class XCategoryGraphQLTypeHelper : XBaseGraphQLTypeHelper<XCategory, int>, IXCategoryGraphQLTypeHelper
    {
        public XCategoryGraphQLTypeHelper(
            XDataServiceConfiguration configuration
        ) : base(configuration)
        { }

        public override string GetInQueryCollectionName()
        {
            return XCategoryServiceConstants.XCategoryCollectionName;
        }

        public override string GetInQuerySingleName()
        {
            return XCategoryServiceConstants.XCategorySingleName;
        }
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xCategoryService\Providers\GraphQL\XCategoryGraphQuery.cs

using GraphQL.Types;
using xCategoryService.Interfaces.Entities;
using xCategoryService.Models.Entities;
using xDataService.Configuration;
using xDataService.GraphQL;

namespace xCategoryService.Providers.GraphQL
{
    public class XCategoryGraphQuery : XBaseGraphQLQuery<XCategory, int, XCategoryGraphType, IntGraphType>
    {
        public XCategoryGraphQuery(
            XDataServiceConfiguration configuration,
            IXCategoryRepository repository,
            IXCategoryGraphQLTypeHelper helper
        ) : base(
            configuration,
            repository,
            helper
        )
        { }
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xCategoryService\Providers\GraphQL\XCategoryGraphSchema.cs

using System;
using GraphQL.Types;

namespace xCategoryService.Providers.GraphQL
{
    public class XCategoryGraphSchema : Schema
    {
        public XCategoryGraphSchema(IServiceProvider services) : base(services)
        {
            Query = (XCategoryGraphQuery)services.GetService(typeof(XCategoryGraphQuery));
        }
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xCategoryService\Providers\GraphQL\XCategoryGraphType.cs

using xCategoryService.Models.Entities;
using xDataService.GraphQL;

namespace xCategoryService.Providers.GraphQL
{
    public class XCategoryGraphType : XBaseGraphObjectType<XCategory, int>
    {
        public XCategoryGraphType() : base()
        {
            Field(x => x.Title);
            Field(x => x.Description);
            Field(x => x.References);
        }
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xCategoryService\Providers\GraphQL\XSubCategoryGraphQLTypeHelper.cs

using xCategoryService.Constants;
using xCategoryService.Interfaces.Entities;
using xCategoryService.Models.Entities;
using xDataService.Configuration;
using xDataService.GraphQL;

namespace xCategoryService.Providers.GraphQL
{
    public class XSubCategoryGraphQLTypeHelper : XBaseGraphQLTypeHelper<XSubCategory, int>, IXSubCategoryGraphQLTypeHelper
    {
        public XSubCategoryGraphQLTypeHelper(
            XDataServiceConfiguration configuration
        ) : base(configuration)
        { }

        public override string GetInQueryCollectionName()
        {
            return XCategoryServiceConstants.XSubCategoryCollectionName;
        }

        public override string GetInQuerySingleName()
        {
            return XCategoryServiceConstants.XSubCategorySingleName;
        }
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xCategoryService\Providers\GraphQL\XSubCategoryGraphQuery.cs

using GraphQL.Types;
using xCategoryService.Interfaces.Entities;
using xCategoryService.Models.Entities;
using xDataService.Configuration;
using xDataService.GraphQL;

namespace xCategoryService.Providers.GraphQL
{
    public class XSubCategoryGraphQuery : XBaseGraphQLQuery<XSubCategory, int, XSubCategoryGraphType, IntGraphType>
    {
        public XSubCategoryGraphQuery(
            XDataServiceConfiguration configuration,
            IXSubCategoryRepository repository,
            IXSubCategoryGraphQLTypeHelper helper
        ) : base(
            configuration,
            repository,
            helper
        )
        { }
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xCategoryService\Providers\GraphQL\XSubCategoryGraphSchema.cs

using System;
using GraphQL.Types;

namespace xCategoryService.Providers.GraphQL
{
    public class XSubCategoryGraphSchema : Schema
    {
        public XSubCategoryGraphSchema(IServiceProvider services) : base(services)
        {
            Query = (XSubCategoryGraphQuery)services.GetService(typeof(XSubCategoryGraphQuery));
        }
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xCategoryService\Providers\GraphQL\XSubCategoryGraphType.cs

using xCategoryService.Models.Entities;
using xDataService.GraphQL;

namespace xCategoryService.Providers.GraphQL
{
    public class XSubCategoryGraphType : XBaseGraphObjectType<XSubCategory, int>
    {
        public XSubCategoryGraphType() : base()
        {
            Field(x => x.Title);
            Field(x => x.Description);
            Field(x => x.References);
        }
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xCategoryService\Providers\XBaseCategoryProvider.cs

using System.Collections.Generic;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using xCategoryService.Extensions;
using xCategoryService.Interfaces;
using xCategoryService.Interfaces.Dtos;
using xCategoryService.Models.Dtos;
using xCommons.Extensions;
using xDataService.Extensions;
using xDataService.Models;
using xExceptions.Constants;
using xModels.Dtos;

namespace xCategoryService.Providers
{
    public abstract class XBaseCategoryProvider<TKey> : IXBaseCategoryProvider<TKey>
    {
        //
        #region Props ...
        /// <summary>
        /// Provider Identifier ...
        /// </summary>
        public string Provider { get; }

        /// <summary>
        /// Tag Provider for Maipulating Tags ...
        /// </summary>
        public IXCategoryServiceProvider CategoryProvider { get; }
        #endregion

        //
        #region Constructor ...
        public XBaseCategoryProvider(
            string providedFor,
            IXCategoryServiceProvider categoryProvider
        )
        {
            //
            Provider = providedFor;
            CategoryProvider = categoryProvider;
        }
        #endregion

        //
        #region Referenced Actions ...
        /// <summary>
        /// Get Specified Indexed Reference for Specific Provided ID ...
        /// </summary>
        /// <param name="providedForId"></param>
        /// <param name="forIndex"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public async Task<XCategoryDto> GetReference(
            TKey providedForId,
            int forIndex = 0,
            CancellationToken cancellationToken = default
        )
        {
            //
            // Validate ...
            if (providedForId.IsNull())
            {
                XException.InvalidArgs.Throw();
            }

            //
            // Normalize ...
            if (forIndex < 0)
            {
                forIndex = 0;
            }

            //
            // Retrieve Last Index ...
            var indexes = await GetReferencingIndexes(
                providedForId: providedForId,
                cancellationToken: cancellationToken
            );
            var maxIndex = indexes.HasChild() ? indexes.Max() : -1;
            if (forIndex > maxIndex)
            {
                XException.NotFound.Throw();
            }

            //
            var indexedIdentifier = GetIndexedProvidedID(
                forIndex: forIndex,
                providedForId: providedForId
            );
            var result = await CategoryProvider.FindOneAsync(
                includeBuilder: null,
                ignoreSoftDeleteds: true,
                cancellationToken: cancellationToken,
                predicate: x => x.References.Contains(indexedIdentifier)
            );
            if (result.IsNullOrDefault())
            {
                XException.NotFound.Throw();
            }

            //
            return result;
        }

        /// <summary>
        /// Retrieve all Exists References of Specific Provided ID ...
        /// </summary>
        /// <param name="providedForId"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public async Task<IEnumerable<XCategoryDto>> GetAllReferences(
            TKey providedForId,
            CancellationToken cancellationToken = default
        )
        {
            //
            // Validate ...
            if (providedForId.IsNull())
            {
                XException.InvalidArgs.Throw();
            }

            //
            var identifier = GetProvidedID(providedForId);
            var result = await CategoryProvider.FindManyAsync(
                orderBuilder: null,
                includeBuilder: null,
                ignoreSoftDeleteds: true,
                cancellationToken: cancellationToken,
                predicate: x => x.References.Contains(identifier)
            );

            //
            return result;
        }

        /// <summary>
        /// Extract all Referencing Models for Specified Key ...
        /// </summary>
        /// <param name="providedForId"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns> 
        public async Task<IEnumerable<XReference<TKey>>> GetAllReferencings(
            TKey providedForId,
            CancellationToken cancellationToken = default
        )
        {
            //
            // Validate ...
            var isValid =
                !providedForId.IsNull();
            if (!isValid)
            {
                XException.InvalidArgs.Throw();
            }

            //
            var identifier = GetProvidedID(providedForId);

            //
            var result = (await CategoryProvider.FindManyAsync(
                orderBuilder: null,
                includeBuilder: null,
                ignoreSoftDeleteds: true,
                cancellationToken: cancellationToken,
                predicate: x => x.References.Contains(identifier)
            ))
            .Select(x => x.References)
            .ToList()
            .SelectMany(x => x.ParseXReferenceList<TKey>())
            .Where(x => x.ProvidedFor == Provider && $"{x.ReferencedTo}" == $"{providedForId}")
            .OrderBy(x => x.Index)
            .AsEnumerable();

            //
            return result;
        }

        /// <summary>
        /// Count References ...
        /// </summary>
        /// <param name="providedForId"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public async Task<int> CountReferences(
            TKey providedForId,
            CancellationToken cancellationToken = default
        )
        {
            //
            // Validate ...
            var isValid = !providedForId.IsNull();
            if (!isValid)
            {
                XException.InvalidArgs.Throw();
            }

            //
            var identifier = GetProvidedID(providedForId);
            var result = (await CategoryProvider.FindManyAsync(
                orderBuilder: null,
                includeBuilder: null,
                ignoreSoftDeleteds: true,
                cancellationToken: cancellationToken,
                predicate: x => x.References.Contains(identifier)
            ))
            .Count();

            //
            return result;
        }

        /// <summary>
        /// Retrieve References of Specific Provided ID as Query ...
        /// </summary>
        /// <param name="query"></param>
        /// <param name="providedForId"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public async Task<XQueryResult<XCategoryDto>> QueryReferences(
            XQuery query,
            TKey providedForId,
            CancellationToken cancellationToken = default
        )
        {
            //
            // Validate ...
            if (query.IsNull() || providedForId.IsNull())
            {
                XException.InvalidArgs.Throw();
            }

            //
            var identifier = GetProvidedID(providedForId);
            var result = await CategoryProvider.QueryAsync(
                query: query,
                includeBuilder: null,
                ignoreSoftDeleteds: true,
                cancellationToken: cancellationToken,
                orderBuilder: x => x.OrderBy(y => y.Id),
                predicate: x => x.References.Contains(identifier)
            );

            //
            return result;
        }

        /// <summary>
        /// Add Reference a Model to Specific Provided ID ...
        /// </summary>
        /// <param name="model"></param>
        /// <param name="providedForId"></param>
        /// <param name="connectionId"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public async Task<bool> AddReference(
            XCategoryDto model,
            TKey providedForId,
            string connectionId = null,
            CancellationToken cancellationToken = default
        )
        {
            //
            var result = false;

            //
            // Validate ...
            result = !model.IsNullOrDefault() &&
                model.Id.IsValidIntId() &&
                !providedForId.IsNull();
            if (!result)
            {
                XException.InvalidArgs.Throw();
            }

            //
            // Check Model Exists ...
            result = await CategoryProvider.IsExistsAsync(model.Id);
            if (!result)
            {
                XException.NotFound.Throw();
            }

            //
            // Update Model by Retrieving ...
            model = await CategoryProvider.GetAsync(
                id: model.Id,
                includeBuilder: null,
                ignoreSoftDeleteds: true,
                cancellationToken: cancellationToken
            );

            //
            // Retrieve all References ...
            var references = await GetAllReferences(
                providedForId: providedForId,
                cancellationToken: cancellationToken
            );

            //
            // Check isReferenced or not ...
            result = references
                .Any(r =>
                    r.Id == model.Id &&
                    r.GetReferences()
                    .Any(rf =>
                        rf.ProvidedFor == Provider &&
                        rf.ReferencedTo == $"{providedForId}"));
            if (result)
            {
                return result;
            }

            //
            // Here means there is not any reference to ProvidedForId ...
            int forIndex = await CountReferences(
                providedForId: providedForId,
                cancellationToken: cancellationToken
            );
            var modelReferences = model.GetReferences();
            modelReferences.Add(new XReference<string>
            {
                Index = forIndex,
                ProvidedFor = Provider,
                ReferencedTo = $"{providedForId}"
            });
            modelReferences = modelReferences
                .OrderBy(r => r.Index)
                .ToList();
            model = model.UpdateReferences(modelReferences);

            //
            // Update Data Base ...
            model = await CategoryProvider.UpdateAsync(
                id: model.Id,
                item: model,
                saveChanges: true,
                connectionId: connectionId,
                cancellationToken: cancellationToken
            );
            result = !model.IsNullOrDefault();

            //
            return result;
        }

        /// <summary>
        /// Add Reference a Model to Specific XRefence<TKey/> ...
        /// </summary>
        /// <param name="model"></param>
        /// <param name="reference"></param>
        /// <param name="connectionId"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public async Task<bool> AddReference(
            XCategoryDto model,
            XReference<TKey> reference,
            string connectionId = null,
            CancellationToken cancellationToken = default
        )
        {
            //
            // Validate ...
            // Since other Validations Handled in Calling, we Ignore them here ...
            var result =
                !model.IsNull() &&
                !reference.IsNullOrDefault() &&
                reference.ProvidedFor == Provider &&
                !reference.ReferencedTo.IsNull();
            if (!result)
            {
                XException.InvalidArgs.Throw();
            }

            //
            result = await AddReference(
                model: model,
                connectionId: connectionId,
                cancellationToken: cancellationToken,
                providedForId: reference.ReferencedTo
            );

            //
            return result;
        }

        /// <summary>
        /// Remove Reference a Model for Specific Provided ID ...
        /// </summary>
        /// <param name="model"></param>
        /// <param name="providedForId"></param>
        /// <param name="connectionId"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public async Task<bool> RemoveReference(
            XCategoryDto model,
            TKey providedForId,
            string connectionId = null,
            CancellationToken cancellationToken = default
        )
        {
            //
            // Validate ...
            var result =
                !providedForId.IsNull() &&
                !model.IsNullOrDefault() &&
                model.Id.IsValidIntId();
            if (!result)
            {
                XException.InvalidArgs.Throw();
            }

            //
            // Retrieve Model ...
            model = await CategoryProvider.GetAsync(
                id: model.Id,
                includeBuilder: null,
                ignoreSoftDeleteds: true,
                cancellationToken: cancellationToken
            );
            result = !model.IsNullOrDefault();
            if (!result)
            {
                XException.NotFound.Throw();
            }

            //
            // Reading Referencing Indexes ...
            var indexes = await GetReferencingIndexes(
                providedForId: providedForId,
                cancellationToken: cancellationToken
            );

            //
            // Check Model Reference to ID ...
            var referencesCount = await CountReferences(
                providedForId: providedForId,
                cancellationToken: cancellationToken
            );
            result = referencesCount == 0;
            if (result)
            {
                //
                // There is not any Reference to Remove ...
                return result;
            }

            //
            // Check Model is Trully Referenced to ProvidedForId or not ...
            var reference = model
                .GetReferences()
                .FirstOrDefault(r =>
                    r.ProvidedFor == Provider &&
                    r.ReferencedTo == $"{providedForId}");
            result = !reference.IsNullOrDefault();
            if (!result)
            {
                XException.ActionFailed.Throw();
            }

            //
            // Remove Referenced Item from Model ...
            var modelReferences = model
                .GetReferences()
                .Where(r =>
                    !(r.ProvidedFor == Provider &&
                    r.ReferencedTo == $"{providedForId}"))
                .ToList();
            model = model.UpdateReferences(modelReferences);

            //
            // Update DataBase ...
            model = await CategoryProvider.UpdateAsync(
                item: model,
                id: model.Id,
                saveChanges: true,
                connectionId: connectionId,
                cancellationToken: cancellationToken
            );

            //
            result = !model.IsNullOrDefault();
            if (!result)
            {
                XException.ActionFailed.Throw();
            }

            //
            // Get Max Exists Indexes ...
            var maxIndex = indexes.Max();

            //
            // Here We Have to Re Arrange Indexed ...
            if (reference.Index < maxIndex)
            {
                //
                var startIndex = reference.Index + 1;
                for (int i = startIndex; i <= maxIndex; i++)
                {
                    //
                    var dto = await GetReference(
                        forIndex: i,
                        providedForId: providedForId,
                        cancellationToken: cancellationToken
                    );
                    if (!dto.IsNullOrDefault())
                    {
                        //
                        var dtoReferences = dto.GetReferences();
                        dtoReferences
                        .ToList()
                        .ForEach(iref =>
                        {
                            //
                            if (
                                iref.Index == i &&
                                iref.ProvidedFor == Provider &&
                                iref.ReferencedTo == reference.ReferencedTo
                            )
                            {
                                iref.Index = i - 1;
                            }
                        });
                        dto = dto.UpdateReferences(dtoReferences);

                        //
                        dto = await CategoryProvider.UpdateAsync(
                            item: dto,
                            id: dto.Id,
                            saveChanges: true,
                            connectionId: connectionId,
                            cancellationToken: cancellationToken
                        );
                    }
                }
            }

            //
            return result;
        }

        /// <summary>
        /// Remove Reference a Model for Specific XRefence<TKey/> ...
        /// </summary>
        /// <param name="model"></param>
        /// <param name="reference"></param>
        /// <param name="connectionId"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public async Task<bool> RemoveReference(
            XCategoryDto model,
            XReference<TKey> reference,
            string connectionId = null,
            CancellationToken cancellationToken = default
        )
        {
            //
            if (model.IsNullOrDefault() ||
                reference.IsNullOrDefault() ||
                reference.ReferencedTo.IsNull() ||
                reference.ProvidedFor != Provider)
            {
                XException.InvalidArgs.Throw();
            }

            //
            var result = await RemoveReference(
                model: model,
                connectionId: connectionId,
                cancellationToken: cancellationToken,
                providedForId: reference.ReferencedTo
            );

            //
            return result;
        }

        /// <summary>
        /// Remove All References to Specified Key ...
        /// </summary>
        /// <param name="providedForId"></param>
        /// <param name="connectionId"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public async Task<bool> RemoveReferences(
            TKey providedForId,
            string connectionId = null,
            CancellationToken cancellationToken = default
        )
        {
            //
            // Validate ...
            if (providedForId.IsNull())
            {
                XException.InvalidArgs.Throw();
            }

            //
            var result = false;
            var references = await GetAllReferences(
                providedForId: providedForId,
                cancellationToken: cancellationToken
            );
            if (!references.IsNull() && references.HasChild())
            {
                //
                foreach (var reference in references)
                {
                    //
                    // Remove Reference ...
                    var itemReferences = reference.GetReferences()
                        .Where(r =>
                            r.ProvidedFor != Provider ||
                            (r.ProvidedFor == Provider &&
                                r.ReferencedTo != $"{providedForId}"))
                        .ToList();
                    var updatedModel = reference.UpdateReferences(itemReferences);
                    updatedModel = await CategoryProvider.UpdateAsync(
                        saveChanges: true,
                        item: updatedModel,
                        id: updatedModel.Id,
                        connectionId: connectionId,
                        cancellationToken: cancellationToken
                    );
                    if (!updatedModel.IsNullOrDefault())
                    {
                        result = true;
                    }
                }
            }

            //
            return result;
        }
        #endregion

        //
        #region Private ...
        private string GetProvidedID(
            TKey providedForId,
            char splitter = '_'
        )
        {
            //
            // Validate ...
            if (providedForId.IsNull())
            {
                XException.InvalidArgs.Throw();
            }

            //
            var result = $"{Provider}{splitter}{providedForId}";
            return result;
        }

        private string GetIndexedProvidedID(
            TKey providedForId,
            int forIndex,
            char splitter = '_'
        )
        {
            //
            var result = $"{GetProvidedID(providedForId, splitter)}{splitter}{forIndex}";

            //
            return result;
        }

        private async Task<IEnumerable<int>> GetReferencingIndexes(
            TKey providedForId,
            CancellationToken cancellationToken = default
        )
        {
            //
            // Validate ...
            var isValid =
                !providedForId.IsNull();
            if (!isValid)
            {
                XException.InvalidArgs.Throw();
            }

            //
            var result = new List<int>();
            var referencings = await GetAllReferencings(
                providedForId: providedForId,
                cancellationToken: cancellationToken
            );
            isValid =
                !referencings.IsNull() &&
                referencings.HasChild();
            if (!isValid)
            {
                return result;
            }

            //
            result =
                referencings
                    .OrderBy(r => r.Index)
                    .Select(r => r.Index)
                    .ToList();

            //
            return result;
        }
        #endregion
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xCategoryService\Providers\XCategoryDescriptionResourceProvider.cs

using xCategoryService.Constants;
using xCategoryService.Interfaces;
using xStringService.Interfaces.Dtos;
using xStringService.Providers;

namespace xCategoryService.Providers
{
    public class XCategoryDescriptionResourceProvider : XBaseItemResourceProvider, IXCategoryDescriptionResourceProvider
    {
        public XCategoryDescriptionResourceProvider(
            IXStringServiceProvider stringProvider
        ) : base(
            stringProvider: stringProvider,
            item: XCategoryServiceConstants.CategoryDescriptionResourceIdentifier
        )
        { }
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xCategoryService\Providers\XCategoryEntityRegisterar.cs

using Microsoft.EntityFrameworkCore;
using xCategoryService.Configurations.Entities;
using xCategoryService.Models.Entities;
using xDataService.Interfaces;
using xDataService.Providers;

namespace xCategoryService.Providers
{
    public class XCategoryEntityRegisterar : XBaseEntityRegisterar, IXEntityRegisterar
    {
        public XCategoryEntityRegisterar()
        : base(nameof(XCategoryEntityRegisterar))
        {
            //
            // Add XCategory Entity ...
            AddEntity<XCategory, int>();
        }

        /// <summary>
        /// Configure Entities ...
        /// </summary>
        /// <param name="modelBuilder"></param>
        public override void ConfigureEntities(ModelBuilder modelBuilder)
        {
            //
            // Configure Entity Using Provided ...
            modelBuilder
                .ApplyConfigurationsFromAssembly(typeof(XCategoryEntityConfiguration).Assembly);

            //
            base.ConfigureEntities(modelBuilder);
        }
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xCategoryService\Providers\XCategoryProvider.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Runtime.CompilerServices;
using System.Threading;
using System.Threading.Tasks;
using xCategoryService.Interfaces;
using xCategoryService.Interfaces.Dtos;
using xCategoryService.Models.Dtos;
using xCategoryService.Models.Entities;
using xCategoryService.Providers.Dtos;
using xCommons.Configurations;
using xCommons.Extensions;
using xExceptions.Constants;
using xIdentityModels.Models;
using xModels.Dtos;
using xDataService.Extensions;
using xPushService.Constants;
using xPushService.Providers;
using xDataService.Configuration;
using xDataService.Models;

namespace xCategoryService.Providers
{
    public class XCategoryProvider : XBaseProvided<XCategory, XCategoryDto, int, XCategoryDtoHub>, IXCategoryProvider
    {
        private readonly IXCategoryServiceProvider provider;
        private readonly XAppConfiguration appConfiguration;
        private readonly XDataServiceConfiguration dataServiceConfiguration;
        private readonly IXCategoryTitleResourceProvider titleResourceProvider;
        private readonly IXCategoryDescriptionResourceProvider descriptionResourceProvider;
        private readonly IXCategorySubCategoryReferenceProvider categorySubCategoryReferenceProvider;

        public string Provider => categorySubCategoryReferenceProvider.Provider;

        public XCategoryProvider(
            XAppConfiguration appConfiguration,
            IXCategoryServiceProvider provider,
            XDataServiceConfiguration dataServiceConfiguration,
            IXCategoryTitleResourceProvider titleResourceProvider,
            IXCategoryDescriptionResourceProvider descriptionResourceProvider,
            IXCategorySubCategoryReferenceProvider categorySubCategoryReferenceProvider
        ) : base(
            provider,
            permittedRoles: new string[] { }
        )
        {
            //
            this.provider = provider;
            this.appConfiguration = appConfiguration;
            this.titleResourceProvider = titleResourceProvider;
            this.dataServiceConfiguration = dataServiceConfiguration;
            this.descriptionResourceProvider = descriptionResourceProvider;
            this.categorySubCategoryReferenceProvider = categorySubCategoryReferenceProvider;
        }

        //
        #region Overrides ...
        public override bool IsOwned(
            XCategoryDto item,
            XUserClaimsInfoDto userInfo
        )
        {
            return !item.IsNullOrDefault();
        }

        public override bool IsOwned(
            XCategory item,
            XUserClaimsInfoDto userInfo
        )
        {
            return !item.IsNullOrDefault();
        }
        #endregion

        //
        #region Actions ...
        /// <summary>
        /// Check Has Specified Locale or not ...
        /// </summary>
        /// <param name="id"></param>
        /// <param name="language"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public async Task<bool> HasLocale(
            int id,
            string language,
            CancellationToken cancellationToken = default
        )
        {
            //
            // Validate ...
            var isValid =
                id.IsValidIntId() &&
                !language.IsNullOrEmpty();
            if (!isValid)
            {
                XException.InvalidArgs.Throw();
            }

            //
            // Retrieve Resource ...
            var resource = await GetResource(
                id: id,
                cancellationToken: cancellationToken
            );

            //
            // Check Result ...
            var result =
                !resource.IsNullOrDefault() &&
                resource.Titles.Locales
                    .Any(x => x.Language
                        .Equals(language, System.StringComparison.InvariantCultureIgnoreCase));

            //
            return result;
        }

        /// <summary>
        /// Load an Item by all of it's Related Translations ...
        /// </summary>
        /// <param name="id"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public async Task<XCategoryResourceDto> GetResource(
            int id,
            CancellationToken cancellationToken = default
        )
        {
            //
            var item = await Get(
                id: id,
                includeBuilder: null,
                cancellationToken: cancellationToken
            );
            var titleResource = await titleResourceProvider.GetResource(
                identifier: id,
                cancellationToken: cancellationToken
            );
            var descriptionResource = await descriptionResourceProvider.GetResource(
                identifier: id,
                cancellationToken: cancellationToken
            );

            //
            var result = new XCategoryResourceDto
            {
                Item = item,
                Titles = titleResource,
                Descriptions = descriptionResource
            };

            //
            return result;
        }

        /// <summary>
        /// Add an Item for Specified Language ...
        /// </summary>
        /// <param name="item"></param>
        /// <param name="language"></param>
        /// <param name="connectionId"></param>
        /// <param name="userInfo"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>        
        public async Task<XCategoryResourceDto> Add(
            XCategoryDto item,
            string language = null,
            string connectionId = null,
            XUserClaimsInfoDto userInfo = null,
            CancellationToken cancellationToken = default
        )
        {
            //
            // Normalize ...
            language =
                !language.IsNullOrEmpty()
                    ? language
                    : appConfiguration.DefaultLanguage;

            //
            // Validate ...
            var isValid = !item.IsNullOrDefault();
            if (!isValid)
            {
                XException.InvalidArgs.Throw();
            }

            //
            // Check Permission ...
            isValid = HasPermision(userInfo);
            if (!isValid)
            {
                XException.NotAllowed.Throw();
            }

            //
            var id = -1;
            try
            {
                //
                var title = item.Title;
                var description = item.Description;

                //
                // Add Item Pure for ID Generating ...
                item = await base.Add(
                    item: item,
                    userInfo: userInfo,
                    connectionId: null, // Since here We dont want notification ...
                    cancellationToken: cancellationToken
                );
                isValid = !item.IsNullOrDefault();
                if (!isValid)
                {
                    XException.ActionFailed.Throw();
                }

                //
                id = item.Id;
                var titleResource = await titleResourceProvider
                    .AddOrUpdateLocale(
                        identifier: id,
                        locale: new XLocaleResourceDto
                        {
                            Value = title,
                            Language = language
                        },
                        connectionId: connectionId,
                        cancellationToken: cancellationToken
                    );
                var descriptionResource = await descriptionResourceProvider
                    .AddOrUpdateLocale(
                        identifier: id,
                        locale: new XLocaleResourceDto
                        {
                            Value = description,
                            Language = language
                        },
                        connectionId: connectionId,
                        cancellationToken: cancellationToken
                    );

                //
                // Update Category Dto ...
                item.Title = titleResource.Resource;
                item.Description = descriptionResource.Resource;
                item = await base.Update(
                    id: id,
                    item: item,
                    userInfo: userInfo,
                    connectionId: null,
                    cancellationToken: cancellationToken
                );
            }
            catch
            {
                XException.InvalidArgs.Throw();
            }

            //  
            // Validate Id ...
            isValid = id.IsValidIntId();
            if (!isValid)
            {
                XException.ActionFailed.Throw();
            }

            //
            // Retrieve Category Resourv=ce ...
            var result = await GetResource(
                id: id,
                cancellationToken: cancellationToken
            );

            //
            // Sending Push Notification ...
            isValid =
                isValid &&
                !result.IsNullOrDefault();
            if (isValid)
            {
                //
                await provider.SendPush(
                    connectionId: connectionId,
                    cancellationToken: cancellationToken,
                    payLoad: result.ToJSON(camelCase: true),
                    action: XBaseEntityHubAction.Add.GetStringValue()
                );
            }

            //
            return result;
        }

        /// <summary>
        /// Add Category by It's Locales ...
        /// </summary>
        /// <param name="item"></param>
        /// <param name="connectionId"></param>
        /// <param name="userInfo"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public async Task<XCategoryResourceDto> AddResource(
            XCategoryResourceDto item,
            string connectionId = null,
            XUserClaimsInfoDto userInfo = null,
            CancellationToken cancellationToken = default
        )
        {
            //
            // Validate ...
            var isValid =
                !item.IsNullOrDefault() &&
                !item.Titles.IsNullOrDefault() &&
                item.Titles.Locales.HasChild() &&
                !item.Titles.Locales.Any(il =>
                    il.Language.IsNullOrEmpty() ||
                    il.Value.IsNullOrEmpty());
            if (!isValid)
            {
                XException.InvalidArgs.Throw();
            }

            //
            // Normalize ...
            if (item.Item.IsNullOrDefault())
            {
                item.Item = new XCategoryDto();
            }

            //
            // Check Permission ...
            isValid = HasPermision(userInfo);
            if (!isValid)
            {
                XException.NotAllowed.Throw();
            }

            //
            var id = -1;
            try
            {
                //
                // Add Category for ID Generation ...
                item.Item = await base.Add(
                    item: item.Item,
                    userInfo: userInfo,
                    connectionId: null, // Since here We dont want notification ...
                    cancellationToken: cancellationToken
                );
                isValid = !item.Item.IsNullOrDefault();
                if (!isValid)
                {
                    XException.ActionFailed.Throw();
                }
                id = item.Item.Id;

                //                
                foreach (var il in item.Titles.Locales)
                {
                    //
                    var title = il.Value;
                    var language = il.Language;

                    //
                    var descriptionItem =
                        item.Descriptions.IsNullOrDefault() ||
                        !item.Descriptions.Locales.HasChild()
                        ? null
                        : item.Descriptions.Locales
                            .FirstOrDefault(ides =>
                                ides.Language
                                    .Equals(
                                        language,
                                        StringComparison.InvariantCultureIgnoreCase));
                    var description =
                        descriptionItem.IsNullOrDefault()
                        ? string.Empty
                        : descriptionItem.Value;

                    //
                    // Try to Add Resources ...
                    var titleResource = await titleResourceProvider
                        .AddOrUpdateLocale(
                            identifier: id,
                            locale: new XLocaleResourceDto
                            {
                                Value = title,
                                Language = language
                            },
                            connectionId: connectionId,
                            cancellationToken: cancellationToken
                        );
                    var descriptionResource = await descriptionResourceProvider
                        .AddOrUpdateLocale(
                            identifier: id,
                            locale: new XLocaleResourceDto
                            {
                                Value = description,
                                Language = language
                            },
                            connectionId: connectionId,
                            cancellationToken: cancellationToken
                        );

                    //
                    // Update Category Dto if not ...
                    if (item.Item.Title.IsNullOrEmpty() || 
                        !item.Item.Title
                        .Equals(
                            titleResource.Resource,
                            StringComparison.InvariantCultureIgnoreCase)
                    )
                    {
                        //
                        item.Item.Title = titleResource.Resource;
                        item.Item.Description = descriptionResource.Resource;
                        item.Item = await base.Update(
                            id: id,
                            item: item.Item,
                            userInfo: userInfo,
                            connectionId: null,
                            cancellationToken: cancellationToken
                        );
                    }
                }
            }
            catch
            {
                XException.InvalidArgs.Throw();
            }

            //  
            // Validate Id ...
            isValid = id.IsValidIntId();
            if (!isValid)
            {
                XException.ActionFailed.Throw();
            }

            //
            // Retrieve Category Resourv=ce ...
            var result = await GetResource(
                id: id,
                cancellationToken: cancellationToken
            );

            //
            // Sending Push Notification ...
            isValid =
                isValid &&
                !result.IsNullOrDefault();
            if (isValid)
            {
                //
                await provider.SendPush(
                    connectionId: connectionId,
                    cancellationToken: cancellationToken,
                    payLoad: result.ToJSON(camelCase: true),
                    action: XBaseEntityHubAction.Add.GetStringValue()
                );
            }

            //
            return result;
        }

        /// <summary>
        /// Remove Item for Specified Language ...
        /// </summary>
        /// <param name="id"></param>
        /// <param name="language">if null, Remove All</param>
        /// <param name="connectionId"></param>
        /// <param name="userInfo"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public async Task<XCategoryResourceDto> Remove(
            int id,
            string language = null,
            string connectionId = null,
            XUserClaimsInfoDto userInfo = null,
            CancellationToken cancellationToken = default
        )
        {
            //
            // Validate ...
            var isValid = id.IsValidIntId();
            if (!isValid)
            {
                XException.InvalidArgs.Throw();
            }

            //
            // Check Item Exists ...
            isValid = await IsExists(
                id: id,
                cancellationToken: cancellationToken
            );
            if (!isValid)
            {
                XException.NotFound.Throw();
            }

            //
            // Validate Locale if Provided ...
            isValid =
                language.IsNullOrEmpty() ||
                await HasLocale(
                    id: id,
                    language: language,
                    cancellationToken: cancellationToken
                );
            if (!isValid)
            {
                XException.NotFound.Throw();
            }

            //
            var result = await GetResource(
                id: id,
                cancellationToken: cancellationToken
            );
            if (language.IsNullOrEmpty())
            {
                //
                // Remove All ...

                //
                // Titles ...
                await titleResourceProvider.RemoveLocales(
                    identifier: id,
                    connectionId: null,
                    cancellationToken: cancellationToken
                );

                //
                // Descriptions ...
                await descriptionResourceProvider.RemoveLocales(
                    identifier: id,
                    connectionId: null,
                    cancellationToken: cancellationToken
                );

                //
                // Remove Entity ...
                await provider.RemoveAsync(
                    id: id,
                    softDelete: false,
                    saveChanges: true,
                    connectionId: null,
                    cancellationToken: cancellationToken
                );

                //
                isValid = true;
                result.Titles.Locales = [];
                result.Descriptions.Locales = [];
            }
            else
            {
                //
                // Remove Only One Locale, and if there is one, Remove all ...

                //
                // Remove Title if Exists ...
                isValid = await titleResourceProvider.HasLocale(
                    identifier: id,
                    language: language,
                    cancellationToken: cancellationToken
                );
                if (isValid)
                {
                    //
                    await titleResourceProvider.RemoveLocale(
                        identifier: id,
                        language: language,
                        connectionId: null,
                        cancellationToken: cancellationToken
                    );
                }

                //
                // Remove Description if Exists ...
                isValid = await descriptionResourceProvider.HasLocale(
                    identifier: id,
                    language: language,
                    cancellationToken: cancellationToken
                );
                if (isValid)
                {
                    //
                    await descriptionResourceProvider.RemoveLocale(
                        identifier: id,
                        language: language,
                        connectionId: null,
                        cancellationToken: cancellationToken
                    );
                }

                //
                // Retrieve Resource ...
                result = await GetResource(
                    id: id,
                    cancellationToken: cancellationToken
                );

                //
                // Check Has Locales ...
                isValid = result.Titles.Locales.HasChild();
                if (!isValid)
                {
                    //
                    // Remove Item ...
                    await provider.RemoveAsync(
                        id: id,
                        softDelete: false,
                        saveChanges: true,
                        connectionId: null,
                        cancellationToken: cancellationToken
                    );

                    //
                    result.Titles.Locales = [];
                    result.Descriptions.Locales = [];
                }

                //
                isValid = true;
            }

            //
            if (isValid)
            {
                //
                // Send Push ...
                await provider.SendPush(
                    connectionId: connectionId,
                    cancellationToken: cancellationToken,
                    payLoad: result.ToJSON(camelCase: true),
                    action:
                        result.Titles.Locales.HasChild()
                        ? "DeleteLocale"
                        : XBaseEntityHubAction.Delete.GetStringValue()
                );
            }

            //
            return result;
        }

        /// <summary>
        /// Update an Item for Specified Language ...
        /// </summary>
        /// <param name="id"></param>
        /// <param name="item"></param>
        /// <param name="language"></param>
        /// <param name="connectionId"></param>
        /// <param name="userInfo"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public async Task<XCategoryResourceDto> Update(
            int id,
            XCategoryDto item,
            string language = null,
            string connectionId = null,
            XUserClaimsInfoDto userInfo = null,
            CancellationToken cancellationToken = default
        )
        {
            //
            // Validate ...
            var isValid =
                id.IsValidIntId() &&
                !item.IsNullOrDefault() &&
                !language.IsNullOrEmpty() &&
                !item.Title.IsNullOrEmpty();
            if (!isValid)
            {
                XException.InvalidArgs.Throw();
            }

            //
            // Check Category Exists ...
            isValid = await IsExists(
                id: id,
                cancellationToken: cancellationToken
            );
            if (!isValid)
            {
                XException.NotFound.Throw();
            }

            //
            // Check Locale Exists ...
            isValid = await HasLocale(
                id: id,
                language: language,
                cancellationToken: cancellationToken
            );
            if (!isValid)
            {
                XException.NotFound.Throw();
            }

            //
            // Retrieve Category Dto for Validate Owining ...
            var dto = await Get(
                id: id,
                includeBuilder: null,
                cancellationToken: cancellationToken
            );

            //
            // Check Permission ...
            isValid =
                !dto.IsNullOrDefault() &&
                !userInfo.IsNullOrDefault() &&
                (IsOwned(
                    item: dto,
                    userInfo: userInfo
                ) || HasPermision(userInfo));
            if (!isValid)
            {
                XException.NotAllowed.Throw();
            }

            //
            // Retrieve Exists Item Resource ...
            var resource = await GetResource(
                id: id,
                cancellationToken: cancellationToken
            );

            //
            var titleUpdated = false;
            var descriptionUpdated = false;

            //
            // Update Title ...
            resource.Titles.Locales
                .ToList()
                .ForEach(tl =>
                {
                    //
                    if (tl.Language.Equals(language, StringComparison.InvariantCultureIgnoreCase))
                    {
                        //
                        titleUpdated = true;
                        tl.Value = item.Title;
                    }
                });

            //
            // Update Description ...
            resource.Descriptions.Locales
                .ToList()
                .ForEach(dl =>
                {
                    //
                    if (dl.Language.Equals(language, StringComparison.InvariantCultureIgnoreCase))
                    {
                        //
                        descriptionUpdated = true;
                        dl.Value = item.Description;
                    }
                });

            //
            // Validate Title and Description Updated ...
            isValid = titleUpdated && descriptionUpdated;
            if (!isValid)
            {
                XException.ActionFailed.Throw();
            }

            //
            resource = await Refresh(
                resource: resource,
                userInfo: userInfo,
                connectionId: connectionId,
                cancellationToken: cancellationToken
            );

            //
            return resource;
        }

        /// <summary>
        /// Refresh a Resource ...
        /// </summary>
        /// <param name="resource"></param>
        /// <param name="connectionId"></param>
        /// <param name="userInfo"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public async Task<XCategoryResourceDto> Refresh(
            XCategoryResourceDto resource,
            string connectionId = null,
            XUserClaimsInfoDto userInfo = null,
            CancellationToken cancellationToken = default
        )
        {
            //
            // Validate Args ...
            var isValid =
                !resource.IsNull();
            if (!isValid)
            {
                XException.InvalidArgs.Throw();
            }

            //
            // Check Permission ...
            isValid = HasPermision(userInfo);
            if (!isValid)
            {
                XException.NotAllowed.Throw();
            }

            //
            var id = -1;
            var isDelete = false;
            XCategoryResourceDto result = null;

            //
            // Check Item Exists ...
            XCategoryDto dto =
                (resource.Item.IsNullOrDefault() ||
                !resource.Item.Id.IsValidIntId())
                ? null
                : await Get(
                    id: resource.Item.Id,
                    includeBuilder: null,
                    cancellationToken: cancellationToken
            );
            var isExists = !dto.IsNullOrDefault();

            //
            // Do Referesh Based on Existance ...
            var isNew =
                !isExists &&
                (resource.Item.IsNullOrDefault() ||
                !resource.Item.Id.IsValidIntId());
            if (isNew)
            {
                //
                // Add ...
                // In this Senario, for Add a Category by Providing Resource 
                // the item must clean, either Title and Description, and tge Locales Provided by Resource
                // ust Contains Values ...
                // the Add Starts by Titles and only Items Add Which has Titles, since Title is Mandatory
                // and Description is Optional ...
                isValid =
                    //
                    // Resource ...
                    (resource.Item.IsNullOrDefault() ||
                    (!resource.Item.Id.IsValidIntId() &&
                    resource.Item.Title.IsNullOrEmpty() &&
                    resource.Item.Description.IsNullOrEmpty())) &&
                    //
                    // Titles ...
                    !resource.Titles.IsNullOrDefault() &&
                    resource.Titles.Locales.HasChild();
                if (!isValid)
                {
                    XException.InvalidArgs.Throw();
                }

                //
                // Add Temp Category ...
                var unique = Guid.NewGuid();
                var temp = new XCategoryDto
                {
                    Title = $"TmpT_{unique}",
                    Description = $"TmpD_{unique}",
                };
                temp = await provider.AddAsync(
                    item: temp,
                    saveChanges: true,
                    connectionId: null,
                    cancellationToken: cancellationToken
                );
                isValid =
                    !temp.IsNullOrDefault() &&
                    temp.Id.IsValidIntId();
                if (!isValid)
                {
                    XException.ActionFailed.Throw();
                }
                id = temp.Id;

                //
                // Update Title and Description ...
                var titleResource = titleResourceProvider.GetResourceTitle(id);
                var descriptionResource = descriptionResourceProvider.GetResourceTitle(id);
                temp.Title = titleResource;
                temp.Description = descriptionResource;
                temp = await provider.UpdateAsync(
                    id: id,
                    item: temp,
                    saveChanges: true,
                    connectionId: null,
                    cancellationToken: cancellationToken
                );

                //
                // Loop through Titles ...
                foreach (var locale in resource.Titles.Locales)
                {
                    //
                    // Add Or Update Locale ...
                    await titleResourceProvider.AddOrUpdateLocale(
                        locale: locale,
                        identifier: id,
                        connectionId: null,
                        cancellationToken: cancellationToken
                    );
                    var desLocale = resource.Descriptions.Locales.FirstOrDefault(
                        dl =>
                            dl.Language == locale.Language);
                    if (!desLocale.IsNullOrDefault())
                    {
                        //
                        // Add Descriptions ...
                        await descriptionResourceProvider.AddOrUpdateLocale(
                            identifier: id,
                            locale: desLocale,
                            connectionId: null,
                            cancellationToken: cancellationToken
                        );
                    }
                }
            }
            else if (isExists)
            {
                //
                // Re State ...
                id = resource.Item.Id;

                //
                // Try to Refresh Resource State ...

                //
                // Check Delete ...
                isDelete = !resource.Titles.Locales.HasChild();
                if (isDelete)
                {
                    //
                    // Handle Delete ...
                    await Remove(
                        id: id,
                        language: null,
                        userInfo: userInfo,
                        connectionId: null,
                        cancellationToken: cancellationToken
                    );
                }
                else
                {
                    //
                    // Handle Update ...
                    result = await GetResource(
                        id: id,
                        cancellationToken: cancellationToken
                    );

                    //
                    #region Remove ...
                    //
                    // Titles ...
                    var removeTitles = result.Titles.Locales.Where(
                        l => !resource.Titles.Locales.Any(r => r.Language.Equals(l.Language, System.StringComparison.InvariantCultureIgnoreCase))
                    );
                    foreach (var locale in removeTitles)
                    {
                        //
                        await titleResourceProvider.RemoveLocale(
                            identifier: id,
                            connectionId: null,
                            language: locale.Language,
                            cancellationToken: cancellationToken
                        );
                    }

                    //
                    // Descriptions ...
                    var removeDescriptions = result.Descriptions.Locales.Where(
                        l => !resource.Descriptions.Locales.Any(r => r.Language.Equals(l.Language, System.StringComparison.InvariantCultureIgnoreCase))
                    );
                    foreach (var locale in removeDescriptions)
                    {
                        //
                        await descriptionResourceProvider.RemoveLocale(
                            identifier: id,
                            connectionId: null,
                            language: locale.Language,
                            cancellationToken: cancellationToken
                        );
                    }
                    #endregion

                    //
                    #region Update ...
                    // 
                    // Titles ...
                    var updateTitles = result.Titles.Locales.Where(
                        l => resource.Titles.Locales.Any(r =>
                            r.Value
                                .Equals(l.Value, StringComparison.InvariantCultureIgnoreCase) &&
                            r.Language
                                .Equals(l.Language, StringComparison.InvariantCultureIgnoreCase)
                        )
                    );
                    foreach (var locale in updateTitles)
                    {
                        //
                        await titleResourceProvider.AddOrUpdateLocale(
                            identifier: id,
                            locale: locale,
                            connectionId: null,
                            cancellationToken: cancellationToken
                        );
                    }

                    //
                    // Descriptions ...
                    var updateDescriptions = result.Descriptions.Locales.Where(
                        l => resource.Descriptions.Locales.Any(r =>
                            r.Value
                                .Equals(l.Value, StringComparison.InvariantCultureIgnoreCase) &&
                            r.Language
                                .Equals(l.Language, StringComparison.InvariantCultureIgnoreCase))
                    );
                    foreach (var locale in updateDescriptions)
                    {
                        //
                        await descriptionResourceProvider.AddOrUpdateLocale(
                            identifier: id,
                            locale: locale,
                            connectionId: null,
                            cancellationToken: cancellationToken
                        );
                    }
                    #endregion

                    //
                    #region New ...
                    //
                    // Titles ...
                    var newTitles = resource.Titles.Locales.Where(
                        l => !result.Titles.Locales.Any(r => r.Language.Equals(l.Language, StringComparison.InvariantCultureIgnoreCase))
                    );
                    foreach (var locale in newTitles)
                    {
                        //
                        await titleResourceProvider.AddOrUpdateLocale(
                            identifier: id,
                            locale: locale,
                            connectionId: null,
                            cancellationToken: cancellationToken
                        );
                    }

                    //
                    // Descriptions ...
                    var newDescriptions = resource.Descriptions.Locales.Where(
                        l => !result.Descriptions.Locales.Any(r => r.Language.Equals(l.Language, StringComparison.InvariantCultureIgnoreCase))
                    );
                    foreach (var locale in newDescriptions)
                    {
                        //
                        await descriptionResourceProvider.AddOrUpdateLocale(
                            identifier: id,
                            locale: locale,
                            connectionId: null,
                            cancellationToken: cancellationToken
                        );
                    }
                    #endregion
                }
            }

            //
            // Validate Action ...
            isValid = id.IsValidIntId();
            if (!isValid)
            {
                XException.ActionFailed.Throw();
            }

            //
            // Get Result ...
            result =
                isDelete
                ? resource
                : await GetResource(
                id: id,
                cancellationToken: cancellationToken
            );
            isValid = !result.IsNullOrDefault();

            //
            // Send Notification ...
            if (isValid)
            {
                //
                await provider.SendPush(
                    connectionId: connectionId,
                    cancellationToken: cancellationToken,
                    payLoad: result.ToJSON(camelCase: true),
                    action: isNew
                        ? XBaseEntityHubAction.Add.GetStringValue()
                        : isDelete
                            ? XBaseEntityHubAction.Delete.GetStringValue()
                            : XBaseEntityHubAction.Update.GetStringValue()
                );
            }

            //
            return result;
        }

        /// <summary>
        /// Get All Resources as Async Enumerable ... 
        /// </summary>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public async IAsyncEnumerable<XCategoryResourceDto> GetAllResourcesAsAsyncEnumerable(
            [EnumeratorCancellation] CancellationToken cancellationToken = default
        )
        {
            //
            var enumerable = provider.GetAllAsAsyncEnumerable(
                includeBuilder: null,
                ignoreSoftDeleteds: true,
                cancellationToken: cancellationToken,
                orderBuilder: x => x.OrderBy(y => y.Id)
            );

            //
            await foreach (var dto in enumerable)
            {
                //
                if (cancellationToken.IsCancellationRequested)
                {
                    yield break;
                }

                //
                var resource = await GetResource(
                    id: dto.Id,
                    cancellationToken: cancellationToken
                );
                yield return resource;
            }
        }

        /// <summary>
        /// Get All Resources ...
        /// </summary>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public async Task<IEnumerable<XCategoryResourceDto>> GetAllResources(
            CancellationToken cancellationToken = default
        )
        {
            //
            var result = new List<XCategoryResourceDto>();

            //
            var enumerable = GetAllResourcesAsAsyncEnumerable(cancellationToken);
            await foreach (var item in enumerable)
            {
                //
                if (cancellationToken.IsCancellationRequested)
                {
                    break;
                }

                //
                result.Add(item);
            }

            //
            return result;
        }

        /// <summary>
        /// Find One Resource ...
        /// </summary>
        /// <param name="predicate"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public async Task<XCategoryResourceDto> FindOneResource(
            Expression<Func<XCategoryResourceDto, bool>> predicate = null,
            CancellationToken cancellationToken = default
        )
        {
            //
            var isApproved = false;
            XCategoryResourceDto result = null;
            var enumerable = GetAllResourcesAsAsyncEnumerable(cancellationToken);
            await foreach (var item in enumerable)
            {
                //
                // Check Cancellation Token ...
                if (cancellationToken.IsCancellationRequested)
                {
                    break;
                }

                //
                // Detect Predicate Condition ...
                isApproved = predicate.Compile()(item);
                if (isApproved)
                {
                    //
                    result = item;
                    break;
                }
            }

            //
            return result;
        }

        /// <summary>
        /// Find Many Resource ...
        /// </summary>
        /// <param name="predicate"></param>
        /// <param name="orderBuilder"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public async Task<IEnumerable<XCategoryResourceDto>> FindManyResource(
            Expression<Func<XCategoryResourceDto, bool>> predicate = null,
            Func<IQueryable<XCategoryResourceDto>, IOrderedQueryable<XCategoryResourceDto>> orderBuilder = null,
            CancellationToken cancellationToken = default
        )
        {
            //
            var isApproved = false;
            var result = new List<XCategoryResourceDto>();
            var enumerable = GetAllResourcesAsAsyncEnumerable(cancellationToken);
            await foreach (var item in enumerable)
            {
                //
                // Check Cancellation Token ...
                if (cancellationToken.IsCancellationRequested)
                {
                    break;
                }

                //
                // Detect Predicate Condition ...
                isApproved = predicate.Compile()(item);
                if (isApproved)
                {
                    result.Add(item);
                }
            }

            //
            // Apply Order ...
            if (!orderBuilder.IsNull())
            {
                //
                result =
                    orderBuilder(result.AsQueryable())
                    .ToList();
            }

            //
            return result;
        }

        /// <summary>
        /// Retrieve Resources by Query Pattern ...
        /// </summary>
        /// <param name="query"></param>
        /// <param name="predicate"></param>
        /// <param name="orderBuilder"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public async Task<XQueryResult<XCategoryResourceDto>> QueryResources(
            XQuery query = null,
            Expression<Func<XCategoryResourceDto, bool>> predicate = null,
            Func<IQueryable<XCategoryResourceDto>, IOrderedQueryable<XCategoryResourceDto>> orderBuilder = null,
            CancellationToken cancellationToken = default
        )
        {
            //
            // Normalize Query ...
            query = query.NormalizeQuery(dataServiceConfiguration);

            //
            var items = await FindManyResource(
                predicate: predicate,
                orderBuilder: orderBuilder,
                cancellationToken: cancellationToken
            );
            var totalItemsCount = items.Count();

            //
            // Apply Filter ...
            if (!query.Filter.IsNullOrEmpty())
            {
                //
                items = items
                    .ApplyFilter(query.Filter);
            }
            int filteredItemsCount = items.Count();

            //
            // Count Pages ...
            var totalPagesCount = query.CountPages(totalItemsCount);
            var filteredPagesCount = query.CountPages(filteredItemsCount);

            //
            // Apply Paging and Sorting ...
            if (totalItemsCount > 0 &&
                filteredItemsCount > 0)
            {
                //
                // Apply Sorting ...
                items = items
                    .ToList()
                    .ApplySorting(
                        query.SortBy,
                        query.IsAscending
                    );

                //
                // Apply Paging ...
                items = items
                    .ToList()
                    .ApplyPaging(
                        query.Page,
                        query.PageSize
                    );
            }

            //
            // Prepare Result ...
            var result = new XQueryResult<XCategoryResourceDto>
            {
                Page = query.Page,
                Items = [.. items],
                PageSize = query.PageSize,
                TotalPages = totalPagesCount,
                TotalItems = totalItemsCount,
                TotalFilteredPages = filteredPagesCount,
                TotalFilteredItems = filteredItemsCount
            };

            //
            return result;
        }
        #endregion

        //
        #region SubCategory References ...
        /// <summary>
        /// Get Specified Indexed Reference for Specific Provided ID ...
        /// </summary>
        /// <param name="providedForId"></param>
        /// <param name="forIndex"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public async Task<XCategoryDto> GetReference(
            int providedForId,
            int forIndex = 0,
            CancellationToken cancellationToken = default
        )
        {
            //
            var result = await categorySubCategoryReferenceProvider
                .GetReference(
                    forIndex: forIndex,
                    providedForId: providedForId,
                    cancellationToken: cancellationToken
                );

            //
            return result;
        }

        /// <summary>
        /// Retrieve all Exists References of Specific Provided ID ...
        /// </summary>
        /// <param name="providedForId"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public async Task<IEnumerable<XCategoryDto>> GetAllReferences(
            int providedForId,
            CancellationToken cancellationToken = default
        )
        {
            //
            var result = await categorySubCategoryReferenceProvider
                .GetAllReferences(
                    providedForId: providedForId,
                    cancellationToken: cancellationToken
                );

            //
            return result;
        }

        /// <summary>
        /// Extract all Referencing Models for Specified Key ...
        /// </summary>
        /// <param name="providedForId"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns> 
        public async Task<IEnumerable<XReference<int>>> GetAllReferencings(
            int providedForId,
            CancellationToken cancellationToken = default
        )
        {
            //
            var result = await categorySubCategoryReferenceProvider
                .GetAllReferencings(
                    providedForId: providedForId,
                    cancellationToken: cancellationToken
                );

            //
            return result;
        }

        /// <summary>
        /// Count References ...
        /// </summary>
        /// <param name="providedForId"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public async Task<int> CountReferences(
            int providedForId,
            CancellationToken cancellationToken = default
        )
        {
            //
            var result = await categorySubCategoryReferenceProvider
                .CountReferences(
                    providedForId: providedForId,
                    cancellationToken: cancellationToken
                );

            //
            return result;
        }

        /// <summary>
        /// Retrieve References of Specific Provided ID as Query ...
        /// </summary>
        /// <param name="query"></param>
        /// <param name="providedForId"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public async Task<XQueryResult<XCategoryDto>> QueryReferences(
            XQuery query,
            int providedForId,
            CancellationToken cancellationToken = default
        )
        {
            //
            var result = await categorySubCategoryReferenceProvider
                .QueryReferences(
                    query: query,
                    providedForId: providedForId,
                    cancellationToken: cancellationToken
                );

            //
            return result;
        }

        /// <summary>
        /// Add Reference a Model to Specific Provided ID ...
        /// </summary>
        /// <param name="model"></param>
        /// <param name="providedForId"></param>
        /// <param name="connectionId"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public async Task<bool> AddReference(
            XCategoryDto model,
            int providedForId,
            string connectionId = null,
            CancellationToken cancellationToken = default
        )
        {
            //
            var result = await categorySubCategoryReferenceProvider
                .AddReference(
                    model: model,
                    connectionId: connectionId,
                    providedForId: providedForId,
                    cancellationToken: cancellationToken
                );

            //
            return result;
        }

        /// <summary>
        /// Add Reference a Model to Specific XRefence<TKey/> ...
        /// </summary>
        /// <param name="model"></param>
        /// <param name="reference"></param>
        /// <param name="connectionId"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public async Task<bool> AddReference(
            XCategoryDto model,
            XReference<int> reference,
            string connectionId = null,
            CancellationToken cancellationToken = default
        )
        {
            //
            var result = await categorySubCategoryReferenceProvider
                .AddReference(
                    model: model,
                    reference: reference,
                    connectionId: connectionId,
                    cancellationToken: cancellationToken
                );

            //
            return result;
        }

        /// <summary>
        /// Remove Reference a Model for Specific Provided ID ...
        /// </summary>
        /// <param name="model"></param>
        /// <param name="providedForId"></param>
        /// <param name="connectionId"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public async Task<bool> RemoveReference(
            XCategoryDto model,
            int providedForId,
            string connectionId = null,
            CancellationToken cancellationToken = default
        )
        {
            //
            var result = await categorySubCategoryReferenceProvider
                .RemoveReference(
                    model: model,
                    connectionId: connectionId,
                    providedForId: providedForId,
                    cancellationToken: cancellationToken
                );

            //
            return result;
        }

        /// <summary>
        /// Remove Reference a Model for Specific XRefence<TKey/> ...
        /// </summary>
        /// <param name="model"></param>
        /// <param name="reference"></param>
        /// <param name="connectionId"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public async Task<bool> RemoveReference(
            XCategoryDto model,
            XReference<int> reference,
            string connectionId = null,
            CancellationToken cancellationToken = default
        )
        {
            //
            var result = await categorySubCategoryReferenceProvider
                .RemoveReference(
                    model: model,
                    reference: reference,
                    connectionId: connectionId,
                    cancellationToken: cancellationToken
                );

            //
            return result;
        }

        /// <summary>
        /// Remove All References to Specified Key ...
        /// </summary>
        /// <param name="providedForId"></param>
        /// <param name="connectionId"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public async Task<bool> RemoveReferences(
            int providedForId,
            string connectionId = null,
            CancellationToken cancellationToken = default
        )
        {
            //
            var result = await categorySubCategoryReferenceProvider
                .RemoveReferences(
                    connectionId: connectionId,
                    providedForId: providedForId,
                    cancellationToken: cancellationToken
                );

            //
            return result;
        }
        #endregion
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xCategoryService\Providers\XCategoryService.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Threading;
using System.Threading.Tasks;
using xCategoryService.Interfaces;
using xCategoryService.Models.Dtos;
using xIdentityModels.Models;
using xModels.Dtos;

namespace xCategoryService.Providers
{
    /// <summary>
    /// Completely Exported Service ...
    /// </summary>
    public class XCategoryService : IXCategoryService
    {
        private readonly IXCategoryProvider categoryProvider;
        private readonly IXSubCategoryProvider subCategoryProvider;

        public XCategoryService(
            IXCategoryProvider categoryProvider,
            IXSubCategoryProvider subCategoryProvider
        )
        {
            this.categoryProvider = categoryProvider;
            this.subCategoryProvider = subCategoryProvider;
        }

        //
        #region Category Provider ...
        /// <summary>
        /// Check Has Specified Locale or not ...
        /// </summary>
        /// <param name="id"></param>
        /// <param name="language"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public virtual async Task<bool> CategoryHasLocale(
            int id,
            string language,
            CancellationToken cancellationToken = default
        )
        {
            //
            return await categoryProvider
                .HasLocale(
                    id: id,
                    language: language,
                    cancellationToken: cancellationToken
            );
        }

        /// <summary>
        /// Load an Item by all of it's Related Translations ...
        /// </summary>
        /// <param name="id"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>        
        public virtual async Task<XCategoryResourceDto> GetCategoryResource(
            int id,
            CancellationToken cancellationToken = default
        )
        {
            //
            return await categoryProvider
                .GetResource(
                    id: id,
                    cancellationToken: cancellationToken
            );
        }

        /// <summary>
        /// Add Item for Specified Language ...
        /// </summary>
        /// <param name="item"></param>
        /// <param name="language"></param>
        /// <param name="connectionId"></param>
        /// <param name="userInfo"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public virtual async Task<XCategoryResourceDto> AddCategory(
            XCategoryDto item,
            string language = null,
            string connectionId = null,
            XUserClaimsInfoDto userInfo = null,
            CancellationToken cancellationToken = default
        )
        {
            //
            return await categoryProvider
                .Add(
                    item: item,
                    language: language,
                    userInfo: userInfo,
                    connectionId: connectionId,
                    cancellationToken: cancellationToken
            );
        }

        /// <summary>
        /// Add Item by It's Locales ...
        /// </summary>
        /// <param name="item"></param>
        /// <param name="connectionId"></param>
        /// <param name="userInfo"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public virtual async Task<XCategoryResourceDto> AddCategoryResource(
            XCategoryResourceDto item,
            string connectionId = null,
            XUserClaimsInfoDto userInfo = null,
            CancellationToken cancellationToken = default
        )
        {
            //
            return await categoryProvider
                .AddResource(
                    item: item,
                    userInfo: userInfo,
                    connectionId: connectionId,
                    cancellationToken: cancellationToken
            );
        }

        /// <summary>
        /// Remove Item for Specified Language ...
        /// </summary>
        /// <param name="id"></param>
        /// <param name="language">if null, Remove All</param>
        /// <param name="connectionId"></param>
        /// <param name="userInfo"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public virtual async Task<XCategoryResourceDto> RemoveCategory(
            int id,
            string language = null,
            string connectionId = null,
            XUserClaimsInfoDto userInfo = null,
            CancellationToken cancellationToken = default
        )
        {
            //
            return await categoryProvider
                .Remove(
                    id: id,
                    language: language,
                    userInfo: userInfo,
                    connectionId: connectionId,
                    cancellationToken: cancellationToken
            );
        }

        /// <summary>
        /// Update an Item for Specified Language ...
        /// </summary>
        /// <param name="id"></param>
        /// <param name="item"></param>
        /// <param name="language"></param>
        /// <param name="connectionId"></param>
        /// <param name="userInfo"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public virtual async Task<XCategoryResourceDto> UpdateCategory(
            int id,
            XCategoryDto item,
            string language = null,
            string connectionId = null,
            XUserClaimsInfoDto userInfo = null,
            CancellationToken cancellationToken = default
        )
        {
            //
            return await categoryProvider
                .Update(
                    id: id,
                    item: item,
                    language: language,
                    userInfo: userInfo,
                    connectionId: connectionId,
                    cancellationToken: cancellationToken
            );
        }

        /// <summary>
        /// Refresh a Resource ...
        /// </summary>
        /// <param name="resource"></param>
        /// <param name="connectionId"></param>
        /// <param name="userInfo"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public virtual async Task<XCategoryResourceDto> RefreshCategory(
            XCategoryResourceDto resource,
            string connectionId = null,
            XUserClaimsInfoDto userInfo = null,
            CancellationToken cancellationToken = default
        )
        {
            //
            return await categoryProvider
                .Refresh(
                    resource: resource,
                    userInfo: userInfo,
                    connectionId: connectionId,
                    cancellationToken: cancellationToken
            );
        }

        /// <summary>
        /// Get All Resources ...
        /// </summary>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public virtual async Task<IEnumerable<XCategoryResourceDto>> GetAllCategoryResources(
            CancellationToken cancellationToken = default
        )
        {
            //
            return await categoryProvider
                .GetAllResources(
                    cancellationToken: cancellationToken
            );
        }

        /// <summary>
        /// Find One Resource ...
        /// </summary>
        /// <param name="predicate"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public virtual async Task<XCategoryResourceDto> FindOneCategoryResource(
            Expression<Func<XCategoryResourceDto, bool>> predicate = null,
            CancellationToken cancellationToken = default
        )
        {
            //
            return await categoryProvider
                .FindOneResource(
                    predicate: predicate,
                    cancellationToken: cancellationToken
            );
        }

        /// <summary>
        /// Find Many Resource ...
        /// </summary>
        /// <param name="predicate"></param>
        /// <param name="orderBuilder"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public virtual async Task<IEnumerable<XCategoryResourceDto>> FindManyCategoryResource(
            Expression<Func<XCategoryResourceDto, bool>> predicate = null,
            Func<IQueryable<XCategoryResourceDto>, IOrderedQueryable<XCategoryResourceDto>> orderBuilder = null,
            CancellationToken cancellationToken = default
        )
        {
            //
            return await categoryProvider
                .FindManyResource(
                    predicate: predicate,
                    orderBuilder: orderBuilder,
                    cancellationToken: cancellationToken
            );
        }

        /// <summary>
        /// Retrieve Resources by Query Pattern ...
        /// </summary>
        /// <param name="query"></param>
        /// <param name="predicate"></param>
        /// <param name="orderBuilder"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public virtual async Task<XQueryResult<XCategoryResourceDto>> QueryCategoryResources(
            XQuery query = null,
            Expression<Func<XCategoryResourceDto, bool>> predicate = null,
            Func<IQueryable<XCategoryResourceDto>, IOrderedQueryable<XCategoryResourceDto>> orderBuilder = null,
            CancellationToken cancellationToken = default
        )
        {
            //
            return await categoryProvider
                .QueryResources(
                    query: query,
                    predicate: predicate,
                    orderBuilder: orderBuilder,
                    cancellationToken: cancellationToken
            );
        }

        /// <summary>
        /// Get All Resources as Async Enumerable ... 
        /// </summary>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public virtual IAsyncEnumerable<XCategoryResourceDto> GetAllCategoryResourcesAsAsyncEnumerable(
            CancellationToken cancellationToken = default
        )
        {
            //
            return categoryProvider
                .GetAllResourcesAsAsyncEnumerable(
                    cancellationToken: cancellationToken
            );
        }
        #endregion

        //
        #region SubCategory Provider ...
        /// <summary>
        /// Check Has Specified Locale or not ...
        /// </summary>
        /// <param name="id"></param>
        /// <param name="language"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public virtual async Task<bool> SubCategoryHasLocale(
            int id,
            string language,
            CancellationToken cancellationToken = default
        )
        {
            //
            return await subCategoryProvider
                .HasLocale(
                    id: id,
                    language: language,
                    cancellationToken: cancellationToken
            );
        }

        /// <summary>
        /// Load an Item by all of it's Related Translations ...
        /// </summary>
        /// <param name="id"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>        
        public virtual async Task<XSubCategoryResourceDto> GetSubCategoryResource(
            int id,
            CancellationToken cancellationToken = default
        )
        {
            //
            return await subCategoryProvider
                .GetResource(
                    id: id,
                    cancellationToken: cancellationToken
            );
        }

        /// <summary>
        /// Add Item for Specified Language ...
        /// </summary>
        /// <param name="item"></param>
        /// <param name="language"></param>
        /// <param name="connectionId"></param>
        /// <param name="userInfo"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public virtual async Task<XSubCategoryResourceDto> AddSubCategory(
            XSubCategoryDto item,
            string language = null,
            string connectionId = null,
            XUserClaimsInfoDto userInfo = null,
            CancellationToken cancellationToken = default
        )
        {
            //
            return await subCategoryProvider
                .Add(
                    item: item,
                    language: language,
                    userInfo: userInfo,
                    connectionId: connectionId,
                    cancellationToken: cancellationToken
            );
        }

        /// <summary>
        /// Add Item by it's Locales and Reference ...
        /// </summary>
        /// <param name="item"></param>
        /// <param name="connectionId"></param>
        /// <param name="userInfo"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public virtual async Task<XSubCategoryResourceDto> AddSubCategoryResource(
            XSubCategoryResourceDto item,
            string connectionId = null,
            XUserClaimsInfoDto userInfo = null,
            CancellationToken cancellationToken = default
        )
        {
            //
            return await subCategoryProvider
                .AddResource(
                    item: item,
                    userInfo: userInfo,
                    connectionId: connectionId,
                    cancellationToken: cancellationToken
            );
        }

        /// <summary>
        /// Remove Item for Specified Language ...
        /// </summary>
        /// <param name="id"></param>
        /// <param name="language">if null, Remove All</param>
        /// <param name="connectionId"></param>
        /// <param name="userInfo"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public virtual async Task<XSubCategoryResourceDto> RemoveSubCategory(
            int id,
            string language = null,
            string connectionId = null,
            XUserClaimsInfoDto userInfo = null,
            CancellationToken cancellationToken = default
        )
        {
            //
            return await subCategoryProvider
                .Remove(
                    id: id,
                    language: language,
                    userInfo: userInfo,
                    connectionId: connectionId,
                    cancellationToken: cancellationToken
            );
        }

        /// <summary>
        /// Update an Item for Specified Language ...
        /// </summary>
        /// <param name="id"></param>
        /// <param name="item"></param>
        /// <param name="language"></param>
        /// <param name="connectionId"></param>
        /// <param name="userInfo"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public virtual async Task<XSubCategoryResourceDto> UpdateSubCategory(
            int id,
            XSubCategoryDto item,
            string language = null,
            string connectionId = null,
            XUserClaimsInfoDto userInfo = null,
            CancellationToken cancellationToken = default
        )
        {
            //
            return await subCategoryProvider
                .Update(
                    id: id,
                    item: item,
                    language: language,
                    userInfo: userInfo,
                    connectionId: connectionId,
                    cancellationToken: cancellationToken
            );
        }

        /// <summary>
        /// Refresh a Resource ...
        /// </summary>
        /// <param name="resource"></param>
        /// <param name="connectionId"></param>
        /// <param name="userInfo"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public virtual async Task<XSubCategoryResourceDto> RefreshSubCategory(
            XSubCategoryResourceDto resource,
            string connectionId = null,
            XUserClaimsInfoDto userInfo = null,
            CancellationToken cancellationToken = default
        )
        {
            //
            return await subCategoryProvider
                .Refresh(
                    resource: resource,
                    userInfo: userInfo,
                    connectionId: connectionId,
                    cancellationToken: cancellationToken
            );
        }

        /// <summary>
        /// Get All Resources ...
        /// </summary>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public virtual async Task<IEnumerable<XSubCategoryResourceDto>> GetAllSubCategoryResources(
            CancellationToken cancellationToken = default
        )
        {
            //
            return await subCategoryProvider
                .GetAllResources(
                    cancellationToken: cancellationToken
            );
        }

        /// <summary>
        /// Find One Resource ...
        /// </summary>
        /// <param name="predicate"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public virtual async Task<XSubCategoryResourceDto> FindOneSubCategoryResource(
            Expression<Func<XSubCategoryResourceDto, bool>> predicate = null,
            CancellationToken cancellationToken = default
        )
        {
            //
            return await subCategoryProvider
                .FindOneResource(
                    predicate: predicate,
                    cancellationToken: cancellationToken
            );
        }

        /// <summary>
        /// Find Many Resource ...
        /// </summary>
        /// <param name="predicate"></param>
        /// <param name="orderBuilder"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public virtual async Task<IEnumerable<XSubCategoryResourceDto>> FindManySubCategoryResource(
            Expression<Func<XSubCategoryResourceDto, bool>> predicate = null,
            Func<IQueryable<XSubCategoryResourceDto>, IOrderedQueryable<XSubCategoryResourceDto>> orderBuilder = null,
            CancellationToken cancellationToken = default
        )
        {
            //
            return await subCategoryProvider
                .FindManyResource(
                    predicate: predicate,
                    orderBuilder: orderBuilder,
                    cancellationToken: cancellationToken
            );
        }

        /// <summary>
        /// Retrieve Resources by Query Pattern ...
        /// </summary>
        /// <param name="query"></param>
        /// <param name="predicate"></param>
        /// <param name="orderBuilder"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public virtual async Task<XQueryResult<XSubCategoryResourceDto>> QuerySubCategoryResources(
            XQuery query = null,
            Expression<Func<XSubCategoryResourceDto, bool>> predicate = null,
            Func<IQueryable<XSubCategoryResourceDto>, IOrderedQueryable<XSubCategoryResourceDto>> orderBuilder = null,
            CancellationToken cancellationToken = default
        )
        {
            //
            return await subCategoryProvider
                .QueryResources(
                    query: query,
                    predicate: predicate,
                    orderBuilder: orderBuilder,
                    cancellationToken: cancellationToken
            );
        }

        /// <summary>
        /// Get All Resources as Async Enumerable ... 
        /// </summary>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public virtual IAsyncEnumerable<XSubCategoryResourceDto> GetAllSubCategoryResourcesAsAsyncEnumerable(
            CancellationToken cancellationToken = default
        )
        {
            //
            return subCategoryProvider
                .GetAllResourcesAsAsyncEnumerable(
                    cancellationToken: cancellationToken
            );
        }
        #endregion        
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xCategoryService\Providers\XCategorySubCategoryReferenceProvider.cs

using xCategoryService.Constants;
using xCategoryService.Interfaces;
using xCategoryService.Interfaces.Dtos;

namespace xCategoryService.Providers
{
    public class XCategorySubCategoryReferenceProvider : XBaseCategoryProvider<int>, IXCategorySubCategoryReferenceProvider
    {
        public XCategorySubCategoryReferenceProvider(
            IXCategoryServiceProvider categoryProvider
        ) : base(
            categoryProvider: categoryProvider,
            providedFor: XCategoryServiceConstants.SubCategoryReference
        )
        { }
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xCategoryService\Providers\XCategoryTitleResourceProvider.cs

using xCategoryService.Constants;
using xCategoryService.Interfaces;
using xStringService.Interfaces.Dtos;
using xStringService.Providers;

namespace xCategoryService.Providers
{
    public class XCategoryTitleResourceProvider : XBaseItemResourceProvider, IXCategoryTitleResourceProvider
    {
        public XCategoryTitleResourceProvider(
            IXStringServiceProvider stringProvider
        ) : base(
            stringProvider: stringProvider,
            item: XCategoryServiceConstants.CategoryTitleResourceIdentifier
        )
        { }
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xCategoryService\Providers\XSubCategoryDescriptionResourceProvider.cs

using xCategoryService.Constants;
using xCategoryService.Interfaces;
using xStringService.Interfaces.Dtos;
using xStringService.Providers;

namespace xCategoryService.Providers
{
    public class XSubCategoryDescriptionResourceProvider : XBaseItemResourceProvider, IXSubCategoryDescriptionResourceProvider
    {
        public XSubCategoryDescriptionResourceProvider(
            IXStringServiceProvider stringProvider
        ) : base(
            stringProvider: stringProvider,
            item: XCategoryServiceConstants.SubCategoryDescriptionResourceIdentifier
        )
        { }
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xCategoryService\Providers\XSubCategoryEntityRegisterar.cs

using Microsoft.EntityFrameworkCore;
using xCategoryService.Configurations.Entities;
using xCategoryService.Models.Entities;
using xDataService.Interfaces;
using xDataService.Providers;

namespace xCategoryService.Providers
{
    public class XSubCategoryEntityRegisterar : XBaseEntityRegisterar, IXEntityRegisterar
    {
        public XSubCategoryEntityRegisterar()
        : base(nameof(XSubCategoryEntityRegisterar))
        {
            //
            // Add Entity ...
            AddEntity<XSubCategory, int>();
        }

        /// <summary>
        /// Configure Entities ...
        /// </summary>
        /// <param name="modelBuilder"></param>
        public override void ConfigureEntities(ModelBuilder modelBuilder)
        {
            //
            // Configure Entity Using Provided ...
            modelBuilder
                .ApplyConfigurationsFromAssembly(typeof(XSubCategoryEntityConfiguration).Assembly);

            //
            base.ConfigureEntities(modelBuilder);
        }
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xCategoryService\Providers\XSubCategoryProvider.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Runtime.CompilerServices;
using System.Threading;
using System.Threading.Tasks;
using xCategoryService.Interfaces;
using xCategoryService.Interfaces.Dtos;
using xCategoryService.Models.Dtos;
using xCategoryService.Models.Entities;
using xCategoryService.Providers.Dtos;
using xCommons.Configurations;
using xCommons.Extensions;
using xDataService.Configuration;
using xExceptions.Constants;
using xIdentityModels.Models;
using xModels.Dtos;
using xDataService.Extensions;
using xPushService.Constants;
using xPushService.Providers;

namespace xCategoryService.Providers
{
    public class XSubCategoryProvider : XBaseProvided<XSubCategory, XSubCategoryDto, int, XSubCategoryDtoHub>, IXSubCategoryProvider
    {
        private readonly XAppConfiguration appConfiguration;
        private readonly IXCategoryProvider categoryProvider;
        private readonly IXSubCategoryServiceProvider provider;
        private readonly XDataServiceConfiguration dataServiceConfiguration;
        private readonly IXSubCategoryTitleResourceProvider titleResourceProvider;
        private readonly IXSubCategoryDescriptionResourceProvider descriptionResourceProvider;

        public XSubCategoryProvider(
            XAppConfiguration appConfiguration,
            IXCategoryProvider categoryProvider,
            IXSubCategoryServiceProvider provider,
            XDataServiceConfiguration dataServiceConfiguration,
            IXSubCategoryTitleResourceProvider titleResourceProvider,
            IXSubCategoryDescriptionResourceProvider descriptionResourceProvider
        ) : base(
            provider,
            permittedRoles: new string[] { }
        )
        {
            this.provider = provider;
            this.appConfiguration = appConfiguration;
            this.categoryProvider = categoryProvider;
            this.titleResourceProvider = titleResourceProvider;
            this.dataServiceConfiguration = dataServiceConfiguration;
            this.descriptionResourceProvider = descriptionResourceProvider;
        }

        //
        #region Overrides ...
        public override bool IsOwned(
            XSubCategoryDto item,
            XUserClaimsInfoDto userInfo
        )
        {
            return !item.IsNullOrDefault();
        }

        public override bool IsOwned(
            XSubCategory item,
            XUserClaimsInfoDto userInfo
        )
        {
            return !item.IsNullOrDefault();
        }
        #endregion

        //
        #region Actions ...
        /// <summary>
        /// Check Has Specified Locale or not ...
        /// </summary>
        /// <param name="id"></param>
        /// <param name="language"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public async Task<bool> HasLocale(
            int id,
            string language,
            CancellationToken cancellationToken = default
        )
        {
            //
            // Validate ...
            var isValid =
                id.IsValidIntId() &&
                !language.IsNullOrEmpty();
            if (!isValid)
            {
                XException.InvalidArgs.Throw();
            }

            //
            // Retrieve Resource ...
            var resource = await GetResource(
                id: id,
                cancellationToken: cancellationToken
            );

            //
            // Check Result ...
            var result =
                !resource.IsNullOrDefault() &&
                resource.Titles.Locales
                    .Any(x => x.Language
                        .Equals(language, System.StringComparison.InvariantCultureIgnoreCase));

            //
            return result;
        }

        /// <summary>
        /// Load an Item by all of it's Related Translations ...
        /// </summary>
        /// <param name="id"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public async Task<XSubCategoryResourceDto> GetResource(
            int id,
            CancellationToken cancellationToken = default
        )
        {
            //
            var item = await Get(
                id: id,
                includeBuilder: null,
                cancellationToken: cancellationToken
            );
            var titleResource = await titleResourceProvider.GetResource(
                identifier: id,
                cancellationToken: cancellationToken
            );
            var descriptionResource = await descriptionResourceProvider.GetResource(
                identifier: id,
                cancellationToken: cancellationToken
            );

            //
            // Reading Category Resource ...
            XCategoryResourceDto categoryResourceDto = null;
            try
            {
                var categoryDto = await categoryProvider.GetReference(
                    providedForId: id,
                    cancellationToken: cancellationToken
                );
                if (!categoryDto.IsNullOrDefault())
                {
                    categoryResourceDto = await categoryProvider.GetResource(
                        id: categoryDto.Id,
                        cancellationToken: cancellationToken
                    );
                }
            }
            catch { }

            //
            var result = new XSubCategoryResourceDto
            {
                Item = item,
                Titles = titleResource,
                Category = categoryResourceDto,
                Descriptions = descriptionResource
            };

            //
            return result;
        }

        /// <summary>
        /// Add an Item for Specified Language ...
        /// </summary>
        /// <param name="item"></param>
        /// <param name="language"></param>
        /// <param name="connectionId"></param>
        /// <param name="userInfo"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>        
        public async Task<XSubCategoryResourceDto> Add(
            XSubCategoryDto item,
            string language = null,
            string connectionId = null,
            XUserClaimsInfoDto userInfo = null,
            CancellationToken cancellationToken = default
        )
        {
            //
            // Normalize ...
            language =
                !language.IsNullOrEmpty()
                    ? language
                    : appConfiguration.DefaultLanguage;

            //
            // Validate ...
            var isValid = !item.IsNullOrDefault();
            if (!isValid)
            {
                XException.InvalidArgs.Throw();
            }

            //
            // Check Permission ...
            isValid = HasPermision(userInfo);
            if (!isValid)
            {
                XException.NotAllowed.Throw();
            }

            //
            var id = -1;
            try
            {
                //
                var title = item.Title;
                var description = item.Description;

                //
                // Add Item Pure for ID Generating ...
                item = await base.Add(
                    item: item,
                    userInfo: userInfo,
                    connectionId: null, // Since here We dont want notification ...
                    cancellationToken: cancellationToken
                );
                isValid = !item.IsNullOrDefault();
                if (!isValid)
                {
                    XException.ActionFailed.Throw();
                }

                //
                id = item.Id;
                var titleResource = await titleResourceProvider
                    .AddOrUpdateLocale(
                        identifier: id,
                        locale: new XLocaleResourceDto
                        {
                            Value = title,
                            Language = language
                        },
                        connectionId: connectionId,
                        cancellationToken: cancellationToken
                    );
                var descriptionResource = await descriptionResourceProvider
                    .AddOrUpdateLocale(
                        identifier: id,
                        locale: new XLocaleResourceDto
                        {
                            Value = description,
                            Language = language
                        },
                        connectionId: connectionId,
                        cancellationToken: cancellationToken
                    );

                //
                // Update Category Dto ...
                item.Title = titleResource.Resource;
                item.Description = descriptionResource.Resource;
                item = await base.Update(
                    id: id,
                    item: item,
                    userInfo: userInfo,
                    connectionId: null,
                    cancellationToken: cancellationToken
                );
            }
            catch
            {
                XException.InvalidArgs.Throw();
            }

            //  
            // Validate Id ...
            isValid = id.IsValidIntId();
            if (!isValid)
            {
                XException.ActionFailed.Throw();
            }

            //
            // Retrieve Category Resourv=ce ...
            var result = await GetResource(
                id: id,
                cancellationToken: cancellationToken
            );

            //
            // Sending Push Notification ...
            isValid =
                isValid &&
                !result.IsNullOrDefault();
            if (isValid)
            {
                //
                await provider.SendPush(
                    connectionId: connectionId,
                    cancellationToken: cancellationToken,
                    payLoad: result.ToJSON(camelCase: true),
                    action: XBaseEntityHubAction.Add.GetStringValue()
                );
            }

            //
            return result;
        }

        /// <summary>
        /// Add Item by it's Locales and Reference ...
        /// </summary>
        /// <param name="item"></param>
        /// <param name="connectionId"></param>
        /// <param name="userInfo"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public async Task<XSubCategoryResourceDto> AddResource(
            XSubCategoryResourceDto item,
            string connectionId = null,
            XUserClaimsInfoDto userInfo = null,
            CancellationToken cancellationToken = default
        )
        {
            //
            // Validate ...
            var isValid =
                !item.IsNullOrDefault() &&
                !item.Titles.IsNullOrDefault() &&
                item.Titles.Locales.HasChild() &&
                !item.Titles.Locales.Any(tl =>
                    tl.Value.IsNullOrEmpty() ||
                    tl.Language.IsNullOrEmpty());
            if (!isValid)
            {
                XException.InvalidArgs.Throw();
            }

            //
            // Normalize ...
            if (item.Item.IsNullOrDefault())
            {
                item.Item = new XSubCategoryDto();
            }

            //
            // Check Permission ...
            isValid = HasPermision(userInfo);
            if (!isValid)
            {
                XException.NotAllowed.Throw();
            }

            //
            var id = -1;
            try
            {
                //
                // Handle Category Generation ...
                if (!item.Category.IsNullOrDefault())
                {
                    //
                    // Handle Category ...
                    try
                    {
                        // Try to Add Category ...
                        item.Category = await categoryProvider.Refresh(
                            resource: item.Category,
                            userInfo: userInfo,
                            connectionId: connectionId,
                            cancellationToken: cancellationToken
                        );
                    }
                    catch { }
                }

                //
                // Add SubCategory for ID Generation ...
                item.Item = await base.Add(
                    item: item.Item,
                    userInfo: userInfo,
                    connectionId: null, // Since here We dont want notification ...
                    cancellationToken: cancellationToken
                );
                isValid = !item.Item.IsNullOrDefault();
                if (!isValid)
                {
                    XException.ActionFailed.Throw();
                }
                id = item.Item.Id;

                //                
                foreach (var il in item.Titles.Locales)
                {
                    //
                    var title = il.Value;
                    var language = il.Language;

                    //
                    var descriptionItem =
                        item.Descriptions.IsNullOrDefault() ||
                        !item.Descriptions.Locales.HasChild()
                        ? null
                        : item.Descriptions.Locales
                            .FirstOrDefault(ides =>
                                ides.Language
                                    .Equals(
                                        language,
                                        StringComparison.InvariantCultureIgnoreCase));
                    var description =
                        descriptionItem.IsNullOrDefault()
                        ? string.Empty
                        : descriptionItem.Value;

                    //
                    // Try to Add Resources ...
                    var titleResource = await titleResourceProvider
                        .AddOrUpdateLocale(
                            identifier: id,
                            locale: new XLocaleResourceDto
                            {
                                Value = title,
                                Language = language
                            },
                            connectionId: connectionId,
                            cancellationToken: cancellationToken
                        );
                    var descriptionResource = await descriptionResourceProvider
                        .AddOrUpdateLocale(
                            identifier: id,
                            locale: new XLocaleResourceDto
                            {
                                Value = description,
                                Language = language
                            },
                            connectionId: connectionId,
                            cancellationToken: cancellationToken
                        );

                    //
                    // Update Category Dto if not ...
                    if (item.Item.Title.IsNullOrEmpty() ||
                        !item.Item.Title
                        .Equals(
                            titleResource.Resource,
                            StringComparison.InvariantCultureIgnoreCase)
                    )
                    {
                        //
                        item.Item.Title = titleResource.Resource;
                        item.Item.Description = descriptionResource.Resource;
                        item.Item = await base.Update(
                            id: id,
                            item: item.Item,
                            userInfo: userInfo,
                            connectionId: null,
                            cancellationToken: cancellationToken
                        );
                    }
                }
            }
            catch
            {
                XException.InvalidArgs.Throw();
            }

            //  
            // Validate Id ...
            isValid = id.IsValidIntId();
            if (!isValid)
            {
                XException.ActionFailed.Throw();
            }

            //
            // Add Resource Reference to Category ...
            isValid = await categoryProvider.AddReference(
                providedForId: id,
                connectionId: null,
                model: item.Category.Item,
                cancellationToken: cancellationToken
            );

            //
            // Retrieve Category Resourv=ce ...
            var result = await GetResource(
                id: id,
                cancellationToken: cancellationToken
            );

            //
            // Sending Push Notification ...
            isValid =
                isValid &&
                !result.IsNullOrDefault();
            if (isValid)
            {
                //
                await provider.SendPush(
                    connectionId: connectionId,
                    cancellationToken: cancellationToken,
                    payLoad: result.ToJSON(camelCase: true),
                    action: XBaseEntityHubAction.Add.GetStringValue()
                );
            }

            //
            return result;
        }

        /// <summary>
        /// Remove Item for Specified Language ...
        /// </summary>
        /// <param name="id"></param>
        /// <param name="language">if null, Remove All</param>
        /// <param name="connectionId"></param>
        /// <param name="userInfo"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public async Task<XSubCategoryResourceDto> Remove(
            int id,
            string language = null,
            string connectionId = null,
            XUserClaimsInfoDto userInfo = null,
            CancellationToken cancellationToken = default
        )
        {
            //
            // Validate ...
            var isValid = id.IsValidIntId();
            if (!isValid)
            {
                XException.InvalidArgs.Throw();
            }

            //
            // Check Item Exists ...
            isValid = await IsExists(
                id: id,
                cancellationToken: cancellationToken
            );
            if (!isValid)
            {
                XException.NotFound.Throw();
            }

            //
            // Validate Locale if Provided ...
            isValid =
                language.IsNullOrEmpty() ||
                await HasLocale(
                    id: id,
                    language: language,
                    cancellationToken: cancellationToken
                );
            if (!isValid)
            {
                XException.NotFound.Throw();
            }

            //
            var result = await GetResource(
                id: id,
                cancellationToken: cancellationToken
            );
            if (language.IsNullOrEmpty())
            {
                //
                // Remove All ...

                //
                // Titles ...
                await titleResourceProvider.RemoveLocales(
                    identifier: id,
                    connectionId: null,
                    cancellationToken: cancellationToken
                );

                //
                // Descriptions ...
                await descriptionResourceProvider.RemoveLocales(
                    identifier: id,
                    connectionId: null,
                    cancellationToken: cancellationToken
                );

                //
                // Remove Entity ...
                await provider.RemoveAsync(
                    id: id,
                    softDelete: false,
                    saveChanges: true,
                    connectionId: null,
                    cancellationToken: cancellationToken
                );

                //
                isValid = true;
                result.Titles.Locales = [];
                result.Descriptions.Locales = [];
            }
            else
            {
                //
                // Remove Only One Locale, and if there is one, Remove all ...

                //
                // Remove Title if Exists ...
                isValid = await titleResourceProvider.HasLocale(
                    identifier: id,
                    language: language,
                    cancellationToken: cancellationToken
                );
                if (isValid)
                {
                    //
                    await titleResourceProvider.RemoveLocale(
                        identifier: id,
                        language: language,
                        connectionId: null,
                        cancellationToken: cancellationToken
                    );
                }

                //
                // Remove Description if Exists ...
                isValid = await descriptionResourceProvider.HasLocale(
                    identifier: id,
                    language: language,
                    cancellationToken: cancellationToken
                );
                if (isValid)
                {
                    //
                    await descriptionResourceProvider.RemoveLocale(
                        identifier: id,
                        language: language,
                        connectionId: null,
                        cancellationToken: cancellationToken
                    );
                }

                //
                // Retrieve Resource ...
                result = await GetResource(
                    id: id,
                    cancellationToken: cancellationToken
                );

                //
                // Check Has Locales ...
                isValid = result.Titles.Locales.HasChild();
                if (!isValid)
                {
                    //
                    // Remove Item ...
                    await provider.RemoveAsync(
                        id: id,
                        softDelete: false,
                        saveChanges: true,
                        connectionId: null,
                        cancellationToken: cancellationToken
                    );

                    //
                    result.Titles.Locales = [];
                    result.Descriptions.Locales = [];
                }

                //
                isValid = true;
            }

            //
            // Remove all Referencings ...
            if (isValid)
            {
                await categoryProvider.RemoveReferences(
                    providedForId: id,
                    connectionId: connectionId,
                    cancellationToken: cancellationToken
                );
            }

            //
            if (isValid)
            {
                //
                // Send Push ...
                await provider.SendPush(
                    connectionId: connectionId,
                    cancellationToken: cancellationToken,
                    payLoad: result.ToJSON(camelCase: true),
                    action:
                        result.Titles.Locales.HasChild()
                        ? "DeleteLocale"
                        : XBaseEntityHubAction.Delete.GetStringValue()
                );
            }

            //
            return result;
        }

        /// <summary>
        /// Update an Item for Specified Language ...
        /// </summary>
        /// <param name="id"></param>
        /// <param name="item"></param>
        /// <param name="language"></param>
        /// <param name="connectionId"></param>
        /// <param name="userInfo"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public async Task<XSubCategoryResourceDto> Update(
            int id,
            XSubCategoryDto item,
            string language = null,
            string connectionId = null,
            XUserClaimsInfoDto userInfo = null,
            CancellationToken cancellationToken = default
        )
        {
            //
            // Validate ...
            var isValid =
                id.IsValidIntId() &&
                !item.IsNullOrDefault() &&
                !language.IsNullOrEmpty() &&
                !item.Title.IsNullOrEmpty();
            if (!isValid)
            {
                XException.InvalidArgs.Throw();
            }

            //
            // Check Category Exists ...
            isValid = await IsExists(
                id: id,
                cancellationToken: cancellationToken
            );
            if (!isValid)
            {
                XException.NotFound.Throw();
            }

            //
            // Check Locale Exists ...
            isValid = await HasLocale(
                id: id,
                language: language,
                cancellationToken: cancellationToken
            );
            if (!isValid)
            {
                XException.NotFound.Throw();
            }

            //
            // Retrieve Category Dto for Validate Owining ...
            var dto = await Get(
                id: id,
                includeBuilder: null,
                cancellationToken: cancellationToken
            );

            //
            // Check Permission ...
            isValid =
                !dto.IsNullOrDefault() &&
                !userInfo.IsNullOrDefault() &&
                (IsOwned(
                    item: dto,
                    userInfo: userInfo
                ) || HasPermision(userInfo));
            if (!isValid)
            {
                XException.NotAllowed.Throw();
            }

            //
            // Retrieve Exists Item Resource ...
            var resource = await GetResource(
                id: id,
                cancellationToken: cancellationToken
            );

            //
            var titleUpdated = false;
            var descriptionUpdated = false;

            //
            // Update Title ...
            resource.Titles.Locales
                .ToList()
                .ForEach(tl =>
                {
                    //
                    if (tl.Language.Equals(language, StringComparison.InvariantCultureIgnoreCase))
                    {
                        //
                        titleUpdated = true;
                        tl.Value = item.Title;
                    }
                });

            //
            // Update Description ...
            resource.Descriptions.Locales
                .ToList()
                .ForEach(dl =>
                {
                    //
                    if (dl.Language.Equals(language, StringComparison.InvariantCultureIgnoreCase))
                    {
                        //
                        descriptionUpdated = true;
                        dl.Value = item.Description;
                    }
                });

            //
            // Validate Title and Description Updated ...
            isValid = titleUpdated && descriptionUpdated;
            if (!isValid)
            {
                XException.ActionFailed.Throw();
            }

            //
            resource = await Refresh(
                resource: resource,
                userInfo: userInfo,
                connectionId: connectionId,
                cancellationToken: cancellationToken
            );

            //
            return resource;
        }

        /// <summary>
        /// Refresh a Resource ...
        /// </summary>
        /// <param name="resource"></param>
        /// <param name="connectionId"></param>
        /// <param name="userInfo"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public async Task<XSubCategoryResourceDto> Refresh(
            XSubCategoryResourceDto resource,
            string connectionId = null,
            XUserClaimsInfoDto userInfo = null,
            CancellationToken cancellationToken = default
        )
        {
            //
            // Validate Args ...
            var isValid =
                !resource.IsNull();
            if (!isValid)
            {
                XException.InvalidArgs.Throw();
            }

            //
            // Check Permission ...
            isValid = HasPermision(userInfo);
            if (!isValid)
            {
                XException.NotAllowed.Throw();
            }

            //
            var id = -1;
            var isDelete = false;
            XSubCategoryResourceDto result = null;

            //
            // Check Item Exists ...
            XSubCategoryDto dto =
                (resource.Item.IsNullOrDefault() ||
                !resource.Item.Id.IsValidIntId())
                ? null
                : await Get(
                    id: resource.Item.Id,
                    includeBuilder: null,
                    cancellationToken: cancellationToken
            );
            var isExists = !dto.IsNullOrDefault();

            //
            // Do Referesh Based on Existance ...
            var isNew =
                !isExists &&
                (resource.Item.IsNullOrDefault() ||
                !resource.Item.Id.IsValidIntId());
            if (isNew)
            {
                //
                // Add ...
                // In this Senario, for Add a Category by Providing Resource 
                // the item must clean, either Title and Description, and tge Locales Provided by Resource
                // ust Contains Values ...
                // the Add Starts by Titles and only Items Add Which has Titles, since Title is Mandatory
                // and Description is Optional ...
                isValid =
                    //
                    // Resource ...
                    (resource.Item.IsNullOrDefault() ||
                    (!resource.Item.Id.IsValidIntId() &&
                    resource.Item.Title.IsNullOrEmpty() &&
                    resource.Item.Description.IsNullOrEmpty())) &&
                    //
                    // Titles ...
                    !resource.Titles.IsNullOrDefault() &&
                    resource.Titles.Locales.HasChild();
                if (!isValid)
                {
                    XException.InvalidArgs.Throw();
                }

                //
                // Add Temp Category ...
                var unique = Guid.NewGuid();
                var temp = new XSubCategoryDto
                {
                    Title = $"TmpT_{unique}",
                    Description = $"TmpD_{unique}",
                };
                temp = await provider.AddAsync(
                    item: temp,
                    saveChanges: true,
                    connectionId: null,
                    cancellationToken: cancellationToken
                );
                isValid =
                    !temp.IsNullOrDefault() &&
                    temp.Id.IsValidIntId();
                if (!isValid)
                {
                    XException.ActionFailed.Throw();
                }
                id = temp.Id;

                //
                // Update Title and Description ...
                var titleResource = titleResourceProvider.GetResourceTitle(id);
                var descriptionResource = descriptionResourceProvider.GetResourceTitle(id);
                temp.Title = titleResource;
                temp.Description = descriptionResource;
                temp = await provider.UpdateAsync(
                    id: id,
                    item: temp,
                    saveChanges: true,
                    connectionId: null,
                    cancellationToken: cancellationToken
                );

                //
                // Loop through Titles ...
                foreach (var locale in resource.Titles.Locales)
                {
                    //
                    // Add Or Update Locale ...
                    await titleResourceProvider.AddOrUpdateLocale(
                        locale: locale,
                        identifier: id,
                        connectionId: null,
                        cancellationToken: cancellationToken
                    );
                    var desLocale = resource.Descriptions.Locales.FirstOrDefault(
                        dl =>
                            dl.Language == locale.Language);
                    if (!desLocale.IsNullOrDefault())
                    {
                        //
                        // Add Descriptions ...
                        await descriptionResourceProvider.AddOrUpdateLocale(
                            identifier: id,
                            locale: desLocale,
                            connectionId: null,
                            cancellationToken: cancellationToken
                        );
                    }
                }
            }
            else if (isExists)
            {
                //
                // Re State ...
                id = resource.Item.Id;

                //
                // Try to Refresh Resource State ...

                //
                // Check Delete ...
                isDelete = !resource.Titles.Locales.HasChild();
                if (isDelete)
                {
                    //
                    // Handle Delete ...
                    await Remove(
                        id: id,
                        language: null,
                        userInfo: userInfo,
                        connectionId: null,
                        cancellationToken: cancellationToken
                    );
                }
                else
                {
                    //
                    // Handle Update ...
                    result = await GetResource(
                        id: id,
                        cancellationToken: cancellationToken
                    );

                    //
                    #region Remove ...
                    //
                    // Titles ...
                    var removeTitles = result.Titles.Locales.Where(
                        l => !resource.Titles.Locales.Any(r => r.Language.Equals(l.Language, System.StringComparison.InvariantCultureIgnoreCase))
                    );
                    foreach (var locale in removeTitles)
                    {
                        //
                        await titleResourceProvider.RemoveLocale(
                            identifier: id,
                            connectionId: null,
                            language: locale.Language,
                            cancellationToken: cancellationToken
                        );
                    }

                    //
                    // Descriptions ...
                    var removeDescriptions = result.Descriptions.Locales.Where(
                        l => !resource.Descriptions.Locales.Any(r => r.Language.Equals(l.Language, System.StringComparison.InvariantCultureIgnoreCase))
                    );
                    foreach (var locale in removeDescriptions)
                    {
                        //
                        await descriptionResourceProvider.RemoveLocale(
                            identifier: id,
                            connectionId: null,
                            language: locale.Language,
                            cancellationToken: cancellationToken
                        );
                    }
                    #endregion

                    //
                    #region Update ...
                    // 
                    // Titles ...
                    var updateTitles = result.Titles.Locales.Where(
                        l => resource.Titles.Locales.Any(r =>
                            r.Value
                                .Equals(l.Value, StringComparison.InvariantCultureIgnoreCase) &&
                            r.Language
                                .Equals(l.Language, StringComparison.InvariantCultureIgnoreCase)
                        )
                    );
                    foreach (var locale in updateTitles)
                    {
                        //
                        await titleResourceProvider.AddOrUpdateLocale(
                            identifier: id,
                            locale: locale,
                            connectionId: null,
                            cancellationToken: cancellationToken
                        );
                    }

                    //
                    // Descriptions ...
                    var updateDescriptions = result.Descriptions.Locales.Where(
                        l => resource.Descriptions.Locales.Any(r =>
                            r.Value
                                .Equals(l.Value, StringComparison.InvariantCultureIgnoreCase) &&
                            r.Language
                                .Equals(l.Language, StringComparison.InvariantCultureIgnoreCase))
                    );
                    foreach (var locale in updateDescriptions)
                    {
                        //
                        await descriptionResourceProvider.AddOrUpdateLocale(
                            identifier: id,
                            locale: locale,
                            connectionId: null,
                            cancellationToken: cancellationToken
                        );
                    }
                    #endregion

                    //
                    #region New ...
                    //
                    // Titles ...
                    var newTitles = resource.Titles.Locales.Where(
                        l => !result.Titles.Locales.Any(r => r.Language.Equals(l.Language, StringComparison.InvariantCultureIgnoreCase))
                    );
                    foreach (var locale in newTitles)
                    {
                        //
                        await titleResourceProvider.AddOrUpdateLocale(
                            identifier: id,
                            locale: locale,
                            connectionId: null,
                            cancellationToken: cancellationToken
                        );
                    }

                    //
                    // Descriptions ...
                    var newDescriptions = resource.Descriptions.Locales.Where(
                        l => !result.Descriptions.Locales.Any(r => r.Language.Equals(l.Language, StringComparison.InvariantCultureIgnoreCase))
                    );
                    foreach (var locale in newDescriptions)
                    {
                        //
                        await descriptionResourceProvider.AddOrUpdateLocale(
                            identifier: id,
                            locale: locale,
                            connectionId: null,
                            cancellationToken: cancellationToken
                        );
                    }
                    #endregion
                }
            }

            //
            // Handle Category ...
            if (
                !isDelete &&
                (isNew || isExists) &&
                !resource.Category.IsNullOrDefault())
            {
                //
                // Refresh Category ...
                var category = await categoryProvider.Refresh(
                    userInfo: userInfo,
                    resource: resource.Category,
                    connectionId: connectionId,
                    cancellationToken: cancellationToken
                );

                //
                // Handle SubCategory Referencings ...
                var references = await categoryProvider.GetAllReferences(
                    providedForId: id,
                    cancellationToken: cancellationToken
                );
                var hasReference =
                    references.HasChild() &&
                    references.Any(r => r.Id == category.Item.Id);
                if (!hasReference)
                {
                    await categoryProvider.AddReference(
                        providedForId: id,
                        model: category.Item,
                        connectionId: connectionId,
                        cancellationToken: cancellationToken
                    );
                }
            }

            //
            // Validate Action ...
            isValid = id.IsValidIntId();
            if (!isValid)
            {
                XException.ActionFailed.Throw();
            }

            //
            // Get Result ...
            result =
                isDelete
                ? resource
                : await GetResource(
                id: id,
                cancellationToken: cancellationToken
            );
            isValid = !result.IsNullOrDefault();

            //
            // Send Notification ...
            if (isValid)
            {
                //
                await provider.SendPush(
                    connectionId: connectionId,
                    cancellationToken: cancellationToken,
                    payLoad: result.ToJSON(camelCase: true),
                    action: isNew
                        ? XBaseEntityHubAction.Add.GetStringValue()
                        : isDelete
                            ? XBaseEntityHubAction.Delete.GetStringValue()
                            : XBaseEntityHubAction.Update.GetStringValue()
                );
            }

            //
            return result;
        }

        /// <summary>
        /// Get All Resources as Async Enumerable ... 
        /// </summary>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public async IAsyncEnumerable<XSubCategoryResourceDto> GetAllResourcesAsAsyncEnumerable(
            [EnumeratorCancellation] CancellationToken cancellationToken = default
        )
        {
            //
            var enumerable = provider.GetAllAsAsyncEnumerable(
                includeBuilder: null,
                ignoreSoftDeleteds: true,
                cancellationToken: cancellationToken,
                orderBuilder: x => x.OrderBy(y => y.Id)
            );

            //
            await foreach (var dto in enumerable)
            {
                //
                if (cancellationToken.IsCancellationRequested)
                {
                    yield break;
                }

                //
                var resource = await GetResource(
                    id: dto.Id,
                    cancellationToken: cancellationToken
                );
                yield return resource;
            }
        }

        /// <summary>
        /// Get All Resources ...
        /// </summary>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public async Task<IEnumerable<XSubCategoryResourceDto>> GetAllResources(
            CancellationToken cancellationToken = default
        )
        {
            //
            var result = new List<XSubCategoryResourceDto>();

            //
            var enumerable = GetAllResourcesAsAsyncEnumerable(cancellationToken);
            await foreach (var item in enumerable)
            {
                //
                if (cancellationToken.IsCancellationRequested)
                {
                    break;
                }

                //
                result.Add(item);
            }

            //
            return result;
        }

        /// <summary>
        /// Find One Resource ...
        /// </summary>
        /// <param name="predicate"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public async Task<XSubCategoryResourceDto> FindOneResource(
            Expression<Func<XSubCategoryResourceDto, bool>> predicate = null,
            CancellationToken cancellationToken = default
        )
        {
            //
            var isApproved = false;
            XSubCategoryResourceDto result = null;
            var enumerable = GetAllResourcesAsAsyncEnumerable(cancellationToken);
            await foreach (var item in enumerable)
            {
                //
                // Check Cancellation Token ...
                if (cancellationToken.IsCancellationRequested)
                {
                    break;
                }

                //
                // Detect Predicate Condition ...
                isApproved = predicate.Compile()(item);
                if (isApproved)
                {
                    //
                    result = item;
                    break;
                }
            }

            //
            return result;
        }

        /// <summary>
        /// Find Many Resource ...
        /// </summary>
        /// <param name="predicate"></param>
        /// <param name="orderBuilder"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public async Task<IEnumerable<XSubCategoryResourceDto>> FindManyResource(
            Expression<Func<XSubCategoryResourceDto, bool>> predicate = null,
            Func<IQueryable<XSubCategoryResourceDto>, IOrderedQueryable<XSubCategoryResourceDto>> orderBuilder = null,
            CancellationToken cancellationToken = default
        )
        {
            //
            var isApproved = false;
            var result = new List<XSubCategoryResourceDto>();
            var enumerable = GetAllResourcesAsAsyncEnumerable(cancellationToken);
            await foreach (var item in enumerable)
            {
                //
                // Check Cancellation Token ...
                if (cancellationToken.IsCancellationRequested)
                {
                    break;
                }

                //
                // Detect Predicate Condition ...
                isApproved = predicate.Compile()(item);
                if (isApproved)
                {
                    result.Add(item);
                }
            }

            //
            // Apply Order ...
            if (!orderBuilder.IsNull())
            {
                //
                result =
                    orderBuilder(result.AsQueryable())
                    .ToList();
            }

            //
            return result;
        }

        /// <summary>
        /// Retrieve Resources by Query Pattern ...
        /// </summary>
        /// <param name="query"></param>
        /// <param name="predicate"></param>
        /// <param name="orderBuilder"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public async Task<XQueryResult<XSubCategoryResourceDto>> QueryResources(
            XQuery query = null,
            Expression<Func<XSubCategoryResourceDto, bool>> predicate = null,
            Func<IQueryable<XSubCategoryResourceDto>, IOrderedQueryable<XSubCategoryResourceDto>> orderBuilder = null,
            CancellationToken cancellationToken = default
        )
        {
            //
            // Normalize Query ...
            query = query.NormalizeQuery(dataServiceConfiguration);

            //
            var items = await FindManyResource(
                predicate: predicate,
                orderBuilder: orderBuilder,
                cancellationToken: cancellationToken
            );
            var totalItemsCount = items.Count();

            //
            // Apply Filter ...
            if (!query.Filter.IsNullOrEmpty())
            {
                //
                items = items
                    .ApplyFilter(query.Filter);
            }
            int filteredItemsCount = items.Count();

            //
            // Count Pages ...
            var totalPagesCount = query.CountPages(totalItemsCount);
            var filteredPagesCount = query.CountPages(filteredItemsCount);

            //
            // Apply Paging and Sorting ...
            if (totalItemsCount > 0 &&
                filteredItemsCount > 0)
            {
                //
                // Apply Sorting ...
                items = items
                    .ToList()
                    .ApplySorting(
                        query.SortBy,
                        query.IsAscending
                    );

                //
                // Apply Paging ...
                items = items
                    .ToList()
                    .ApplyPaging(
                        query.Page,
                        query.PageSize
                    );
            }

            //
            // Prepare Result ...
            var result = new XQueryResult<XSubCategoryResourceDto>
            {
                Page = query.Page,
                Items = [.. items],
                PageSize = query.PageSize,
                TotalPages = totalPagesCount,
                TotalItems = totalItemsCount,
                TotalFilteredPages = filteredPagesCount,
                TotalFilteredItems = filteredItemsCount
            };

            //
            return result;
        }
        #endregion
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xCategoryService\Providers\XSubCategoryTitleResourceProvider.cs

using xCategoryService.Constants;
using xCategoryService.Interfaces;
using xStringService.Interfaces.Dtos;
using xStringService.Providers;

namespace xCategoryService.Providers
{
    public class XSubCategoryTitleResourceProvider : XBaseItemResourceProvider, IXSubCategoryTitleResourceProvider
    {
        public XSubCategoryTitleResourceProvider(
            IXStringServiceProvider stringProvider
        ) : base(
            stringProvider: stringProvider,
            item: XCategoryServiceConstants.SubCategoryTitleResourceIdentifier 
        )
        { }
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xCommons\Attributes\RequireXPoweredAttribute.cs

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

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xCommons\Authorization\RequiredRolesHandler.cs

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

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xCommons\Authorization\RequiredRolesRequirement.cs

using Microsoft.AspNetCore.Authorization;

namespace xCommons.Authorization {
    public partial class RequiredRolesRequirement : IAuthorizationRequirement {
        public string[] Roles { get; }
        public RequiredRolesRequirement (params string[] Roles) {
            this.Roles = Roles;
        }
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xCommons\Configurations\XAppConfiguration.cs

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

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xCommons\Configurations\XSwaggerConfiguration.cs

using System.Collections.Generic;

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 Dictionary<string, string> DefaultValues {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; }
    }

    public partial class XSwaggerDefaultValues
    {
        public Dictionary<string, string> Values { get; set; }        
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xCommons\Constants\CommonConstants.cs

namespace xCommons.Constants {
    public partial class CommonConstants {
        public static char DEFAULT_LIST_SEPERATOR = ',';
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xCommons\Constants\ConfigurationNodeNames.cs

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

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xCommons\Constants\XAuthentication.cs

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

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xCommons\Constants\XAuthorization.cs

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

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xCommons\Constants\XCustomClaims.cs

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 Bio ="bio";
        public const string CoverImage = "cover_image";
        public const string OpenToSearch = "open_to_search";
        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";
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xCommons\Constants\XDeviceType.cs

namespace xCommons.Constants {
    /// <summary>
    /// a collection of available Client Devices
    /// </summary>
    public enum XDeviceType {
        Unknown,
        Mobile,
        Tablet,
        Desktop
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xCommons\Constants\XFileType.cs

namespace xCommons.Constants {
    public enum XFileType {
        Image,
        ProfileImasge,
        CoverImage,
        Audio,
        Video,
        Document
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xCommons\Constants\XPolicy.cs

namespace xCommons.Constants {
    public partial struct XPolicy {
        public const string AllowedOrigins = "AllowedOrigins";
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xCommons\Controllers\XBaseApiController.cs

using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Logging;
using xCommons.Attributes;
using xCommons.Configurations;
using xCommons.Providers;

namespace xCommons.Controllers {
    /// <summary>
    /// Base Api Controller 
    /// </summary>
    [ApiController]
    [RequireXPowered(true)]
    [Route("api/[controller]")]
    [Produces("application/json")]
    public abstract partial class XBaseApiController : XBaseController
    {
        protected XBaseApiController(
            ILogger logger, 
            XAppConfiguration appConfiguration, 
            XValidationProvider validationProvider
        ) : base(
            logger, 
            appConfiguration, 
            validationProvider
        )
        { }
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xCommons\Controllers\XBaseApiV1Controller.cs

using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Logging;
using xCommons.Attributes;
using xCommons.Configurations;
using xCommons.Providers;

namespace xCommons.Controllers {
    /// <summary>
    /// Base Api V1 Controller 
    /// </summary>
    [ApiController]
    [ApiVersion("1.0")]
    [RequireXPowered(true)]
    [Route("api/v{version:apiVersion}/[controller]")]
    public abstract partial class XBaseApiV1Controller : XBaseApiController
    {
        protected XBaseApiV1Controller(
            ILogger logger, 
            XAppConfiguration appConfiguration, 
            XValidationProvider validationProvider
        ) : base(
            logger, 
            appConfiguration, 
            validationProvider
        )
        { }
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xCommons\Controllers\XBaseController.cs

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

        protected 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
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xCommons\DI\XDIHelperExtension.cs

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

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xCommons\Extensions\CertificateExtensions.cs

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: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xCommons\Extensions\CommonExtensions.cs

using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.Serialization;
using System.Security.Cryptography;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading;
using System.Threading.Tasks;
using System.Web;
using System.Xml;
using AutoMapper;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using Newtonsoft.Json.Serialization;
using xCommons.Constants;
using xCommons.Helpers;
using xExceptions.Attributes;
using xExceptions.Constants;

namespace xCommons.Extensions
{
    public static partial class CommonExtensions
    {
        /// <summary>
        /// Conert XMLNode to String ...
        /// </summary>
        /// <param name="node"></param>
        /// <param name="indentation"></param>
        /// <returns></returns>
        public static string ToString(this XmlNode node, int indentation = 2)
        {
            //
            using (var sw = new StringWriter())
            {
                //
                using (var xw = new XmlTextWriter(sw))
                {
                    xw.Formatting = System.Xml.Formatting.Indented;
                    xw.Indentation = indentation;
                    node.WriteContentTo(xw);
                }

                //
                return sw.ToString();
            }
        }

        /// <summary>
        /// Converts a Json String to Dictionary of String Mappings 
        /// </summary>
        /// <param name="source">Json String</param>
        /// <returns></returns>
        public static Dictionary<string, string> JSONToDictionary(this string source)
        {
            //
            try
            {
                return JsonConvert.DeserializeObject<Dictionary<string, string>>(source);
            }
            catch
            {
                return null;
            }
        }

        /// <summary>
        /// Convert properties of specific Class instance to Dictionary ...
        /// </summary>
        /// <param name="source">class instance</param>
        /// <returns></returns>
        public static Dictionary<string, string> ToDictionary<T>(this T source) where T : class
        {
            //
            var result = new Dictionary<string, string>();

            //
            if (source.IsNull())
            {
                return result;
            }

            //
            PropertyInfo[] propertyInfos = source.GetType().GetProperties();
            if (!propertyInfos.HasChild())
            {
                return result;
            }

            //
            foreach (PropertyInfo propertyInfo in propertyInfos)
            {
                result.Add(
                    propertyInfo.Name,
                    propertyInfo
                    .GetValue(source, null)
                    .ToString()
                );
            }

            //
            return result;
        }

        /// <summary>
        /// run specific task and retrieve result ...
        /// </summary>
        /// <param name="source"></param>
        public static void RunTask(this Task source)
        {
            source.
            GetAwaiter()
                .GetResult();
        }

        /// <summary>
        /// run specific task and retrieve result ...
        /// </summary>
        /// <param name="source"></param>
        public static T RunTask<T>(this Task<T> source)
        {
            return source.
            GetAwaiter()
                .GetResult();
        }

        /// <summary>
        /// Convert XML String to Json Object ...
        /// </summary>
        /// <param name="source"></param>
        /// <returns></returns>
        public static string ToJSON(this string source)
        {
            //
            var result = string.Empty;
            try
            {
                //
                result = XMLToJSONHelper.ToJSON(source);

                //
                // Handle Removing Additional Values ...
                result = result.Replace("s:", "").Replace("a:", "");
            }
            catch { }

            //
            return result;
        }

        /// <summary>
        /// Convert object to Json ...
        /// </summary>
        /// <param name="value"></param>
        /// <returns></returns>
        public static string ToJSON<T>(this T value)
        where T : class
        {
            //
            if (value.IsNull())
            {
                return string.Empty;
            }

            //
            var setting = new JsonSerializerSettings
            {
                Formatting = Newtonsoft.Json.Formatting.Indented,
                ReferenceLoopHandling = ReferenceLoopHandling.Ignore,
                PreserveReferencesHandling = PreserveReferencesHandling.None
            };

            //
            return JsonConvert.SerializeObject(value, Newtonsoft.Json.Formatting.None, setting);
        }

        /// <summary>
        /// Convert to Json With Support of Camel Casing
        /// </summary>
        /// <param name="value"></param>
        /// <param name="camelCase"></param>
        /// <returns></returns>
        public static string ToJSON<T>(this T value, bool camelCase = false)
        {
            //
            if (value.IsNull())
            {
                return string.Empty;
            }

            //
            var setting = new JsonSerializerSettings
            {
                Formatting = Newtonsoft.Json.Formatting.Indented,
                ReferenceLoopHandling = ReferenceLoopHandling.Ignore,
                PreserveReferencesHandling = PreserveReferencesHandling.None,
            };

            //
            if (camelCase)
            {
                setting.ContractResolver = new CamelCasePropertyNamesContractResolver();
            }

            //
            return JsonConvert.SerializeObject(value, Newtonsoft.Json.Formatting.None, setting);
        }

        /// <summary>
        /// Map to Dynamic Object ...
        /// </summary>
        /// <param name="source"></param>
        /// <returns></returns>
        public static dynamic ToDynamicObject(this string source)
        {
            return JsonConvert.DeserializeObject(source);
        }

        /// <summary>
        /// Map to Dynamic Object ...
        /// </summary>
        /// <param name="source"></param>
        /// <returns></returns>
        public static dynamic ToDynamicObject(this object source)
        {
            //
            var dMapConfig = new MapperConfiguration(b => { });
            var dMapper = dMapConfig.CreateMapper();

            //
            return dMapper.Map<dynamic>(source);
        }

        /// <summary>
        /// Parse From Dynamic Object ...
        /// </summary>
        /// <param name="source"></param>
        /// <typeparam name="T"></typeparam>
        /// <returns></returns>
        public static T FromDynamicObject<T>(this object source)
        where T : class
        {
            //
            var dMapConfig = new MapperConfiguration(b => { });
            var dMapper = dMapConfig.CreateMapper();
            dynamic dSource = source;

            //
            return dMapper.Map<T>(dSource);
        }

        /// <summary>
        /// Convert Type of Object to Safe Type
        /// </summary>
        /// <param name="source"></param>
        /// <typeparam name="T"></typeparam>
        /// <returns></returns>
        public static T ConvertTo<T>(this object source)
        {
            //
            T result = default(T);

            //
            try
            {
                //
                T item = (T)Convert.ChangeType(source, typeof(T));

                //
                result = item;
            }
            catch { }

            //
            return result;
        }

        /// <summary>
        /// Convert an Instance to another Instance
        /// using AutoMapper dynamic Convertion
        /// </summary>
        /// <param name="source"></param>
        /// <typeparam name="T"></typeparam>
        /// <returns></returns>
        public static T MapConvert<T>(this T source)
        where T : class
        {
            //
            if (source.IsNull())
            {
                return null;
            }

            //
            var dSource = (object)source.ToDynamicObject();
            return dSource.FromDynamicObject<T>();
        }

        /// <summary>
        /// Convert Using Auto Mapper ...
        /// </summary>
        /// <param name="source"></param>
        /// <typeparam name="T"></typeparam>
        /// <typeparam name="E"></typeparam>
        /// <returns></returns>
        public static T MapConvert<T, E>(this E source)
        where T : class
        where E : class
        {
            //
            if (source.IsNull())
            {
                return null;
            }

            //
            var dMapConfig = new MapperConfiguration(b =>
            {
                b.CreateMap<T, E>()
                    .ReverseMap();
            });
            var dMapper = dMapConfig.CreateMapper();

            //
            var dSource = (object)dMapper.Map<dynamic>(source);
            var result = dMapper.Map<T>(dSource);

            //
            return result;
        }

        /// <summary>
        /// Convert Using Auto Mapper ...
        /// </summary>
        /// <param name="source"></param>
        /// <typeparam name="T"></typeparam>
        /// <typeparam name="E"></typeparam>
        /// <returns></returns>
        public static IEnumerable<T> MapConvert<T, E>(this IEnumerable<E> source)
        {
            //
            if (source.IsNull())
            {
                return null;
            }

            //
            var dMapConfig = new MapperConfiguration(b =>
            {
                b.CreateMap<T, E>()
                    .ReverseMap();
            });
            var dMapper = dMapConfig.CreateMapper();

            //
            var dSource = (object)dMapper.Map<dynamic>(source);
            var result = dMapper.Map<IEnumerable<T>>(dSource);

            //
            return result;
        }

        /// <summary>
        /// Convert Using Auto Mapper ...
        /// </summary>
        /// <param name="source"></param>
        /// <typeparam name="T"></typeparam>
        /// <typeparam name="E"></typeparam>
        /// <returns></returns>
        public static ICollection<T> MapConvert<T, E>(this ICollection<E> source)
        {
            //
            if (source.IsNull())
            {
                return null;
            }

            //
            var dMapConfig = new MapperConfiguration(b =>
            {
                b.CreateMap<T, E>()
                    .ReverseMap();
            });
            var dMapper = dMapConfig.CreateMapper();

            //
            var dSource = (object)dMapper.Map<dynamic>(source);
            var result = dMapper.Map<ICollection<T>>(dSource);

            //
            return result;
        }

        /// <summary>
        /// Convert Using Auto Mapper ...
        /// </summary>
        /// <param name="source"></param>
        /// <typeparam name="T"></typeparam>
        /// <typeparam name="E"></typeparam>
        /// <returns></returns>
        public static IList<T> MapConvert<T, E>(this IList<E> source)
        {
            //
            if (source.IsNull())
            {
                return null;
            }

            //
            var dMapConfig = new MapperConfiguration(b =>
            {
                b.CreateMap<T, E>()
                    .ReverseMap();
            });
            var dMapper = dMapConfig.CreateMapper();

            //
            var dSource = (object)dMapper.Map<dynamic>(source);
            var result = dMapper.Map<IList<T>>(dSource);

            //
            return result;
        }

        /// <summary>
        /// Convert Using Auto Mapper ...
        /// </summary>
        /// <param name="source"></param>
        /// <typeparam name="TKey"></typeparam>
        /// <typeparam name="TDest"></typeparam>
        /// <typeparam name="TSource"></typeparam>
        /// <returns></returns>
        public static IDictionary<TKey, TDest> MapConvert<TKey, TDest, TSource>(this IDictionary<TKey, TSource> source)
        {
            //
            if (source.IsNull())
            {
                return null;
            }

            //
            var dMapConfig = new MapperConfiguration(b =>
            {
                b.CreateMap<TDest, TSource>()
                    .ReverseMap();
            });
            var dMapper = dMapConfig.CreateMapper();

            //
            var dSource = (object)dMapper.Map<dynamic>(source);
            var result = dMapper.Map<IDictionary<TKey, TDest>>(dSource);

            //
            return result;
        }

        /// <summary>
        /// Convert a Type to Static Type 
        /// </summary>
        /// <param name="source"></param>
        /// <typeparam name="T"></typeparam>
        /// <returns></returns>
        public static T ToStatic<T>(this object source)
        {
            //
            var entity = Activator.CreateInstance<T>();

            //
            var properties = source as IDictionary<string, object>;

            //
            if (properties == null)
            {
                return entity;
            }

            //
            foreach (var entry in properties)
            {
                //
                var propertyInfo = entity.GetType().GetProperty(entry.Key);
                if (propertyInfo != null)
                {
                    propertyInfo.SetValue(entity, entry.Value, null);
                }
            }

            //
            return entity;
        }

        /// <summary>
        /// Convert From Json String ...
        /// </summary>
        /// <param name="value"></param>
        /// <typeparam name="T"></typeparam>
        /// <returns></returns>
        public static T FromJSON<T>(this string value)
        {
            return JsonConvert.DeserializeObject<T>(value);
        }

        /// <summary>
        /// Convert From Json String ...
        /// </summary>
        /// <param name="value"></param>
        /// <param name="type"></param>
        /// <returns></returns>
        public static object FromJSON(
            this string value,
            Type type
        )
        {
            return JsonConvert
                .DeserializeObject(value, type);
        }

        /// <summary>
        /// Search a Json String for Specific Node ...
        /// </summary>
        /// <param name="containerToken"></param>
        /// <param name="name"></param>
        /// <returns></returns>
        public static List<JToken> FindTokens(this JToken containerToken, string name)
        {
            List<JToken> matches = new List<JToken>();
            FindTokens(containerToken, name, matches);
            return matches;
        }

        /// <summary>
        /// Convert to MD5 Bytes ...
        /// </summary>
        /// <param name="source"></param>
        /// <returns></returns>
        public static byte[] ToMd5Bytes(this string source)
        {
            return new MD5CryptoServiceProvider().ComputeHash(Encoding.UTF8.GetBytes(source));
        }

        /// <summary>
        /// Convert to MD5 String ...
        /// </summary>
        /// <param name="source"></param>
        /// <returns></returns>
        public static string ToMd5String(this string source)
        {
            //
            // string representation (similar to UNIX format)
            return BitConverter.ToString(source.ToMd5Bytes())
                // without dashes
                .Replace("-", string.Empty)
                // make lowercase
                .ToLower();
        }

        /// <summary>
        /// Check a String is MD5 String or not ...
        /// </summary>
        /// <param name="source"></param>
        /// <returns></returns>
        public static bool IsMD5String(this string source)
        {
            //
            if (String.IsNullOrEmpty(source))
            {
                return false;
            }

            //
            return Regex.IsMatch(source, "^[0-9a-fA-F]{32}$", RegexOptions.Compiled);
        }

        /// <summary>
        /// Convert an string to Byte array Representation ...
        /// </summary>
        /// <param name="source"></param>
        /// <returns></returns>
        public static byte[] ToBytes(this string source)
        {
            return Encoding.UTF8.GetBytes(source);
        }

        /// <summary>
        /// Converts Byte Array to String Value ...
        /// </summary>
        /// <param name="source"></param>
        /// <returns></returns>
        public static string FromBytes(this byte[] source)
        {
            //
            var result = Encoding.UTF8.GetString(source, 0, source.Length);
            return result;
        }

        /// <summary>
        /// Check object is Null ...
        /// </summary>
        /// <param name="source"></param>
        /// <returns></returns>
        public static bool IsNull(this object source)
        {
            return source == null;
        }

        /// <summary>
        /// Check collection Has Childs ...
        /// </summary>
        /// <param name="source"></param>
        /// <typeparam name="T"></typeparam>
        /// <returns></returns>
        public static bool HasChild<T>(this IList<T> source)
        {
            return !source.IsNull() && source.Count() > 0;
        }

        /// <summary>
        /// Check collection Has Childs ...
        /// </summary>
        /// <param name="source"></param>
        /// <typeparam name="T"></typeparam>
        /// <returns></returns>
        public static bool HasChild<T>(this ICollection<T> source)
        {
            return !source.IsNull() && source.Count() > 0;
        }

        /// <summary>
        /// Check collection Has Childs ...
        /// </summary>
        /// <param name="source"></param>
        /// <typeparam name="T"></typeparam>
        /// <returns></returns>
        public static bool HasChild<T>(this IEnumerable<T> source)
        {
            return !source.IsNull() && source.Count() > 0;
        }

        /// <summary>
        /// Select Async ...
        /// </summary>
        /// <param name="source"></param>
        /// <param name="method"></param>
        /// <typeparam name="TSource"></typeparam>
        /// <typeparam name="TResult"></typeparam>
        /// <returns></returns>
        public static async Task<IEnumerable<TResult>> SelectAsync<TSource, TResult>(
            this IEnumerable<TSource> source, Func<TSource, Task<TResult>> method
        )
        {
            return await Task.WhenAll(source.Select(async s => await method(s)));
        }

        /// <summary>
        /// Converts an Enumerable to Async Enumerable ...
        /// </summary>
        /// <param name="source"></param>
        /// <param name="cancellationToken"></param>
        /// <typeparam name="T"></typeparam>
        /// <returns></returns>
        public static async IAsyncEnumerable<T> ToAsyncEnumerable<T>(
            this IEnumerable<T> source,
            [System.Runtime.CompilerServices.EnumeratorCancellation]
            CancellationToken cancellationToken = default
        )
        {
            //
            foreach (var item in source)
            {
                //
                if (cancellationToken.IsCancellationRequested)
                {
                    yield break;
                }

                //
                yield return item;
            }
        }

        /// <summary>
        /// Converts an Stream to Model AsyncEnumerator ...
        /// </summary>
        /// <param name="source"></param>
        /// <param name="cancellationToken"></param>
        /// <typeparam name="T"></typeparam>
        /// <returns></returns>
        public static async IAsyncEnumerable<T> ToModelAsyncEnumerable<T>(
            this Stream source,
            [System.Runtime.CompilerServices.EnumeratorCancellation]
            CancellationToken cancellationToken = default
        )
        {
            //
            // Validate Stream ...
            if (source.IsNull())
            {
                yield break;
            }

            //
            while (source.CanRead)
            {
                //
                var model = await source
                    .ReadModelFromStream<T>(cancellationToken);

                //
                yield return model;
            }
        }

        /// <summary>
        /// Converts an Stream to String AsyncEnumerator ...
        /// using Read Line of Stream Reader ...S
        /// </summary>
        /// <param name="source"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public static async IAsyncEnumerable<string> ToStringAsyncEnumerable(
            this Stream source,
            [System.Runtime.CompilerServices.EnumeratorCancellation]
            CancellationToken cancellationToken = default
        )
        {
            //
            // Validate Stream ...
            if (source.IsNull())
            {
                yield break;
            }

            //
            while (source.CanRead)
            {
                //
                var json = await source
                    .ReadJsonFromStream(cancellationToken);

                //
                yield return json;
            }
        }

        /// <summary>
        /// Write a Model to Stream ...
        /// </summary>
        /// <param name="source">an Stream to Write ...</param>
        /// <param name="model">a Model instance to Write ...</param>
        /// <param name="cancellationToken"></param>
        /// <typeparam name="T"></typeparam>
        /// <returns></returns>
        public static async Task WriteModelToStream<T>(
            this Stream source,
            T model,
            CancellationToken cancellationToken = default
        )
        {
            //
            // Validate Args ...
            if (source.IsNull() || model.IsNull())
            {
                return;
            }

            //
            // Extract Json of Model ...
            var json = model.ToJSON(true);

            //
            await source.WriteJsonToStream(
                json: json,
                cancellationToken: cancellationToken
            );
        }

        /// <summary>
        /// Write a Json String to Stream ...
        /// </summary>
        /// <param name="source">an Stream to Write ...</param>
        /// <param name="json">json string to write ...</param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public static async Task WriteJsonToStream(
            this Stream source,
            string json,
            CancellationToken cancellationToken = default
        )
        {
            //
            // Validate Args ...
            if (source.IsNull() || json.IsNullOrEmpty())
            {
                return;
            }

            //
            using (var streamWriter = new StreamWriter(stream: source))
            {
                //
                using (var jsonWriter = new JsonTextWriter(streamWriter))
                {
                    //
                    await jsonWriter.WriteRawAsync(json, cancellationToken);
                    await jsonWriter.FlushAsync(cancellationToken);
                }
            }
        }

        /// <summary>
        /// Read a Json Model From Stream ...
        /// </summary>
        /// <param name="source"></param>
        /// <param name="cancellationToken"></param>
        /// <typeparam name="T"></typeparam>
        /// <returns></returns>
        public static async Task<T> ReadModelFromStream<T>(
            this Stream source,
            CancellationToken cancellationToken = default
        )
        {
            //
            T result = default(T);

            //
            var json = await source.ReadJsonFromStream(cancellationToken);
            if (!json.IsNullOrEmpty())
            {
                //
                try
                {
                    result = json.FromJSON<T>();
                }
                catch
                { }
            }

            //
            return result;
        }

        /// <summary>
        /// Reading Json String From Stream ...
        /// </summary>
        /// <param name="source">an Stream to Write ...</param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public static async Task<string> ReadJsonFromStream(
            this Stream source,
            CancellationToken cancellationToken = default
        )
        {
            //
            var result = string.Empty;

            //
            // Validate Args ...
            if (source.IsNull())
            {
                return result;
            }

            //
            using (var streamReader = new StreamReader(source))
            {
                //
                result = await Task.Run(() =>
                {
                    return streamReader.ReadLine();
                },
                cancellationToken);
            }

            //
            return result;
        }

        /// <summary>
        /// Update a Collection item ...
        /// </summary>
        /// <param name="source"></param>
        /// <param name="sourceItem"></param>
        /// <param name="updateWith"></param>
        /// <typeparam name="T"></typeparam>
        /// <returns></returns>
        public static IList<T> Update<T>(
            this IList<T> source,
            T sourceItem,
            T updateWith
        )
        {
            //
            var result = new List<T>();

            //
            // Validate Args ...
            if (!source.HasChild() ||
                updateWith.IsNull() ||
                sourceItem.IsNull()
            )
            {
                return result;
            }

            //
            // Extract Item from source ...
            result = source
                .Except(new List<T>() { sourceItem })
                .ToList();
            result.Add(updateWith);

            //
            return source;
        }

        /// <summary>
        /// Update a Collection item ...
        /// </summary>
        /// <param name="source"></param>
        /// <param name="sourceItem"></param>
        /// <param name="updateWith"></param>
        /// <typeparam name="T"></typeparam>
        /// <returns></returns>
        public static ICollection<T> Update<T>(
            this ICollection<T> source,
            T sourceItem,
            T updateWith
        )
        {
            //
            var result = new List<T>();

            //
            // Validate Args ...
            if (!source.HasChild() ||
                updateWith.IsNull() ||
                sourceItem.IsNull()
            )
            {
                return result;
            }

            //
            // Extract Item from source ...
            result = source
                .Except(new List<T>() { sourceItem })
                .ToList();
            result.Add(updateWith);

            //
            return source;
        }

        /// <summary>
        /// Update a Collection item ...
        /// </summary>
        /// <param name="source"></param>
        /// <param name="sourceItem"></param>
        /// <param name="updateWith"></param>
        /// <typeparam name="T"></typeparam>
        /// <returns></returns>
        public static IEnumerable<T> Update<T>(
            this IEnumerable<T> source,
            T sourceItem,
            T updateWith
        )
        {
            //
            var result = new List<T>();

            //
            // Validate Args ...
            if (!source.HasChild() ||
                updateWith.IsNull() ||
                sourceItem.IsNull()
            )
            {
                return result;
            }

            //
            // Extract Item from source ...
            result = source
                .Except(new List<T>() { sourceItem })
                .ToList();
            result.Add(updateWith);

            //
            return source;
        }

        /// <summary>
        /// Select and Retrieve Nth Childs of given List ...
        /// </summary>
        /// <param name="source"></param>
        /// <param name="n"></param>
        /// <param name="throwException"></param>
        /// <typeparam name="T"></typeparam>
        /// <returns></returns>
        public static IEnumerable<T> GetNthItems<T>(this IList<T> source, int n, bool throwException = false)
        {
            //
            var result = new List<T>();
            if (n < 1 || n > source.Count || source.IsNull() || !source.HasChild())
            {
                if (throwException)
                {
                    throw XException.InvalidArgs.ToException();
                }
                else
                {
                    return result;
                }
            }

            //
            var index = 0;
            foreach (var item in source)
            {
                //
                result.Add(item);
                index++;

                //
                if (index >= n)
                {
                    break;
                }
            }

            //
            return result;
        }

        /// <summary>
        /// Select and Retrieve Nth Childs of given List ...
        /// </summary>
        /// <param name="source"></param>
        /// <param name="n"></param>
        /// <param name="throwException"></param>
        /// <typeparam name="T"></typeparam>
        /// <returns></returns>
        public static IEnumerable<T> GetNthItems<T>(this ICollection<T> source, int n, bool throwException = false)
        {
            return source.ToList().GetNthItems(
                n: n,
                throwException: throwException
            );
        }

        /// <summary>
        /// Select and Retrieve Nth Childs of given List ...
        /// </summary>
        /// <param name="source"></param>
        /// <param name="n"></param>
        /// <param name="throwException"></param>
        /// <typeparam name="T"></typeparam>
        /// <returns></returns>
        public static IEnumerable<T> GetNthItems<T>(this IEnumerable<T> source, int n, bool throwException = false)
        {
            return source.ToList().GetNthItems(
                n: n,
                throwException: throwException
            );
        }

        /// <summary>
        /// Check an string is Null or Empty ...
        /// </summary>
        /// <param name="sourse"></param>
        /// <returns></returns>
        public static bool IsNullOrEmpty(this string sourse)
        {
            return string.IsNullOrEmpty(sourse);
        }

        /// <summary>
        /// Get string Value Attribute of an Enum ...
        /// </summary>
        /// <param name="source"></param>
        /// <returns></returns>
        public static string GetStringValue(this Enum source)
        {
            var type = source.GetType();
            var fieldInfo = type.GetField(source.ToString());
            var attributes = fieldInfo.GetCustomAttributes(typeof(StringValueAttribute), false) as StringValueAttribute[];

            return attributes != null && attributes.Length > 0 ?
                attributes[0].StringValue : null;
        }

        /// <summary>
        /// Extracts digit's of an string ...
        /// </summary>
        /// <param name="source"></param>
        /// <returns></returns>
        public static string GetDigits(this string source)
        {
            try
            {
                //
                Regex regexObj = new Regex(@"[^\d]");
                return regexObj.Replace(source, "");
            }
            catch
            {
                return null;
            }
        }

        /// <summary>
        /// Check an string is contains only digits ...
        /// </summary>
        /// <param name="source"></param>
        /// <returns></returns>
        public static bool IsDigits(this string source)
        {
            return (source.GetDigits() != null &&
                source.GetDigits().ToString() == source);
        }

        /// <summary>
        /// Convert to normal string, Trim and ToLower ...
        /// </summary>
        /// <param name="source"></param>
        /// <returns></returns>
        public static string ToNormalString(this string source)
        {
            //
            if (source.IsNullOrEmpty())
            {
                return string.Empty;
            }

            //
            return source.Trim().ToLowerInvariant();
        }

        /// <summary>
        /// Capitalize an string ...
        /// </summary>
        /// <param name="source"></param>
        /// <returns></returns>
        public static string Capitalize(this string source)
        {
            //
            if (source.IsNullOrEmpty())
            {
                return string.Empty;
            }

            //
            var result = "";
            if (source.Length > 1)
            {
                //
                var firstCharr = source.Substring(0, 1);
                var otherParts = source.Substring(1, source.Length - 1);

                //
                result = firstCharr.ToUpperInvariant() + otherParts;
            }
            else
            {
                result = source.ToUpperInvariant();
            }

            //
            return result;
        }

        /// <summary>
        /// Summarize a Text ...
        /// </summary>
        /// <param name="source"></param>
        /// <param name="maxAllowedLength"></param>
        /// <param name="endsWith"></param>
        /// <returns></returns>
        public static string SummarizeContent(
            this string source,
            int maxAllowedLength = 0,
            string endsWith = ""
        )
        {
            //
            var result = string.Empty;
            if (source.IsNullOrEmpty() || maxAllowedLength <= 0)
            {
                //
                result = source;
                return result;
            }

            //
            // Pattern of Links ...
            var pattern = @"(?:[!]\[(.*?)\]\(.*?\))";

            //
            // Apply Summarization ...

            //
            // Replace Markdown Links using RegExp ...
            result = Regex.Replace(source, pattern, "");

            //
            // Do Summarization if Length bigger than MaxLength ...
            if (result.Length > maxAllowedLength)
            {
                result = result.Substring(0, maxAllowedLength);
            }

            //
            // Apply EndsWith if Provided ...
            if (!endsWith.IsNullOrEmpty() &&
                !result.EndsWith(endsWith))
            {
                result += endsWith;
            }

            //
            return result;
        }

        /// <summary>
        /// Check an string is a Valid Representation of PhoneNumber ...
        /// </summary>
        /// <param name="source"></param>
        /// <returns></returns>
        public static bool IsValidMobileNumber(this string source)
        {
            //
            // Validating Mobile Numbers ...
            var phoneNumberUtil = PhoneNumbers.PhoneNumberUtil.GetInstance();
            try
            {
                //
                var mPhoneNumber = phoneNumberUtil.Parse(source, null);
                if (phoneNumberUtil.IsValidNumber(mPhoneNumber))
                {
                    //
                    return true;
                }

                //
                return false;
            }
            catch
            {

                //
                return false;
            }
        }

        /// <summary>
        /// Check an string is Valid Representation of Email Address ...
        /// </summary>
        /// <param name="source"></param>
        /// <returns></returns>
        public static bool IsValidEmail(this string source)
        {
            try
            {
                var addr = new System.Net.Mail.MailAddress(source);
                return addr.Address == source;
            }
            catch
            {
                return false;
            }
        }

        /// <summary>
        /// Check an string is Valid Representation of URL Address ...
        /// </summary>
        /// <param name="url"></param>
        /// <returns></returns>
        public static bool IsValidUrl(this string url)
        {
            return Uri.IsWellFormedUriString(url, UriKind.RelativeOrAbsolute);
        }

        /// <summary>
        /// check a URL has / at the end, if not add one ...
        /// </summary>
        /// <param name="url"></param>
        /// <returns></returns>
        public static string NormalizeUrl(this string url)
        {
            return url.EndsWith("/") ? url : url + "/";
        }

        /// <summary>
        /// Check an string is GUID or not ...
        /// </summary>
        /// <param name="source"></param>
        /// <returns></returns>
        public static bool IsGuid(this string source)
        {
            //
            // Validate Args ...
            if (source.IsNullOrEmpty())
            {
                return false;
            }

            //
            Guid guid;
            var result = Guid.TryParse(source, out guid);

            //
            return result;
        }

        /// <summary>
        /// Check Specific Guid string is Default Guid or not ...
        /// </summary>
        /// <param name="guid"></param>
        /// <returns></returns>
        public static bool IsDefaultGuid(this string guid)
        {
            //
            if (!guid.IsGuid())
            {
                return false;
            }

            //
            var empty = Guid.Empty.ToString();
            return guid == empty;
        }

        /// <summary>
        /// Check Specific Guid is Default Guid or not ...
        /// </summary>
        /// <param name="guid"></param>
        /// <returns></returns>
        public static bool IsDefaultGuid(this Guid guid)
        {
            //
            var empty = Guid.Empty;
            return guid == empty;
        }

        /// <summary>
        /// Parse an String to related Enumerable Items ...
        /// </summary>
        /// <param name="source"></param>
        /// <param name="separator"></param>
        /// <typeparam name="T"></typeparam>
        /// <returns></returns>
        public static IEnumerable<T> ParseListString<T>(
            this string source,
            char? separator = null
        )
        {
            //
            if (!separator.HasValue)
            {
                separator = CommonConstants.DEFAULT_LIST_SEPERATOR;
            }

            //
            var list = source.Split(separator.Value);
            var result = new Collection<T>();

            //
            foreach (var s in list)
            {
                //
                try
                {
                    //
                    T item = (T)Convert.ChangeType(s, typeof(T));

                    //
                    result.Add(item);
                }
                catch { }
            }

            //
            return result;
        }

        /// <summary>
        /// Converts a List String Representation to GUid List ...
        /// </summary>
        /// <param name="list"></param>
        /// <param name="separator"></param>
        /// <returns></returns>
        public static IEnumerable<Guid> ParseListGuid(
            this string list,
            char? separator = null
        )
        {
            //
            var result = new List<Guid>();

            //
            if (!separator.HasValue)
            {
                separator = CommonConstants.DEFAULT_LIST_SEPERATOR;
            }

            //
            if (list.IsNullOrEmpty())
            {
                return result;
            }

            //
            var items = list.Split(separator.Value);
            items.ToList().ForEach(i =>
            {
                //
                if (!i.IsNullOrEmpty() && i.IsGuid() && !i.IsDefaultGuid())
                {
                    //
                    var gID = new Guid(i);
                    result.Add(gID);
                }
            });

            //
            return result;
        }

        /// <summary>
        /// Convert a List to List String ...
        /// </summary>
        /// <param name="source"></param>
        /// <param name="separator"></param>
        /// <typeparam name="T"></typeparam>
        /// <returns></returns>
        public static string ToListString<T>(
            this IEnumerable<T> source,
            char? separator = null
        )
        {
            //
            if (!separator.HasValue)
            {
                separator = CommonConstants.DEFAULT_LIST_SEPERATOR;
            }

            //
            if (!source.HasChild())
            {
                return string.Empty;
            }

            //
            string result = String.Join(
                separator
                .ToString(),
                source
            );

            //
            return result;
        }

        /// <summary>
        /// get default value of a Type
        /// </summary>
        /// <param name="source"></param>
        /// <typeparam name="T"></typeparam>
        /// <returns></returns>
        public static T Default<T>(this T source)
        where T : class
        {
            return default(T);
        }

        /// <summary>
        /// Check if an object is Null or Default Value
        /// </summary>
        /// <param name="source"></param>
        /// <typeparam name="T"></typeparam>
        /// <returns></returns>
        public static bool IsNullOrDefault<T>(this T source)
        where T : class
        {
            return Equals(source, default(T));
        }

        /// <summary>
        /// convert a timestamp to ISO String representation ...
        /// </summary>
        /// <param name="timestamp"></param>
        /// <returns></returns>
        public static string ISODateString(this long timestamp)
        {
            //
            var time = timestamp.FromTimestamp();
            var result = time.ToString("o");

            //
            return result;
        }

        /// <summary>
        /// Converts a DateTime to Unix Like Long ...
        /// </summary>
        /// <param name="source"></param>
        /// <returns></returns>
        public static long ToTimestamp(
            this DateTime source
        )
        {
            return new DateTimeOffset(source)
                .ToUnixTimeMilliseconds();
        }

        /// <summary>
        /// convert timestamp to DateTime ...
        /// </summary>
        /// <param name="timestamp"></param>
        /// <returns></returns>
        public static DateTime FromTimestamp(this long timestamp)
        {
            //
            var result = DateTimeOffset.FromUnixTimeMilliseconds(timestamp);
            return result.DateTime;
        }
        public static DateTime FromTimestamp(this string source)
        {
            //
            var timestamp = Int64.Parse(source);
            var time = timestamp.FromTimestamp();
            return time;
        }

        /// <summary>
        /// Check a Date Time is Expired or not
        /// </summary>
        /// <param name="source"></param>
        /// <returns></returns>
        public static bool IsExPired(this DateTime source)
        {
            //
            if (source.IsNull())
            {
                return true;
            }

            //
            var currentDate = DateTime.UtcNow;
            var isExpired = currentDate >= source;

            //
            return isExpired;
        }
        public static bool IsExpired(this long source)
        {
            var time = source.FromTimestamp();
            return time.IsExPired();
        }
        public static bool IsExpired(this string source)
        {
            //
            var time = DateTime.Parse(source);
            return time.IsExPired();
        }

        /// <summary>
        /// Determines a File Type is Image Kind or not
        /// </summary>
        /// <param name="source"></param>
        /// <returns></returns>
        public static bool IsImageKind(this XFileType source)
        {
            //
            var imageKind = new Collection<XFileType>() {
                XFileType.Image,
                XFileType.CoverImage,
                XFileType.ProfileImasge
            };

            //
            return imageKind.Contains(source);
        }

        /// <summary>
        /// Encode String as Url
        /// </summary>
        /// <param name="source"></param>
        /// <returns></returns>
        public static string ToUrlEncoded(this string source)
        {
            return HttpUtility.UrlEncode(source);
        }

        /// <summary>
        /// Decode Url String
        /// </summary>
        /// <param name="source"></param>
        /// <returns></returns>
        public static string ToUrlDecoded(this string source)
        {
            return HttpUtility.UrlDecode(source);
        }

        /// <summary>
        /// Convert an Object to string for use in HttpParams 
        /// </summary>
        /// <param name="value"></param>
        /// <param name="cultureInfo"></param>
        /// <returns></returns>
        public static string ToHttpParamString(this object value, CultureInfo cultureInfo)
        {
            //
            if (value is Enum)
            {
                //
                string name = Enum.GetName(value.GetType(), value);
                if (name != null)
                {
                    //
                    var field = IntrospectionExtensions
                        .GetTypeInfo(value.GetType())
                        .GetDeclaredField(name);

                    //
                    if (field != null)
                    {
                        //
                        var attribute = CustomAttributeExtensions
                            .GetCustomAttribute(field, typeof(EnumMemberAttribute))
                        as EnumMemberAttribute;

                        //
                        if (attribute != null)
                        {
                            return attribute.Value != null ? attribute.Value : name;
                        }
                    }
                }
            }
            else if (value is bool)
            {
                return System.Convert.ToString(value, cultureInfo).ToLowerInvariant();
            }
            else if (value is byte[])
            {
                return System.Convert.ToBase64String((byte[])value);
            }
            else if (value != null && value.GetType().IsArray)
            {
                //
                var array = Enumerable.OfType<object>((Array)value);
                return string.Join(",", Enumerable
                    .Select(
                        array,
                        o => o.ToHttpParamString(cultureInfo)));
            }

            //
            return System.Convert.ToString(value, cultureInfo);
        }

        /// <summary>
        /// ReShape an Object as HttpParam String
        /// </summary>
        /// <param name="value"></param>
        /// <returns></returns>
        public static string AsHttpParamString(this object value)
        {
            return System.Uri
                .EscapeDataString(value
                    .ToHttpParamString(CultureInfo.InvariantCulture));
        }

        /// <summary>
        /// Calculating Date Difference Provider String
        /// and Generate Date based on UTC Time in Milliseconds like unix Date ...
        /// </summary>
        /// <param name="offsetProvider"></param>
        /// <returns></returns>
        public static long GenerateDateTimeOffset(this string offsetProvider)
        {
            //
            if (offsetProvider.IsNullOrEmpty())
            {
                return 0;
            }

            //
            var mExpireValue = 0;
            var mExpireValueStr = offsetProvider.GetDigits();
            var mExpireUnit = offsetProvider.Replace(mExpireValueStr, "");
            if (mExpireValueStr.IsNullOrEmpty() || mExpireUnit.IsNullOrEmpty())
            {
                return 0;
            }

            //
            var isParsed = int.TryParse(mExpireValueStr, out mExpireValue);
            if (!isParsed)
            {
                return 0;
            }

            //
            DateTime? date = null;
            switch (mExpireUnit)
            {
                case "d":
                    date = DateTime.UtcNow.AddDays(mExpireValue);
                    break;

                case "h":
                    date = DateTime.UtcNow.AddHours(mExpireValue);
                    break;

                case "m":
                    date = DateTime.UtcNow.AddMinutes(mExpireValue);
                    break;

                case "s":
                    date = DateTime.UtcNow.AddSeconds(mExpireValue);
                    break;

                case "ms":
                default:
                    date = DateTime.UtcNow.AddMilliseconds(mExpireValue);
                    break;
            }

            //
            var result = !date.HasValue ? 0 : new DateTimeOffset(date.Value)
                .ToUnixTimeMilliseconds();

            //
            return result;
        }

        //
        #region Int Id Extensions ...
        public static bool IsValidIntId(this int source)
        {
            return source > 0;
        }

        public static void ValidateIntId(this int source)
        {
            //
            if (!source.IsValidIntId())
            {
                XException.InvalidArgs.Throw();
            }
        }
        #endregion

        //
        #region StringExtensions for Identity Server ...
        public static string EnsureTrailingSlash(this string input)
        {
            if (!input.EndsWith("/"))
            {
                return input + "/";
            }

            return input;
        }

        public static bool IsMissing(this string value)
        {
            return string.IsNullOrWhiteSpace(value);
        }

        public static bool IsPresent(this string value)
        {
            return !string.IsNullOrWhiteSpace(value);
        }

        public static string Sha256(this string input)
        {
            if (input.IsMissing()) return string.Empty;

            using (var sha = SHA256.Create())
            {
                var bytes = Encoding.UTF8.GetBytes(input);
                var hash = sha.ComputeHash(bytes);

                return Convert.ToBase64String(hash);
            }
        }
        #endregion

        //
        #region Private ...
        private static void FindTokens(JToken containerToken, string name, List<JToken> matches)
        {
            if (containerToken.Type == JTokenType.Object)
            {
                foreach (JProperty child in containerToken.Children<JProperty>())
                {
                    if (child.Name == name)
                    {
                        matches.Add(child.Value);
                    }
                    FindTokens(child.Value, name, matches);
                }
            }
            else if (containerToken.Type == JTokenType.Array)
            {
                foreach (JToken child in containerToken.Children())
                {
                    FindTokens(child, name, matches);
                }
            }
        }
        #endregion        
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xCommons\Extensions\DIExtensions.cs

using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Mvc;
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>
        /// <param name="addDefaultValueFilter"></param>
        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);
            }

            //
            // Handle RequireXPowered Filter ...
            if (addRequiredXPoweredFilter) {
                source.OperationFilter<RequireXPoweredOperationFilter> ();
            }

            //
            // Add Default Values Filter ...
            if (addDefaultValueFilter) {
                source.OperationFilter<SwaggerDefaultValuesOperationFilter> ();
            }

            //
            // 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>
        /// <param name="addDefaultValueFilter"></param>
        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 ...
        }

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

        /// <summary>
        /// Register Api V1 Versioning ...
        /// </summary>
        /// <param name="services"></param>
        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;
            });            
        }
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xCommons\Extensions\EnumExtensions.cs

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

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xCommons\Extensions\ExceptionExtensions.cs

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

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xCommons\Extensions\FilterExtensions.cs

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

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xCommons\Extensions\IConfigurationExtensions.cs

using System.Collections.Generic;
using System.Linq;
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>();
        }
    
        /// <summary>
        /// Converts a ConfigurationSection to object Representation ...
        /// </summary>
        /// <param name="section"></param>
        /// <returns></returns>
        public static object ToObject(this IConfigurationSection section)
        {
            //
            // an Inner Function for Create Recursive Parsing ...
            object ConvertSection(IConfigurationSection sec)
            {
                //
                var children = sec
                    .GetChildren()
                    .ToList();
                if (!children.Any())
                {
                    return sec.Value ?? string.Empty;
                }

                //
                // Detect Array Like Sections ...
                bool isArray = children.All(ch => int.TryParse(ch.Key, out _));
                if (isArray)
                {
                    //
                    return children
                        .OrderBy(c => int.Parse(c.Key))
                        .Select(ConvertSection)
                        .ToList();
                }

                //
                // Otherwise ...
                return children
                    .ToDictionary(
                        c => c.Key,
                        c => ConvertSection(c)
                    );
            }

            //
            // Try to Parse using Inner Function ...
            var result = ConvertSection(section);

            //
            return result;
        }

        /// <summary>
        /// Converts a ConfigurationSection to Json Representation ... 
        /// </summary>
        /// <param name="section"></param>
        /// <returns></returns>
        public static string ToJSON(this IConfigurationSection section)
        {
            //
            // Try to Parse using Inner Function ...
            var obj = section.ToObject();

            //
            // Convert it to Json ...
            var result = obj.ToJSON();

            //
            return result;
        }

        /// <summary>
        /// Get a Configuration Section as Object ... 
        /// </summary>
        /// <param name="source"></param>
        /// <param name="section"></param>
        /// <returns></returns>
        public static object GetSectionAsObject(
            this IConfiguration source,
            string section
        )
        {
            //
            object result = null;

            //
            if (!section.IsNullOrEmpty())
            {
                //
                var sec = source.GetSection(section);
                if (!sec.IsNull())
                {
                    result = sec.ToObject();
                }
            }

            //
            return result;
        }

        /// <summary>
        /// Retrieve a Configuration Section as Json String ...
        /// </summary>
        /// <param name="source"></param>
        /// <param name="section"></param>
        /// <returns></returns>
        public static string GetSectionAsJson(
            this IConfiguration source,
            string section
        )
        {
            //
            var result = string.Empty;

            //
            // Retrieve Secion as Object ...
            var obj = source.GetSectionAsObject(section);
            if (!obj.IsNull())
            {
                //
                // Converts Section Object to Json ...
                result = obj.ToJSON();
            }

            //
            return result;
        }    
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xCommons\Extensions\IFormFileExtensions.cs

using System;
using System.IO;
using System.Linq;
using System.Text;
using UglyToad.PdfPig;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Http;
using xCommons.Extensions;

namespace xAiModels.Extensions
{
    public static class IFormFileExtensions
    {
        /// <summary>
        /// Read a IFormFile Content as byte array ...
        /// </summary>
        /// <param name="source"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public static async Task<byte[]> ReadAsBytes(
            this IFormFile source,
            CancellationToken cancellationToken = default
        )
        {
            //
            // Create and use a Memory Stream ...
            using var stream = new MemoryStream();

            //
            // Copy File Content to Stream ...
            await source.CopyToAsync(
                target: stream,
                cancellationToken: cancellationToken
            );

            //
            // Read Stream Content as byte array ...
            var result = stream.ToArray();

            //
            return result;
        }

        /// <summary>
        /// Read a File Content by it's Path as byte array ...
        /// </summary>
        /// <param name="filePath"></param>
        /// <param name="bufferSize"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        /// <exception cref="Exception"></exception>
        public static async Task<byte[]> ReadAsBytes(
            this string filePath,
            int bufferSize = 81920,
            CancellationToken cancellationToken = default
        )
        {
            //
            if (string.IsNullOrWhiteSpace(filePath))
            {
                throw new Exception("Invalid Args ...");
            }

            //
            // Create and use a Memory Stream ...
            using var memStream = new MemoryStream();

            //
            using var stream = new FileStream(
                path: filePath,
                mode: FileMode.Open,
                access: FileAccess.Read,
                share: FileShare.ReadWrite
            );

            //
            // Copy File Content to Stream ...
            await stream.CopyToAsync(
                destination: memStream,
                bufferSize: bufferSize,
                cancellationToken: cancellationToken
            );

            //
            // Read Stream Content as byte array ...
            var result = memStream.ToArray();

            //
            return result;
        }

        /// <summary>
        /// Read Text Content of Document ...
        /// </summary>
        /// <param name="source"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public static async Task<string> ReadContent(
            this IFormFile source,
            CancellationToken cancellationToken = default
        )
        {
            //
            // Check if File PDF or not ...
            var isPDF = source.ContentType
                .ToNormalString()
                .Contains("pdf"
                    .ToNormalString());

            //
            var result = string.Empty;

            //
            var isValidFileType = isPDF;
            if (!isValidFileType)
            {
                return result;
            }

            //
            if (isPDF)
            {
                //
                // Reading File Content as Byte array ...
                var fileBytes = await source.ReadAsBytes(cancellationToken);

                //
                // Create a PDF Document ...
                using var stream = new MemoryStream(fileBytes);
                using var document = PdfDocument.Open(stream);

                //
                // Extract PDF Text ...
                var textBuilder = new StringBuilder();
                foreach (var page in document.GetPages())
                {
                    textBuilder.Append(page.Text);
                }

                //
                result = textBuilder.ToString();
            }

            //
            return result;
        }
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xCommons\Extensions\ModelExtensions.cs

using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.Linq.Expressions;
using System.Reflection;

namespace xCommons.Extensions
{
    public static partial class ModelExtensions
    {
        /// <summary>
        /// Retrieve a Binding Flag for Retrieve all Instance Members including
        /// Priate and Public ...
        /// </summary>
        /// <returns></returns>
        public static BindingFlags GetDefaultBindingFlag()
        {
            return BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic;
        }

        /// <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 a Class is Contains a Property or not ...
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="source"></param>
        /// <param name="property"></param>
        /// <param name="bindingAttr"></param>
        /// <returns></returns>
        public static bool HasProperty<T>(
            this T source,
            string property,
            BindingFlags bindingAttr = BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic
        )
        where T : class
        {
            //
            var result = source
                .GetType()
                .GetProperties(bindingAttr)
                .Any(prop => prop.Name == property); ;

            //
            return result;
        }

        /// <summary>
        /// Check a Class is Contains a field or not ...
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="source"></param>
        /// <param name="field"></param>
        /// <param name="bindingAttr"></param>
        /// <returns></returns>
        public static bool HasField<T>(
            this T source,
            string field,
            BindingFlags bindingAttr = BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic
        )
        where T : class
        {
            //
            var result = source
                .GetType()
                .GetFields(bindingAttr)
                .Any(fld => fld.Name == field);

            //
            return result;
        }

        /// <summary>
        /// Check a Class is Contains a Method or not ...
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="source"></param>
        /// <param name="method"></param>
        /// <param name="bindingAttr"></param>
        /// <returns></returns>
        public static bool HasMethod<T>(
            this T source,
            string method,
            BindingFlags bindingAttr = BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic
        )
        where T : class
        {
            //
            var result = source
                .GetType()
                .GetMethods(bindingAttr)
                .Any(mthd => mthd.Name == method);

            //
            return result;
        }

        /// <summary>
        /// Retrieve a Class Properties Names ...
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="source"></param>
        /// <param name="bindingAttr"></param>
        /// <returns></returns>
        public static string[] GetPropertiesNames<T>(
            this T source,
            BindingFlags bindingAttr = BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic
        )
        {
            //
            var result = source
                .GetType()
                .GetProperties(bindingAttr)
                .Select(p => p.Name)
                .ToArray();

            //
            return result;
        }

        /// <summary>
        /// Retrieve a Class Fields Names ...
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="source"></param>
        /// <param name="bindingAttr"></param>
        /// <returns></returns>
        public static string[] GetFieldsNames<T>(
            this T source,
            BindingFlags bindingAttr = BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic
        )
        {
            //
            var result = source
                .GetType()
                .GetFields(bindingAttr)
                .Select(p => p.Name)
                .ToArray();

            //
            return result;
        }

        /// <summary>
        /// Retrieve a Class Methods Names ...
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="source"></param>
        /// <param name="bindingAttr"></param>
        /// <returns></returns>
        public static string[] GetMethodsNames<T>(
            this T source,
            BindingFlags bindingAttr = BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic
        )
        {
            //
            var result = source
                .GetType()
                .GetMethods(bindingAttr)
                .Select(p => p.Name)
                .ToArray();

            //
            return result;
        }

        /// <summary>
        /// Retrieve a Class Members Names ...
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="source"></param>
        /// <param name="bindingAttr"></param>
        /// <returns></returns>
        public static string[] GetMembersNames<T>(
            this T source,
            BindingFlags bindingAttr = BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic
        )
        {
            //
            var result = source
                .GetType()
                .GetMembers(bindingAttr)
                .Select(p => p.Name)
                .ToArray();

            //
            return result;
        }

        /// <summary>
        /// Get a Class Property Value using Generic Concept ...
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <typeparam name="TProp"></typeparam>
        /// <param name="source"></param>
        /// <param name="property"></param>
        /// <param name="bindingAttr"></param>
        /// <returns></returns>
        public static TProp GetProperty<T, TProp>(
            this T source,
            string property,
            BindingFlags bindingAttr = BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic
        )
        where T : class
        {
            //
            TProp result = default;

            //
            // Check if T Has Property ...
            if (source.HasProperty(property))
            {
                //
                // Access Property ...
                var prop = source
                    .GetType()
                    .GetProperty(
                        property, 
                        bindingAttr
                    );

                //
                // Retrieve Property Value as Object ...
                var propVal = prop.GetValue(source);

                //
                result = (TProp)propVal;
            }

            //
            return result;
        }

        /// <summary>
        /// Get a Class Field Value using Generic Concept ...
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <typeparam name="TField"></typeparam>
        /// <param name="source"></param>
        /// <param name="field"></param>
        /// <param name="bindingAttr"></param>
        /// <returns></returns>
        public static TField GetField<T, TField>(
            this T source,
            string field,
            BindingFlags bindingAttr = BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic
        )
        where T : class
        {
            //
            TField result = default;

            //
            if (source.HasField(field))
            {
                //
                var fld = source
                    .GetType()
                    .GetField(
                        field,
                        bindingAttr
                    );

                //
                var fieldVal = fld.GetValue(source);
                result = (TField)fieldVal;
            }

            //
            return result;
        }

        /// <summary>
        /// Set a Class Property Value using Generic Concept ...
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <typeparam name="TProp"></typeparam>
        /// <param name="source"></param>
        /// <param name="property"></param>
        /// <param name="value"></param>
        /// <param name="bindingAttr"></param>
        /// <returns></returns>
        public static bool SetProperty<T, TProp>(
            this T source,
            string property,
            TProp value,
            BindingFlags bindingAttr = BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic
        )
        where T : class
        {
            //
            // Check T Has Property ...
            var result = source.HasProperty(property);
            if (!result)
            {
                return result;
            }

            //
            // Access Property ...
            var prop = source
                .GetType()
                .GetProperty(
                    property,
                    bindingAttr
                );

            //
            // Set Property ...
            try
            {
                //
                result = true;
                prop.SetValue(source, value);
            }
            catch
            {
                result = false;
            }

            //
            return result;
        }

        /// <summary>
        /// Set a Class Field Value using Generic Concept ...
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <typeparam name="TField"></typeparam>
        /// <param name="source"></param>
        /// <param name="field"></param>
        /// <param name="value"></param>
        /// <param name="bindingAttr"></param>
        /// <returns></returns>
        public static bool SetField<T, TField>(
            this T source,
            string field,
            TField value,
            BindingFlags bindingAttr = BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic
        )
        where T : class
        {
            //
            // Check T Has Field ...
            var result = source.HasField(field);
            if (!result)
            {
                return result;
            }

            //
            // Access Field ...
            var fld = source
                .GetType()
                .GetField(
                    field,
                    bindingAttr
                );

            //
            // Set Value ...
            try
            {
                //
                result = true;
                fld.SetValue(source, value);
            }
            catch
            {
                result = false;
            }

            //
            return result;
        }

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

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xCommons\Extensions\ServiceProviderExtensions.cs

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

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xCommons\Extensions\XHttpContextExtensions.cs

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

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xCommons\Extensions\XMiddlewareExtensions.cs

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

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xCommons\Filters\RequireXPoweredOperationFilter.cs

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

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xCommons\Filters\SwaggerDefaultValuesOperationFilter.cs

using System.Linq;
using Microsoft.OpenApi.Any;
using Microsoft.OpenApi.Models;
using Swashbuckle.AspNetCore.SwaggerGen;
using xCommons.Configurations;
using xCommons.Extensions;

namespace xCommons.Filters
{
    public class SwaggerDefaultValuesOperationFilter : IOperationFilter
    {
        private readonly XSwaggerConfiguration config;

        public SwaggerDefaultValuesOperationFilter(
            XSwaggerConfiguration config
        )
        {
            this.config = config;
        }

        public void Apply(
            OpenApiOperation operation,
            OperationFilterContext context
        )
        {
            //
            // Validate Configuration ...
            if (
                !config.IsNull() &&
                !config.DefaultValues.IsNull() &&
                config.DefaultValues.HasChild()
            )
            {
                //                
                foreach (var prv in config.DefaultValues)
                {
                    //
                    // Detect Parameter ...
                    var swaggerParam = operation.Parameters.FirstOrDefault(p => p.Name == prv.Key);
                    if (!swaggerParam.IsNull())
                    {
                        swaggerParam.Schema.Default = new OpenApiString(prv.Value);
                    }
                }
            }
        }
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xCommons\Helpers\ObjectHelper.cs

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

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xCommons\Helpers\XDateHelper.cs

using System;

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

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xCommons\Helpers\XGenericHelper.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using xCommons.Extensions;

namespace xCommons.Helpers
{
    public static class XGenericHelper
    {
        /// <summary>
        /// Invoke a Generic Method of Specified Type ...
        /// </summary>
        /// <param name="source"></param>
        /// <param name="methodName"></param>
        /// <param name="runtimeType"></param>
        /// <param name="args"></param>
        public static void InvokeGenericMethod(
            this Type source,
            string methodName,
            Type runtimeType,
            params object[] args
        )
        {
            //
            source.InvokeGenericMethod<object>(
                args: args,
                methodName: methodName,
                runtimeType: runtimeType
            );
        }

        /// <summary>
        /// Invoke a Generic Method of Specified Type ...
        /// </summary>
        /// <typeparam name="TResponse"></typeparam>
        /// <param name="source"></param>
        /// <param name="methodName"></param>
        /// <param name="runtimeType"></param>
        /// <param name="args"></param>
        /// <returns></returns>
        public static TResponse InvokeGenericMethod<TResponse>(
            this Type source,
            string methodName,
            Type runtimeType,
            params object[] args
        )
        {
            //
            var overLoads = source.GetGenericMethodInfo(
                methodName: methodName
            );
            if (!overLoads.HasChild())
            {
                return default;
            }

            //
            var method = overLoads.ElementAt(0);
            MethodInfo genericMethod = method.MakeGenericMethod(runtimeType);

            //
            var resultObj = genericMethod.Invoke(null, args);
            var result = (TResponse)resultObj;

            //
            return result;
        }

        /// <summary>
        /// Invoke a Generic Method of Specified Type ...
        /// </summary>
        /// <param name="source"></param>
        /// <param name="methodName"></param>
        /// <param name="runtimeTypes"></param>
        /// <param name="args"></param>
        public static void InvokeGenericMethod(
            this Type source,
            string methodName,
            Type[] runtimeTypes,
            params object[] args
        )
        {
            //
            source.InvokeGenericMethod<object>(
                args: args,
                methodName: methodName,
                runtimeTypes: runtimeTypes
            );
        }

        /// <summary>
        /// Invoke a Generic Method of Specified Type ...
        /// </summary>
        /// <typeparam name="TResponse"></typeparam>
        /// <param name="source"></param>
        /// <param name="methodName"></param>
        /// <param name="runtimeTypes"></param>
        /// <param name="args"></param>
        /// <returns></returns>
        public static TResponse InvokeGenericMethod<TResponse>(
            this Type source,
            string methodName,
            Type[] runtimeTypes,
            params object[] args
        )
        {
            //
            var overLoads = source.GetGenericMethodInfo(
                methodName: methodName
            );
            if (!overLoads.HasChild())
            {
                return default;
            }

            //
            // Detect a Method by Generic Types ...
            // var method = overLoads.ElementAt(0);
            var method = overLoads.First(m => m.GetGenericArguments().Length == runtimeTypes.Length);
            MethodInfo genericMethod = method.MakeGenericMethod(runtimeTypes);

            //
            var resultObj = genericMethod.Invoke(null, args);
            var result = resultObj.ConvertTo<TResponse>();

            //
            return result;
        }

        /// <summary>
        /// Extract a Generic Method's Overloads ...
        /// </summary>
        /// <param name="source"></param>
        /// <param name="methodName"></param>
        /// <returns></returns>
        public static List<MethodInfo> GetGenericMethodInfo(
            this Type source,
            string methodName
        )
        {
            //
            var methods = source
                .GetMethods();

            //
            var result = methods
                .Where(mi =>
                    mi.Name == methodName &&
                    mi.IsGenericMethodDefinition)
                .ToList();

            //
            return result;
        }
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xCommons\Helpers\XMLToJSONHelper.cs

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

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xCommons\Helpers\XNetworkHelper.cs

using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Net.NetworkInformation;
using System.Net.Sockets;
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;
        }
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xCommons\Helpers\XOsHelper.cs

using System;
using System.Diagnostics;
using System.Runtime.InteropServices;
using System.Threading.Tasks;
using xCommons.Extensions;
using xExceptions.Attributes;
using xExceptions.Constants;

namespace xCommons.Helpers
{
    /// <summary>
    /// Several OS Type ...
    /// </summary>
    public enum XOSType
    {
        [StringValue("Unknown")]
        XUnknown,

        [StringValue("Mac")]
        XMacOs,

        [StringValue("Linux")]
        XLinux,

        [StringValue("Windows")]
        XWindows,

        [StringValue("FreeBSD")]
        XFreeBSD,
    }

    /// <summary>
    /// OS Command Execution Result ...
    /// </summary>
    public class XOSCMDResult
    {
        /// <summary>
        /// Execution Result ...
        /// </summary>
        /// <value></value>
        public string Result { get; set; }

        /// <summary>
        /// Execution Error ...
        /// </summary>
        /// <value></value>
        public string Error { get; set; }
    }

    /// <summary>
    /// a Helper Class which Provides OS Command Executions ...
    /// </summary>
    public static partial class XOsHelper
    {
        /// <summary>
        /// Retrieve OS Type ...
        /// </summary>
        /// <returns></returns>
        public static XOSType GetOSType()
        {
            //
            XOSType result = XOSType.XUnknown;

            //
            if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX))
            {
                result = XOSType.XMacOs;
            }
            else if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux))
            {
                result = XOSType.XLinux;
            }
            else if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
            {
                result = XOSType.XWindows;
            }
            // else if (RuntimeInformation.IsOSPlatform(OSPlatform.FreeBSD))
            // {
            //     result = XOSType.XFreeBSD;
            // }

            //
            return result;
        }

        /// <summary>
        /// Retrieve OS Description ...
        /// </summary>
        /// <returns></returns>
        public static string GetOSDescription()
        {
            //
            var result = RuntimeInformation.OSDescription;
            return result;
        }

        /// <summary>
        /// Execute an Specified Command ...
        /// </summary>
        /// <param name="cmd">Specified Command</param>
        /// <param name="args">Command Arguments</param>
        /// <returns></returns>
        public static async Task<XOSCMDResult> Execute(
            string cmd,
            string args
        )
        {
            //
            var result = new XOSCMDResult
            {
                Error = "Unknown",
            };

            //
            try
            {
                //
                // Validate CMD ...
                var isValid = !cmd.IsNullOrEmpty();
                if (!isValid)
                {
                    XException.InvalidArgs.Throw();
                }

                //
                // Validate OS Type ...
                XOSType osType = GetOSType();
                isValid = osType != XOSType.XUnknown;
                if (!isValid)
                {
                    XException.InvalidArgs.Throw();
                }

                //
                return await Task.Run<XOSCMDResult>(() =>
                {
                    //
                    ProcessStartInfo psi = new ProcessStartInfo();

                    //
                    psi.FileName = cmd;
                    psi.Arguments = args;
                    psi.UseShellExecute = false;
                    psi.RedirectStandardError = true;
                    psi.RedirectStandardOutput = true;

                    //
                    Process process = Process.Start(psi);

                    //
                    // Read the output
                    string output = process.StandardOutput.ReadToEnd();
                    string error = process.StandardError.ReadToEnd();

                    //
                    process.WaitForExit();

                    //
                    result = new XOSCMDResult
                    {
                        Error = error,
                        Result = output,
                    };

                    //
                    return result;
                });
            }
            catch (Exception ex)
            {
                result.Error = ex.Message;
            }

            //
            return result;
        }
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xCommons\Helpers\XReflectionHelper.cs

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

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xCommons\Interfaces\IXCipher.cs

namespace xCommons.Interfaces
{
    public interface IXCipher
    {
        string Encrypt(string plainText);
        string Decrypt(string cipherText);
        string EncryptFromBytes(byte[] textBytes);
        string DecryptFromBytes(byte[] cipherBytes);
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xCommons\Middlewares\XRequestLogger.cs

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

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xCommons\Models\XCertificate.cs

namespace xCommons.Models {
    public partial class XCertificate {
        public string Path { get; set; }
        public string Secret { get; set; }
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xCommons\Models\XLoggerModel.cs

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

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xCommons\Models\XNetworkInfo.cs

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

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xCommons\Models\XServiceDescriptor.cs

using System;

namespace xCommons.Models
{
    public class XServiceDescriptor
    {
        public Type Service { get; set; }
        public Type Implementation { get; set; }
    }

    public class XServiceDescriptor<TService, TImplmentation> : XServiceDescriptor
    {
        public XServiceDescriptor() : base()
        {
            Service = typeof(TService);
            Implementation = typeof(TImplmentation);
        }
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xCommons\Providers\XCipher.cs

using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Security.Cryptography;
using System.Text;
using System.Threading.Tasks;
using xCommons.Extensions;
using xCommons.Interfaces;

namespace xCommons.Providers
{
    public class XCipher : IXCipher
    {
        //
        #region Props ...
        private readonly string secretKey;
        private readonly byte[] iv;
        private readonly byte[] key;
        private readonly XValidationProvider validationProvider;
        #endregion

        //
        #region Constructor ...
        public XCipher(
            string cipherKey,
            XValidationProvider validationProvider
        )
        {
            //
            this.secretKey = cipherKey.ToMd5String();
            this.validationProvider = validationProvider;

            //
            var ivBytes = new byte[16];
            var keyBytes = new byte[32];
            var secretBytes = Encoding.UTF8.GetBytes(this.secretKey);

            //
            Array.Copy(
                secretBytes,
                ivBytes,
                secretBytes.Length < ivBytes.Length ?
                secretBytes.Length :
                ivBytes.Length
            );
            this.iv = ivBytes;

            //
            Array.Copy(
                secretBytes,
                keyBytes,
                secretBytes.Length < keyBytes.Length ?
                secretBytes.Length :
                keyBytes.Length
            );
            this.key = keyBytes;

            // Encoding.UTF8.GetBytes (this.secretKey);
        }
        #endregion

        //
        #region Actions ...
        public string Encrypt(string plainText)
        {
            //
            validationProvider.NotEmpty(plainText);

            //
            var textBytes = Encoding.UTF8.GetBytes(plainText);
            var result = EncryptFromBytes(textBytes);

            //
            return result;
        }

        public string Decrypt(string cipherText)
        {
            //
            validationProvider.NotEmpty(cipherText);

            //
            var cipherBytes = Convert.FromBase64String(cipherText);
            var result = DecryptFromBytes(cipherBytes);

            //
            return result;
        }

        public string EncryptFromBytes(byte[] textBytes)
        {
            //
            // Validate Args ...
            validationProvider.NotNull(textBytes);

            // Declare the string used to hold
            // the decrypted text.
            byte[] encryptedBytes = null;

            // Create an RijndaelManaged object
            // with the specified key and IV.
            using (var rijAlg = new RijndaelManaged())
            {
                //Settings
                rijAlg.Mode = CipherMode.CBC;
                rijAlg.Padding = PaddingMode.PKCS7;
                // rijAlg.FeedbackSize = 128;

                rijAlg.Key = key;
                rijAlg.IV = iv;

                //
                using (var encryptor = rijAlg.CreateEncryptor(rijAlg.Key, rijAlg.IV))
                {
                    encryptedBytes = encryptor.TransformFinalBlock(textBytes, 0, textBytes.Length);
                }
            }

            //
            return Convert.ToBase64String(encryptedBytes);
        }

        public string DecryptFromBytes(byte[] cipherBytes)
        {
            //
            // Validate Args ...
            validationProvider.NotNull(cipherBytes);

            // Declare the string used to hold
            // the decrypted text.
            string plaintext = null;

            // Create an RijndaelManaged object
            // with the specified key and IV.
            using (var rijAlg = new RijndaelManaged())
            {
                //Settings
                rijAlg.Mode = CipherMode.CBC;
                rijAlg.Padding = PaddingMode.PKCS7;
                // rijAlg.FeedbackSize = 128;

                rijAlg.Key = key;
                rijAlg.IV = iv;

                // Create a decrytor to perform the stream transform.
                var decryptor = rijAlg.CreateDecryptor(rijAlg.Key, rijAlg.IV);

                // Create the streams used for decryption.
                using (var msDecrypt = new MemoryStream(cipherBytes))
                {
                    using (var csDecrypt = new CryptoStream(msDecrypt, decryptor, CryptoStreamMode.Read))
                    {
                        using (var srDecrypt = new StreamReader(csDecrypt))
                        {
                            // Read the decrypted bytes from the decrypting stream
                            // and place them in a string.
                            plaintext = srDecrypt.ReadToEnd();
                        }
                    }
                }
            }

            //
            return plaintext;
        }
        #endregion        
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xCommons\Providers\XValidationProvider.cs

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    

    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xDataService\Configuration\XDataBaseConfiguration.cs

using System.Collections.Generic;
using xDataService.Constants;

namespace xDataService.Configuration
{
    /// <summary>
    /// Describe a Database ...
    /// </summary>
    public class XDataBaseConfiguration
    {
        /// <summary>
        /// Provider Type ...
        /// </summary>
        /// <value></value>
        public XDbProviders Provider { get; set; }

        /// <summary>
        /// Connection String which provide Requires Data to Connect to Db Provider ...
        /// </summary>
        /// <value></value>
        public string ConnectionString { get; set; }

        /// <summary>
        /// Holds Seeding items ...
        /// nameof(TEntity) => TEntity
        /// </summary>
        public IDictionary<string, List<object>> SeedItems { get; set; } = new Dictionary<string, List<object>>();
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xDataService\Configuration\XDataServiceConfiguration.cs

using System.Collections.Generic;
using xDataService.Constants;

namespace xDataService.Configuration
{
    /// <summary>
    /// Represent Configurations of DataService Module ...
    /// </summary>
    public partial class XDataServiceConfiguration
    {
        /// <summary>
        /// the base path for providing GraphQL ...
        /// </summary>
        /// <value></value>
        public string GraphQLBasePath { get; set; } = "/graphql";

        /// <summary>
        /// Data Bases Configuration ...
        /// </summary>
        /// <returns></returns>
        public IDictionary<string, XDataBaseConfiguration> Databases { get; set; } = new Dictionary<string, XDataBaseConfiguration>();

        /// <summary>
        /// Enable Soft Delete Entities or Not ...
        /// </summary>
        /// <value></value>
        public bool EnableSoftDelete { get; set; }

        /// <summary>
        /// Specified Seeding Mode ...
        /// </summary>
        public XDbSeedingMode SeedingMode { get; set; } = XDbSeedingMode.None;

        /// <summary>
        /// Enable Tracking of Entities ...
        /// Only Used on EFCore ...
        /// </summary>
        /// <value></value>
        public bool EnableTracking { get; set; } = false;

        /// <summary>
        /// Enable Logging Details of Errors ...
        /// Only Used on EFCore ...
        /// </summary>
        /// <value></value>
        public bool EnableDetailedErrors { get; set; } = false;

        /// <summary>
        /// Enable Logging Sensitive Data ...
        /// Only Used on EFCore ...
        /// </summary>
        /// <value></value>
        public bool EnableSensitiveDataLogging { get; set; } = false;

        /// <summary>
        /// this is a way to provide Default Pagination Data on XQuery based requests ...
        /// </summary>
        /// <returns></returns>
        public PagingConfiguration PagingConfiguration { get; set; } = new PagingConfiguration();
    }

    /// <summary>
    /// this is a way to provide Default Pagination Data on XQuery based requests ...
    /// </summary>
    public partial class PagingConfiguration
    {
        /// <summary>
        /// Default Page Size ...
        /// </summary>
        /// <value></value>
        public int DefaultPageSize { get; set; } = XDataServiceConstants.DEFAULT_PAGE_SIZE;

        /// <summary>
        /// restrict Maximum Page Size ...
        /// </summary>
        /// <value></value>
        public int MaxAvailablePageSize { get; set; } = XDataServiceConstants.MAX_AVAILABLE_PAGE_SIZE;

        /// <summary>
        /// restrice Minimum Page Size ...
        /// </summary>
        /// <value></value>
        public int MinAvailablePageSize { get; set; } = XDataServiceConstants.MIN_AVAILABLE_PAGE_SIZE;
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xDataService\Constants\ConfigurationNodeNames.cs

namespace xDataService.Constants {
    public partial struct ConfigurationNodeNames {
        public const string DB_PROVIDER_NODE = "XDBProvider";
        public const string DATA_SERVICE_NODE = "DataServiceConfiguration";
        public const string DATA_SERVICE_DB_SEED_NODE = "DbSeeder";
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xDataService\Constants\XDataServiceConstants.cs

namespace xDataService.Constants {
    /// <summary>
    /// Default Pagination Values ...
    /// </summary>
    public partial struct XDataServiceConstants {
        public static int DEFAULT_PAGE_SIZE = 50;
        public static int MAX_AVAILABLE_PAGE_SIZE = 500;
        public static int MIN_AVAILABLE_PAGE_SIZE = 20;
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xDataService\Constants\XDbProviders.cs

namespace xDataService.Constants {
    /// <summary>
    /// Represent Supported DBMS for Managing Data ...
    /// </summary>
    public enum XDbProviders {
        None,
        MySQL,
        SQLite,
        Oracle,
        SQLServer,
        MongoDB,
    }

    /// <summary>
    /// Represent Supported DBMS for Managing Data ...
    /// </summary>
    public partial struct ProviderType {
        public const string MySQL = "MYSQL";
        public const string SQLite = "SQLITE";
        public const string Oracle = "ORACLE";
        public const string MongoDB = "MONGODB";
        public const string SQLServer = "SQLSERVER";
    }

}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xDataService\Constants\XDbSeedingMode.cs

namespace xDataService.Constants
{
    /// <summary>
    /// All Seeding Data Mode ...
    /// </summary>
    public enum XDbSeedingMode
    {
        /// <summary>
        /// No Seed Data ...
        /// </summary>
        None,

        /// <summary>
        /// Seed Only New Items ...
        /// </summary>
        AddIfNotExists,

        /// <summary>
        /// Seed Force (Add/Update) ...
        /// </summary>
        AddOrUpdate,
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xDataService\Constants\XRepositoryType.cs

using xExceptions.Attributes;

namespace xDataService.Constants
{
    public enum XRepositoryType
    {
        [StringValue("EF")]
        EF,

        [StringValue("Mongo")]
        Mongo,

        [StringValue("InMemory")]
        InMemory
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xDataService\Controllers\XBaseRepositoryController.cs

using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Logging;
using xCommons.Configurations;
using xCommons.Extensions;
using xCommons.Providers;
using xExceptions.Constants;
using xModels.Base;
using xModels.Dtos;
using xDataService.Interfaces;
using System.Linq;
using Microsoft.EntityFrameworkCore.Query;
using System.Threading;
using xCommons.Controllers;
using Microsoft.AspNetCore.Authorization;

namespace xDataService.Controllers
{
    /// <summary>
    /// an Abstract Controller for Providing Entity Repository Actions Implementatin ...
    /// </summary>
    /// <typeparam name="TEntity"></typeparam>
    /// <typeparam name="TKey"></typeparam>
    [AllowAnonymous]
    public abstract class XBaseRepositoryController<TEntity, TKey> : XBaseApiV1Controller, IXBaseRepositoryController<TEntity, TKey>
    where TEntity : XBaseEntity<TKey>
    {
        //
        #region Properties ...
        public IXBaseRepository<TEntity, TKey> Repository { get; }

        public Func<IQueryable<TEntity>, IOrderedQueryable<TEntity>> DefaultOrderBuilder { get; }

        public Func<IQueryable<TEntity>, IIncludableQueryable<TEntity, object>> DefaultIncludeBuilder { get; }
        #endregion

        //
        #region Constructor ...
        protected XBaseRepositoryController(
            ILogger<XBaseRepositoryController<TEntity, TKey>> logger,
            XAppConfiguration appConfiguration,
            XValidationProvider validationProvider,
            IXBaseRepository<TEntity, TKey> repository,
            Func<IQueryable<TEntity>, IOrderedQueryable<TEntity>> defaultOrderBuilder = null,
            Func<IQueryable<TEntity>, IIncludableQueryable<TEntity, object>> defaultIncludeBuilder = null
        ) : base(
            logger,
            appConfiguration,
            validationProvider
        )
        {
            //
            Repository = repository;
            DefaultOrderBuilder = defaultOrderBuilder;
            DefaultIncludeBuilder = defaultIncludeBuilder;
        }
        #endregion

        //
        #region Actions ...
        //
        #region Add ...
        /// <summary>
        /// Add Specified Item ...
        /// </summary>
        /// <remarks>
        /// </remarks>
        /// <param name="item"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        [HttpPost]
        public virtual async Task<ActionResult<TEntity>> Add(
            [FromBody] TEntity item,
            CancellationToken cancellationToken = default
        )
        {
            //
            try
            {
                //
                // Validate Args ...
                if (!ModelState.IsValid)
                {
                    XException.InvalidArgs.Throw();
                }
                ValidationProvider.NotNull(item);

                //
                // Get Result ...
                var result = await Repository
                    .AddAsync(
                        item,
                        saveChanges: true,
                        cancellationToken: cancellationToken
                    );

                //
                return Ok(result
                    .ToDynamicObject());
            }
            catch (Exception ex)
            {
                //
                var result = GetExceptionActionResult(ex);
                return result;
            }
        }

        /// <summary>
        /// Add or Update Specified Item ... 
        /// </summary>
        /// <remarks>
        /// </remarks>
        /// <param name="item"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        [HttpPost("AddOrUpdate")]
        public virtual async Task<ActionResult<TEntity>> AddOrUpdate(
            [FromBody] TEntity item,
            CancellationToken cancellationToken = default
        )
        {
            //
            try
            {
                //
                // Validate Args ...
                if (!ModelState.IsValid)
                {
                    XException.InvalidArgs.Throw();
                }
                ValidationProvider.NotNull(item);

                //
                // Get Result ...
                var result = await Repository
                    .AddOrUpdateAsync(
                        item,
                        saveChanges: true,
                        cancellationToken: cancellationToken
                    );

                //
                return Ok(result
                    .ToDynamicObject());
            }
            catch (Exception ex)
            {
                //
                var result = GetExceptionActionResult(ex);
                return result;
            }
        }

        /// <summary>
        /// Add a Collection of Items ...
        /// </summary>
        /// <remarks>
        /// </remarks>
        /// <param name="request"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        [HttpPost("AddMany")]
        public virtual async Task<ActionResult> AddMany(
            [FromBody] XBaseRangeRequest<TEntity> request,
            CancellationToken cancellationToken = default
        )
        {
            //
            try
            {
                //
                // Validate Args ...
                if (!ModelState.IsValid)
                {
                    XException.InvalidArgs.Throw();
                }
                await ValidationProvider
                    .GroupValidationBuilder()
                    .AddNotNull(request)
                    .AddNotZeroChilds(request.Items)
                    .ValidateGroupAsync();

                //
                // Get Result ...
                await Repository
                    .AddRangeAsync(
                        request.Items,
                        saveChanges: true,
                        cancellationToken: cancellationToken
                    );

                //
                return Ok();
            }
            catch (Exception ex)
            {
                //
                var result = GetExceptionActionResult(ex);
                return result;
            }
        }
        #endregion

        //
        #region Retrieve ...
        /// <summary>
        /// Get Specified Item ...
        /// </summary>
        /// <remarks>
        /// </remarks>
        /// <param name="id"></param>
        /// <param name="ignoreSoftDeleteds"></param>
        /// <param name="useDefaultIncludes"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        [HttpGet("{id}")]
        public virtual async Task<ActionResult<TEntity>> Get(
            [FromRoute] TKey id,
            [FromQuery] bool ignoreSoftDeleteds = true,
            [FromQuery] bool useDefaultIncludes = false,
            CancellationToken cancellationToken = default
        )
        {
            //
            try
            {
                //
                // Validate Args ...
                ValidationProvider.NotNull(id);

                //
                // Get Result ...
                var result = await Repository
                    .GetAsync(
                        id,
                        includeBuilder: useDefaultIncludes
                            ? DefaultIncludeBuilder
                            : null,
                        cancellationToken: cancellationToken,
                        ignoreSoftDeleteds: ignoreSoftDeleteds
                    );

                //
                return Ok(result
                    .ToDynamicObject());
            }
            catch (Exception ex)
            {
                //
                var result = GetExceptionActionResult(ex);
                return result;
            }
        }

        /// <summary>
        /// Get All Items ...
        /// </summary>
        /// <remarks>
        /// </remarks>
        /// <param name="ignoreSoftDeleteds"></param>
        /// <param name="useDefaultOrders"></param>
        /// <param name="useDefaultIncludes"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        [HttpGet]
        public virtual async Task<ActionResult<IEnumerable<TEntity>>> GetAll(
            [FromQuery] bool ignoreSoftDeleteds = true,
            [FromQuery] bool useDefaultOrders = false,
            [FromQuery] bool useDefaultIncludes = false,
            CancellationToken cancellationToken = default
        )
        {
            //
            try
            {
                //
                // Get Result ...
                var result = await Repository
                    .GetAllAsync(
                        orderBuilder: useDefaultOrders
                            ? DefaultOrderBuilder
                            : null,
                        includeBuilder: useDefaultIncludes
                            ? DefaultIncludeBuilder
                            : null,
                        cancellationToken: cancellationToken,
                        ignoreSoftDeleteds: ignoreSoftDeleteds
                    );

                //
                return Ok(result
                    .ToDynamicObject());
            }
            catch (Exception ex)
            {
                //
                var result = GetExceptionActionResult(ex);
                return result;
            }
        }

        /// <summary>
        /// Find Specified Item ...
        /// </summary>
        /// <remarks>
        /// </remarks>
        /// <param name="query"></param>
        /// <param name="ignoreSoftDeleteds"></param>
        /// <param name="useDefaultIncludes"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        [HttpGet("FindOne/{query}")]
        public virtual async Task<ActionResult<TEntity>> FindOne(
            [FromRoute] string query,
            [FromQuery] bool ignoreSoftDeleteds = true,
            [FromQuery] bool useDefaultIncludes = false,
            CancellationToken cancellationToken = default
        )
        {
            //
            try
            {
                //
                // Validate Args ...
                ValidationProvider.NotEmpty(query);

                //
                // Get Result ...
                var result = await Repository
                    .FindOneAsync(
                        predicate: t =>
                            t.PropValuesContains(query),
                        includeBuilder: useDefaultIncludes
                            ? DefaultIncludeBuilder
                            : null,
                        cancellationToken: cancellationToken,
                        ignoreSoftDeleteds: ignoreSoftDeleteds
                    );

                //
                return Ok(result
                    .ToDynamicObject());
            }
            catch (Exception ex)
            {
                //
                var result = GetExceptionActionResult(ex);
                return result;
            }
        }

        /// <summary>
        /// Find Many Items ...
        /// </summary>
        /// <remarks>
        /// </remarks>
        /// <param name="query"></param>
        /// <param name="ignoreSoftDeleteds"></param>
        /// <param name="useDefaultOrders"></param>
        /// <param name="useDefaultIncludes"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        [HttpGet("FindMany/{query}")]
        public virtual async Task<ActionResult<IEnumerable<TEntity>>> FindMany(
            [FromRoute] string query,
            [FromQuery] bool ignoreSoftDeleteds = true,
            [FromQuery] bool useDefaultOrders = false,
            [FromQuery] bool useDefaultIncludes = false,
            CancellationToken cancellationToken = default
        )
        {
            //
            try
            {
                //
                // Validate Args ...
                ValidationProvider.NotEmpty(query);

                //
                // Get Result ...
                var result = await Repository
                    .FindManyAsync(
                        predicate: t =>
                            t.PropValuesContains(query),
                        orderBuilder: useDefaultOrders
                            ? DefaultOrderBuilder
                            : null,
                        includeBuilder: useDefaultIncludes
                            ? DefaultIncludeBuilder
                            : null,
                        cancellationToken: cancellationToken,
                        ignoreSoftDeleteds: ignoreSoftDeleteds
                    );

                //
                return Ok(result
                    .ToDynamicObject());
            }
            catch (Exception ex)
            {
                //
                var result = GetExceptionActionResult(ex);
                return result;
            }
        }

        /// <summary>
        /// Retrieve Items Based on Query Mechanism ...
        /// </summary>
        /// <remarks>
        /// </remarks>
        /// <param name="query"></param>
        /// <param name="ignoreSoftDeleteds"></param>
        /// <param name="useDefaultOrders"></param>
        /// <param name="useDefaultIncludes"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        [HttpGet("Query")]
        public virtual async Task<ActionResult<XQueryResult<TEntity>>> Query(
            [FromQuery] XQuery query,
            [FromQuery] bool ignoreSoftDeleteds = true,
            [FromQuery] bool useDefaultOrders = false,
            [FromQuery] bool useDefaultIncludes = false,
            CancellationToken cancellationToken = default
        )
        {
            //
            try
            {
                //
                // Validate Args ...
                ValidationProvider.NotNull(query);

                //
                // Get Result ...
                var result = await Repository
                    .QueryAsync(
                        query: query,
                        orderBuilder: useDefaultOrders
                            ? DefaultOrderBuilder
                            : null,
                        includeBuilder: useDefaultIncludes
                            ? DefaultIncludeBuilder
                            : null,
                        cancellationToken: cancellationToken,
                        ignoreSoftDeleteds: ignoreSoftDeleteds
                    );

                //
                return Ok(result
                    .ToDynamicObject());
            }
            catch (Exception ex)
            {
                //
                var result = GetExceptionActionResult(ex);
                return result;
            }
        }
        #endregion

        //
        #region Update ...
        /// <summary>
        /// Update Item ...
        /// </summary>
        /// <remarks>
        /// </remarks>
        /// <param name="id"></param>
        /// <param name="item"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        [HttpPut("{id}")]
        public virtual async Task<ActionResult<TEntity>> Update(
            [FromRoute] TKey id,
            [FromBody] TEntity item,
            CancellationToken cancellationToken = default
        )
        {
            //
            try
            {
                //
                // Validate Args ...
                if (!ModelState.IsValid)
                {
                    XException.InvalidArgs.Throw();
                }
                await ValidationProvider
                    .GroupValidationBuilder()
                    .AddNotNull(id, item)
                    .ValidateGroupAsync();

                //
                // Get Result ...
                var result = await Repository
                    .UpdateAsync(
                        id: id,
                        item: item,
                        saveChanges: true,
                        cancellationToken: cancellationToken
                    );

                //
                return Ok(result
                    .ToDynamicObject());
            }
            catch (Exception ex)
            {
                //
                var result = GetExceptionActionResult(ex);
                return result;
            }
        }

        /// <summary>
        /// Update a Collection of items ... 
        /// </summary>
        /// <remarks>
        /// </remarks>
        /// <param name="request"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        [HttpPost("UpdateMany")]
        public virtual async Task<ActionResult<bool>> UpdateMany(
            [FromBody] XBaseRangeRequest<TEntity> request,
            CancellationToken cancellationToken = default
        )
        {
            //
            try
            {
                //
                // Validate Args ...
                if (!ModelState.IsValid)
                {
                    XException.InvalidArgs.Throw();
                }
                await ValidationProvider
                    .GroupValidationBuilder()
                    .AddNotNull(request)
                    .AddNotZeroChilds(request.Items)
                    .ValidateGroupAsync();

                //
                // Get Result ...
                var result = await Repository
                    .UpdateRangeAsync(
                        saveChanges: true,
                        items: request.Items,
                        cancellationToken: cancellationToken
                    );

                //
                return Ok(result
                    .ToDynamicObject());
            }
            catch (Exception ex)
            {
                //
                var result = GetExceptionActionResult(ex);
                return result;
            }
        }
        #endregion

        //
        #region Exists ...
        /// <summary>
        ///Check an Item Exists or not ... 
        /// </summary>
        /// <remarks>
        /// </remarks>
        /// <param name="id"></param>
        /// <param name="ignoreSoftDeleteds"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        [HttpGet("{id}/IsExists")]
        public virtual async Task<ActionResult<bool>> IsExists(
            [FromRoute] TKey id,
            [FromQuery] bool ignoreSoftDeleteds = true,
            CancellationToken cancellationToken = default
        )
        {
            //
            try
            {
                //
                // Validate Args ...
                ValidationProvider.NotNull(id);

                //
                // Get Result ...
                var result = await Repository
                    .IsExistsAsync(
                        id: id,
                        cancellationToken: cancellationToken,
                        ignoreSoftDeleteds: ignoreSoftDeleteds
                    );

                //
                return Ok(result
                    .ToDynamicObject());
            }
            catch (Exception ex)
            {
                //
                var result = GetExceptionActionResult(ex);
                return result;
            }
        }
        #endregion

        //
        #region Remove ...
        /// <summary>
        /// Remove an Items ... 
        /// </summary>
        /// <remarks>
        /// </remarks>
        /// <param name="id"></param>
        /// <param name="softDelete"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        [HttpDelete("{id}")]
        public virtual async Task<ActionResult<TEntity>> Remove(
            [FromRoute] TKey id,
            [FromQuery] bool softDelete = true,
            CancellationToken cancellationToken = default
        )
        {
            //
            try
            {
                //
                // Validate Args ...
                ValidationProvider.NotNull(id);

                //
                // Get Result ...
                var result = await Repository
                    .RemoveAsync(
                        id: id,
                        saveChanges: true,
                        softDelete: softDelete,
                        cancellationToken: cancellationToken
                    );

                //
                return Ok(result
                    .ToDynamicObject());
            }
            catch (Exception ex)
            {
                //
                var result = GetExceptionActionResult(ex);
                return result;
            }
        }

        /// <summary>
        /// Remove Many Items ... 
        /// </summary>
        /// <remarks>
        /// </remarks>
        /// <param name="request"></param>
        /// <param name="softDelete"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        [HttpPost("RemoveMany")]
        public virtual async Task<ActionResult> RemoveMany(
            [FromBody] XBaseRangeRequest<TEntity> request,
            [FromQuery] bool softDelete = true,
            CancellationToken cancellationToken = default
        )
        {
            //
            try
            {
                //
                // Validate Args ...
                await ValidationProvider
                    .GroupValidationBuilder()
                    .AddNotNull(request)
                    .AddNotZeroChilds(request.Items)
                    .ValidateGroupAsync();

                //
                // Get Result ...
                await Repository
                    .RemoveRangeAsync(
                        saveChanges: true,
                        items: request.Items,
                        softDelete: softDelete,
                        cancellationToken: cancellationToken
                    );

                //
                return Ok();
            }
            catch (Exception ex)
            {
                //
                var result = GetExceptionActionResult(ex);
                return result;
            }
        }
        #endregion
        #endregion
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xDataService\Controllers\XBaseServiceController.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore.Query;
using Microsoft.Extensions.Logging;
using xCommons.Configurations;
using xCommons.Controllers;
using xCommons.Extensions;
using xCommons.Providers;
using xDataService.Interfaces;
using xExceptions.Constants;
using xModels.Base;
using xModels.Dtos;

namespace xDataService.Controllers
{
    /// <summary>
    /// an Abstract Controller for Providing Entity Dto Repository Service Actions Implementatin ...
    /// </summary>
    /// <typeparam name="TEntity"></typeparam>
    /// <typeparam name="TDto"></typeparam>
    /// <typeparam name="TKey"></typeparam>
    [AllowAnonymous]
    public abstract class XBaseServiceController<TEntity, TDto, TKey> : XBaseApiV1Controller, IXBaseServiceController<TEntity, TDto, TKey>
    where TEntity : XBaseEntity<TKey>
    where TDto : XBaseEntityDto<TKey>
    {
        //
        #region Properties ...
        public IXBaseRepositoryService<TEntity, TDto, TKey> RepositoryService { get; }
        public Func<IQueryable<TEntity>, IOrderedQueryable<TEntity>> DefaultOrderBuilder { get; }
        public Func<IQueryable<TEntity>, IIncludableQueryable<TEntity, object>> DefaultIncludeBuilder { get; }
        #endregion

        //
        #region Constructor ...
        protected XBaseServiceController(
            ILogger<XBaseServiceController<TEntity, TDto, TKey>> logger,
            XAppConfiguration appConfiguration,
            XValidationProvider validationProvider,
            IXBaseRepositoryService<TEntity, TDto, TKey> repositoryService,
            Func<IQueryable<TEntity>, IOrderedQueryable<TEntity>> defaultOrderBuilder = null,
            Func<IQueryable<TEntity>, IIncludableQueryable<TEntity, object>> defaultIncludeBuilder = null
        ) : base(
            logger,
            appConfiguration,
            validationProvider
        )
        {
            //
            RepositoryService = repositoryService;
            DefaultOrderBuilder = defaultOrderBuilder;
            DefaultIncludeBuilder = defaultIncludeBuilder;
        }
        #endregion

        //
        #region Actions ...
        //
        #region Add ...
        /// <summary>
        /// Add Specified Item ...
        /// </summary>
        /// <remarks>
        /// </remarks>
        /// <param name="item"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        [HttpPost]
        public virtual async Task<ActionResult<TDto>> Add(
            [FromBody] TDto item,
            CancellationToken cancellationToken = default
        )
        {
            //
            try
            {
                //
                // Validate Args ...
                if (!ModelState.IsValid)
                {
                    XException.InvalidArgs.Throw();
                }
                ValidationProvider.NotNull(item);

                //
                // Get Result ...
                var result = await RepositoryService
                    .AddAsync(
                        item,
                        saveChanges: true,
                        cancellationToken: cancellationToken
                    );

                //
                return Ok(result
                    .ToDynamicObject());
            }
            catch (Exception ex)
            {
                //
                var result = GetExceptionActionResult(ex);
                return result;
            }
        }

        /// <summary>
        /// Add or Update Specified Item ... 
        /// </summary>
        /// <remarks>
        /// </remarks>
        /// <param name="item"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        [HttpPost("AddOrUpdate")]
        public virtual async Task<ActionResult<TDto>> AddOrUpdate(
            [FromBody] TDto item,
            CancellationToken cancellationToken = default
        )
        {
            //
            try
            {
                //
                // Validate Args ...
                if (!ModelState.IsValid)
                {
                    XException.InvalidArgs.Throw();
                }
                ValidationProvider.NotNull(item);

                //
                // Get Result ...
                var result = await RepositoryService
                    .AddOrUpdateAsync(
                        item,
                        saveChanges: true,
                        cancellationToken: cancellationToken
                    );

                //
                return Ok(result
                    .ToDynamicObject());
            }
            catch (Exception ex)
            {
                //
                var result = GetExceptionActionResult(ex);
                return result;
            }
        }

        /// <summary>
        /// Add a Collection of Items ...
        /// </summary>
        /// <remarks>
        /// </remarks>
        /// <param name="request"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        [HttpPost("AddMany")]
        public virtual async Task<ActionResult> AddMany(
            [FromBody] XBaseRangeRequest<TDto> request,
            CancellationToken cancellationToken = default
        )
        {
            //
            try
            {
                //
                // Validate Args ...
                if (!ModelState.IsValid)
                {
                    XException.InvalidArgs.Throw();
                }
                await ValidationProvider
                    .GroupValidationBuilder()
                    .AddNotNull(request)
                    .AddNotZeroChilds(request.Items)
                    .ValidateGroupAsync();

                //
                // Get Result ...
                await RepositoryService
                    .AddRangeAsync(
                        request.Items,
                        saveChanges: true,
                        cancellationToken: cancellationToken
                    );

                //
                return Ok();
            }
            catch (Exception ex)
            {
                //
                var result = GetExceptionActionResult(ex);
                return result;
            }
        }
        #endregion

        //
        #region Retrieve ...
        /// <summary>
        /// Get Specified Item ...
        /// </summary>
        /// <remarks>
        /// </remarks>
        /// <param name="id"></param>
        /// <param name="ignoreSoftDeleteds"></param>
        /// <param name="useDefaultIncludes"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        [HttpGet("{id}")]
        public virtual async Task<ActionResult<TDto>> Get(
            [FromRoute] TKey id,
            [FromQuery] bool ignoreSoftDeleteds = true,
            [FromQuery] bool useDefaultIncludes = false,
            CancellationToken cancellationToken = default
        )
        {
            //
            try
            {
                //
                // Validate Args ...
                ValidationProvider.NotNull(id);

                //
                // Get Result ...
                var result = await RepositoryService
                    .GetAsync(
                        id,
                        includeBuilder: useDefaultIncludes
                            ? DefaultIncludeBuilder
                            : null,
                        cancellationToken: cancellationToken,
                        ignoreSoftDeleteds: ignoreSoftDeleteds
                    );

                //
                return Ok(result
                    .ToDynamicObject());
            }
            catch (Exception ex)
            {
                //
                var result = GetExceptionActionResult(ex);
                return result;
            }
        }

        /// <summary>
        /// Get All Items ...
        /// </summary>
        /// <remarks>
        /// </remarks>
        /// <param name="ignoreSoftDeleteds"></param>
        /// <param name="useDefaultOrders"></param>
        /// <param name="useDefaultIncludes"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        [HttpGet]
        public virtual async Task<ActionResult<IEnumerable<TDto>>> GetAll(
            [FromQuery] bool ignoreSoftDeleteds = true,
            [FromQuery] bool useDefaultOrders = false,
            [FromQuery] bool useDefaultIncludes = false,
            CancellationToken cancellationToken = default
        )
        {
            //
            try
            {
                //
                // Get Result ...
                var result = await RepositoryService
                    .GetAllAsync(
                        orderBuilder: useDefaultOrders
                            ? DefaultOrderBuilder
                            : null,
                        includeBuilder: useDefaultIncludes
                            ? DefaultIncludeBuilder
                            : null,
                        cancellationToken: cancellationToken,
                        ignoreSoftDeleteds: ignoreSoftDeleteds
                    );

                //
                return Ok(result
                    .ToDynamicObject());
            }
            catch (Exception ex)
            {
                //
                var result = GetExceptionActionResult(ex);
                return result;
            }
        }

        /// <summary>
        /// Find Specified Item ...
        /// </summary>
        /// <remarks>
        /// </remarks>
        /// <param name="query"></param>
        /// <param name="ignoreSoftDeleteds"></param>
        /// <param name="useDefaultIncludes"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        [HttpGet("FindOne/{query}")]
        public virtual async Task<ActionResult<TDto>> FindOne(
            [FromRoute] string query,
            [FromQuery] bool ignoreSoftDeleteds = true,
            [FromQuery] bool useDefaultIncludes = false,
            CancellationToken cancellationToken = default
        )
        {
            //
            try
            {
                //
                // Validate Args ...
                ValidationProvider.NotEmpty(query);

                //
                // Get Result ...
                var result = await RepositoryService
                    .FindOneAsync(
                        predicate: t =>
                            t.PropValuesContains(query),
                        includeBuilder: useDefaultIncludes
                            ? DefaultIncludeBuilder
                            : null,
                        cancellationToken: cancellationToken,
                        ignoreSoftDeleteds: ignoreSoftDeleteds
                    );

                //
                return Ok(result
                    .ToDynamicObject());
            }
            catch (Exception ex)
            {
                //
                var result = GetExceptionActionResult(ex);
                return result;
            }
        }

        /// <summary>
        /// Find Many Items ...
        /// </summary>
        /// <remarks>
        /// </remarks>
        /// <param name="query"></param>
        /// <param name="ignoreSoftDeleteds"></param>
        /// <param name="useDefaultOrders"></param>
        /// <param name="useDefaultIncludes"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        [HttpGet("FindMany/{query}")]
        public virtual async Task<ActionResult<IEnumerable<TDto>>> FindMany(
            [FromRoute] string query,
            [FromQuery] bool ignoreSoftDeleteds = true,
            [FromQuery] bool useDefaultOrders = false,
            [FromQuery] bool useDefaultIncludes = false,
            CancellationToken cancellationToken = default
        )
        {
            //
            try
            {
                //
                // Validate Args ...
                ValidationProvider.NotEmpty(query);

                //
                // Get Result ...
                var result = await RepositoryService
                    .FindManyAsync(
                        predicate: t =>
                            t.PropValuesContains(query),
                        orderBuilder: useDefaultOrders
                            ? DefaultOrderBuilder
                            : null,
                        includeBuilder: useDefaultIncludes
                            ? DefaultIncludeBuilder
                            : null,
                        cancellationToken: cancellationToken,
                        ignoreSoftDeleteds: ignoreSoftDeleteds
                    );

                //
                return Ok(result
                    .ToDynamicObject());
            }
            catch (Exception ex)
            {
                //
                var result = GetExceptionActionResult(ex);
                return result;
            }
        }

        /// <summary>
        /// Retrieve Items Based on Query Mechanism ...
        /// </summary>
        /// <remarks>
        /// </remarks>
        /// <param name="query"></param>
        /// <param name="ignoreSoftDeleteds"></param>
        /// <param name="useDefaultOrders"></param>
        /// <param name="useDefaultIncludes"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        [HttpGet("Query")]
        public virtual async Task<ActionResult<XQueryResult<TDto>>> Query(
            [FromQuery] XQuery query,
            [FromQuery] bool ignoreSoftDeleteds = true,
            [FromQuery] bool useDefaultOrders = false,
            [FromQuery] bool useDefaultIncludes = false,
            CancellationToken cancellationToken = default
        )
        {
            //
            try
            {
                //
                // Validate Args ...
                ValidationProvider.NotNull(query);

                //
                // Get Result ...
                var result = await RepositoryService
                    .QueryAsync(
                        query: query,
                        orderBuilder: useDefaultOrders
                            ? DefaultOrderBuilder
                            : null,
                        includeBuilder: useDefaultIncludes
                            ? DefaultIncludeBuilder
                            : null,
                        cancellationToken: cancellationToken,
                        ignoreSoftDeleteds: ignoreSoftDeleteds
                    );

                //
                return Ok(result
                    .ToDynamicObject());
            }
            catch (Exception ex)
            {
                //
                var result = GetExceptionActionResult(ex);
                return result;
            }
        }
        #endregion

        //
        #region Update ...
        /// <summary>
        /// Update Item ...
        /// </summary>
        /// <remarks>
        /// </remarks>
        /// <param name="id"></param>
        /// <param name="item"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        [HttpPut("{id}")]
        public virtual async Task<ActionResult<TDto>> Update(
            [FromRoute] TKey id,
            [FromBody] TDto item,
            CancellationToken cancellationToken = default
        )
        {
            //
            try
            {
                //
                // Validate Args ...
                if (!ModelState.IsValid)
                {
                    XException.InvalidArgs.Throw();
                }
                await ValidationProvider
                    .GroupValidationBuilder()
                    .AddNotNull(id, item)
                    .ValidateGroupAsync();

                //
                // Get Result ...
                var result = await RepositoryService
                    .UpdateAsync(
                        id: id,
                        item: item,
                        saveChanges: true,
                        cancellationToken: cancellationToken
                    );

                //
                return Ok(result
                    .ToDynamicObject());
            }
            catch (Exception ex)
            {
                //
                var result = GetExceptionActionResult(ex);
                return result;
            }
        }

        /// <summary>
        /// Update a Collection of items ... 
        /// </summary>
        /// <remarks>
        /// </remarks>
        /// <param name="request"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        [HttpPost("UpdateMany")]
        public virtual async Task<ActionResult<bool>> UpdateMany(
            [FromBody] XBaseRangeRequest<TDto> request,
            CancellationToken cancellationToken = default
        )
        {
            //
            try
            {
                //
                // Validate Args ...
                if (!ModelState.IsValid)
                {
                    XException.InvalidArgs.Throw();
                }
                await ValidationProvider
                    .GroupValidationBuilder()
                    .AddNotNull(request)
                    .AddNotZeroChilds(request.Items)
                    .ValidateGroupAsync();

                //
                // Get Result ...
                var result = await RepositoryService
                    .UpdateRangeAsync(
                        saveChanges: true,
                        items: request.Items,
                        cancellationToken: cancellationToken
                    );

                //
                return Ok(result
                    .ToDynamicObject());
            }
            catch (Exception ex)
            {
                //
                var result = GetExceptionActionResult(ex);
                return result;
            }
        }
        #endregion

        //
        #region Exists ...
        /// <summary>
        ///Check an Item Exists or not ... 
        /// </summary>
        /// <remarks>
        /// </remarks>
        /// <param name="id"></param>
        /// <param name="ignoreSoftDeleteds"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        [HttpGet("{id}/IsExists")]
        public virtual async Task<ActionResult<bool>> IsExists(
            [FromRoute] TKey id,
            [FromQuery] bool ignoreSoftDeleteds = true,
            CancellationToken cancellationToken = default
        )
        {
            //
            try
            {
                //
                // Validate Args ...
                ValidationProvider.NotNull(id);

                //
                // Get Result ...
                var result = await RepositoryService
                    .IsExistsAsync(
                        id: id,
                        cancellationToken: cancellationToken,
                        ignoreSoftDeleteds: ignoreSoftDeleteds
                    );

                //
                return Ok(result
                    .ToDynamicObject());
            }
            catch (Exception ex)
            {
                //
                var result = GetExceptionActionResult(ex);
                return result;
            }
        }
        #endregion

        //
        #region Remove ...
        /// <summary>
        /// Remove an Items ... 
        /// </summary>
        /// <remarks>
        /// </remarks>
        /// <param name="id"></param>
        /// <param name="softDelete"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        [HttpDelete("{id}")]
        public virtual async Task<ActionResult<TDto>> Remove(
            [FromRoute] TKey id,
            [FromQuery] bool softDelete = true,
            CancellationToken cancellationToken = default
        )
        {
            //
            try
            {
                //
                // Validate Args ...
                ValidationProvider.NotNull(id);

                //
                // Get Result ...
                var result = await RepositoryService
                    .RemoveAsync(
                        id: id,
                        saveChanges: true,
                        softDelete: softDelete,
                        cancellationToken: cancellationToken
                    );

                //
                return Ok(result
                    .ToDynamicObject());
            }
            catch (Exception ex)
            {
                //
                var result = GetExceptionActionResult(ex);
                return result;
            }
        }

        /// <summary>
        /// Remove Many Items ... 
        /// </summary>
        /// <remarks>
        /// </remarks>
        /// <param name="request"></param>
        /// <param name="softDelete"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        [HttpPost("RemoveMany")]
        public virtual async Task<ActionResult> RemoveMany(
            [FromBody] XBaseRangeRequest<TDto> request,
            [FromQuery] bool softDelete = true,
            CancellationToken cancellationToken = default
        )
        {
            //
            try
            {
                //
                // Validate Args ...
                await ValidationProvider
                    .GroupValidationBuilder()
                    .AddNotNull(request)
                    .AddNotZeroChilds(request.Items)
                    .ValidateGroupAsync();

                //
                // Get Result ...
                await RepositoryService
                    .RemoveRangeAsync(
                        saveChanges: true,
                        items: request.Items,
                        softDelete: softDelete,
                        cancellationToken: cancellationToken
                    );

                //
                return Ok();
            }
            catch (Exception ex)
            {
                //
                var result = GetExceptionActionResult(ex);
                return result;
            }
        }
        #endregion
        #endregion
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xDataService\Db\XDbContext.cs

using System;
using System.Linq;
using Microsoft.EntityFrameworkCore;
using xCommons.Extensions;
using xDataService.Configuration;
using xDataService.Helpers;
using xDataService.Providers;

namespace xDataService.Db
{
    /// <summary>
    /// Provide an abstraction layout arround DBContext ...
    /// Only Used on EFCore ...
    /// </summary>
    public abstract class XDbContext : DbContext
    {
        //
        #region Properties ...
        private readonly string database;
        private readonly XDataServiceConfiguration config;
        private readonly string[] dynamicEntityRegisterarsNames;
        private readonly XEntityRegisterarHandlerService dynamicEntityHandlers;
        #endregion

        //
        #region Entities ...
        //
        // Register Default and Base Entities ...
        #endregion

        //
        #region  Constructor ...
        public XDbContext(
            string database,
            DbContextOptions options,
            XDataServiceConfiguration config,
            XEntityRegisterarHandlerService dynamicEntityHandlers,
            string[] dynamicEntityRegisterarsNames = null
        ) : base(options)
        {
            //
            try
            {
                Database.EnsureCreated();
                Database.Migrate();
            }
            catch { }

            //
            this.config = config;
            this.database = database;
            this.dynamicEntityHandlers = dynamicEntityHandlers;
            this.dynamicEntityRegisterarsNames = dynamicEntityRegisterarsNames;

            //
            // Handling DbSets of Dynamic Entities ...
            if (!dynamicEntityHandlers.IsNull())
            {
                //
                // Configure XEntityRegisterarHandlerService ...
                dynamicEntityHandlers.HandleRegisteredEntities();

                //
                // Loop through Entity Types ...
                foreach (var entityType in dynamicEntityHandlers.GetEntityTypes(dynamicEntityRegisterarsNames))
                {
                    //
                    try
                    {
                        //
                        // Use reflection to call Set<T>()
                        var method = typeof(XDbContext)
                            .GetMethod(nameof(XDbContext.Set), Type.EmptyTypes)
                            .MakeGenericMethod(entityType);
                        if (!method.IsNull())
                        {
                            method.Invoke(this, null);
                        }
                    }
                    catch { }
                }
            }
        }
        #endregion

        /// <summary>
        /// Extract Current Database Configuration ...
        /// </summary>
        /// <returns></returns>
        public XDataBaseConfiguration GetDatabaseConfiguration()
        {
            //
            XDataBaseConfiguration result =
                config.Databases.FirstOrDefault(db => string
                    .Equals(db.Key, database, StringComparison.InvariantCultureIgnoreCase)).Value;

            //
            return result;
        }

        //
        #region Overrides ...
        //
        // Prepare Model Configs ...
        protected override void OnModelCreating(ModelBuilder modelBuilder)
        {
            //
            OnXModelCreating(modelBuilder);

            //
            // Automatically apply all IEntityTypeConfiguration<T> in this assembly
            modelBuilder.ApplyConfigurationsFromAssembly(typeof(XDbContext).Assembly);

            //
            // Check Dynamic Registered Service is Exists or not ...
            if (!dynamicEntityHandlers.IsNull())
            {
                //
                // Set Entity of Dynamically Registered Entities ...
                foreach (var entityType in dynamicEntityHandlers.GetEntityTypes(dynamicEntityRegisterarsNames))
                {
                    modelBuilder.Entity(entityType);
                }

                //
                // Configure Entity using Provided Registerar ...
                dynamicEntityHandlers
                    .HandleApplyRegisteredEntitiesConfigurations(modelBuilder, dynamicEntityRegisterarsNames);
            }

            //
            // Since this class inherit from Identity Db Context,
            // we have to pass this to Building Identity Models ...
            base.OnModelCreating(modelBuilder);
        }

        //
        // Prepare Configuring ...
        protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
        {
            //
            if (config.EnableDetailedErrors)
            {
                optionsBuilder.EnableDetailedErrors();
            }

            //
            if (config.EnableSensitiveDataLogging)
            {
                optionsBuilder.EnableSensitiveDataLogging();
            }

            //
            if (config.EnableTracking)
            {
                optionsBuilder.UseQueryTrackingBehavior(QueryTrackingBehavior.TrackAll);
            }
            else
            {
                optionsBuilder.UseQueryTrackingBehavior(QueryTrackingBehavior.NoTracking);
            }

            //
            OnXConfiguring(optionsBuilder);

            //
            base.OnConfiguring(optionsBuilder);
        }
        #endregion

        //
        #region Abstracts ...
        //
        public abstract void OnXModelCreating(ModelBuilder modelBuilder);

        //
        public abstract void OnXConfiguring(DbContextOptionsBuilder optionsBuilder);
        #endregion

        //
        #region Dynamic DbSet(s) ...
        public override DbSet<TEntity> Set<TEntity>()
        where TEntity : class
        {
            return base.Set<TEntity>();
        }
        #endregion
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xDataService\Db\XUnitOfWorks.cs

using System.Threading;
using System.Threading.Tasks;
using Microsoft.EntityFrameworkCore;
using xDataService.Interfaces;
using xModels.Base;

namespace xDataService.Db {
    /// <summary>
    /// Provide Unit Of Works Design Pattern for Db Transactions ...
    /// Only Used on EFCore ...
    /// </summary>
    /// <typeparam name="TDbContext"></typeparam>
    public class XUnitOfWorks<TDbContext> : IXUnitOfWorks<TDbContext>
        where TDbContext : XDbContext {
            public TDbContext DbContext { get; }

            public XUnitOfWorks (TDbContext context) {
                this.DbContext = context;
            }

            public DbSet<T> GetDbSet<T, TKey> ()
            where T : XBaseEntity<TKey> {
                return DbContext.Set<T> ();
            }

            /// <summary>
            /// Save Changes
            /// </summary>        
            public int SaveChanges () {
                return DbContext.SaveChanges ();
            }

            /// <summary>
            /// Save Changes Async
            /// </summary>
            /// <param name="cancellationToken"></param>
            /// <returns></returns>
            public async Task<int> SaveChangesAsync (
                CancellationToken cancellationToken = default
            ) {
                return await DbContext.SaveChangesAsync (cancellationToken);
            }

            public void Dispose () {
                DbContext.Dispose ();
            }
        }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xDataService\DI\XDIHelperExtension.cs

using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.AspNetCore.Builder;
using Microsoft.EntityFrameworkCore.Infrastructure;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using xCommons.Extensions;
using xCommons.Helpers;
using xDataService.Configuration;
using xDataService.Constants;
using xDataService.Extensions;
using xDataService.Helpers;
using xDataService.Models;
using xDataService.Providers;
using xExceptions.Constants;

namespace xDataService.DI
{
    public static partial class XDIHelperExtension
    {
        /// <summary>
        /// Retrive XDataService Configurations
        /// </summary>
        /// <param name="source"></param>
        /// <returns></returns>
        public static XDataServiceConfiguration GetXDataServiceConfiguration(
            this IConfiguration source
        )
        {
            //
            var xDataServiceConfigSection = source
                .GetSection(ConfigurationNodeNames.DATA_SERVICE_NODE);
            var result = xDataServiceConfigSection.Get<XDataServiceConfiguration>();

            //
            // Reading Seeders ...
            if (!result.IsNull() &&
                result.Databases.HasChild())
            {
                //
                result
                    .Databases
                    .ToList()
                    .ForEach(db =>
                    {
                        //
                        var seedItemsSectionName = $"{ConfigurationNodeNames.DATA_SERVICE_NODE}:{nameof(XDataServiceConfiguration.Databases)}:{db.Key}:{nameof(XDataBaseConfiguration.SeedItems)}";
                        var section = source.GetSection(seedItemsSectionName);
                        var sectionJson = source.GetSectionAsJson(seedItemsSectionName);
                        var sectionDict = sectionJson.FromJSON<Dictionary<string, List<object>>>();
                        if (!sectionDict.IsNull() &&
                            sectionDict.Values.HasChild())
                        {
                            //
                            sectionDict
                                .Keys
                                .ToList()
                                .ForEach(entity =>
                                {
                                    //
                                    // Setting Values to Result ...
                                    result.Databases[db.Key].SeedItems[entity] = sectionDict[entity];
                                });
                        }
                    });
            }

            //
            return result;
        }

        /// <summary>
        /// Register XDataService Configuration ... 
        /// </summary>
        /// <param name="source"></param>
        /// <param name="configuration"></param>
        public static void AddXDataServiceConfiguration(
            this IServiceCollection source,
            IConfiguration configuration
        )
        {
            //
            var config = configuration.GetXDataServiceConfiguration();
            if (config.IsNullOrDefault())
            {
                //
                Log("Configurations Not Founded ...");
                XException.NotFound.Throw();
            }

            //
            source.AddSingleton(config);
        }

        /// <summary>
        /// Register XDataService Configuration ... 
        /// </summary>
        /// <param name="source"></param>
        /// <param name="configuration"></param>
        public static void AddXDataServiceConfiguration(
            this IServiceCollection source,
            XDataServiceConfiguration configuration
        )
        {
            //
            if (configuration.IsNullOrDefault())
            {
                //
                Log("Configurations Not Founded ...");
                XException.NotFound.Throw();
            }

            //
            source.AddSingleton(configuration);
        }

        /// <summary>
        /// Register a Data Base using Descriptor ...
        /// </summary>
        /// <param name="source"></param>
        /// <param name="configuration"></param>
        /// <param name="descriptor"></param>
        /// <param name="lifeTime"></param>
        public static void AddXDatabase(
            this IServiceCollection source,
            IConfiguration configuration,
            XDatabaseDescriptor descriptor,
            ServiceLifetime lifeTime = ServiceLifetime.Scoped
        )
        {
            //
            // Validate Database Descriptor ...
            var isValid =
                !descriptor.IsNullOrDefault() &&
                !descriptor.Name.IsNullOrEmpty();
            if (!isValid)
            {
                //
                Log("Invalid Database Descriptor ...");
                return;
            }

            //
            // Check Service Collection Validation ...
            isValid =
                !source.IsNull() &&
                !configuration.IsNull();
            if (!isValid)
            {
                //
                Log("Invalid Service Provider or Configuration ...");
                return;
            }

            //
            // Get Registere Data Service Configuration ...
            var xDataServiceConfiguration = source
                .GetRegisteredService<XDataServiceConfiguration>();
            isValid = !xDataServiceConfiguration.IsNullOrDefault();
            if (!isValid)
            {
                //
                // Extract Configuration from Configuration ...
                xDataServiceConfiguration = configuration.GetXDataServiceConfiguration();
                isValid = !xDataServiceConfiguration.IsNullOrDefault();
                if (!isValid)
                {
                    //
                    Log("DataService Configuration not provided ...");
                    return;
                }

                //
                // Register Configuration in DI ... 
                source.AddSingleton(xDataServiceConfiguration);
            }

            //
            // Check Data Service Configuration has Database ...
            isValid =
                !xDataServiceConfiguration.Databases.IsNullOrDefault() &&
                xDataServiceConfiguration.Databases.HasChild() &&
                xDataServiceConfiguration.Databases.Keys.Contains(descriptor.Name);
            if (!isValid)
            {
                //
                Log("Invalid Database Descriptor ...");
                return;
            }

            //
            // Register Handler Service ...
            source.AddSingleton<XEntityRegisterarHandlerService>();

            //
            // Configure Database Descriptor ...
            descriptor.Configure(source);

            //
            // Register Context ...
            if (!descriptor.Context.IsNull() &&
                descriptor.Provider != XDbProviders.None &&
                !descriptor.ConnectionString.IsNullOrEmpty())
            {
                //
                try
                {
                    //
                    typeof(XDataServiceHelper).InvokeGenericMethod(
                        methodName: "AddXDbContext",
                        runtimeType: descriptor.Context,
                        args: [
                            source,
                            descriptor,
                            lifeTime
                        ]
                    );

                    //
                    Log($"DbContext: {descriptor.Name} Registered Successfully ...");
                }
                catch (Exception ex)
                {
                    Log($"DbContext: {descriptor.Name} Registration failed due {ex.Message} ...");
                }
            }

            //
            // Register Repositories ...
            if (!descriptor.Repositories.IsNull() &&
                descriptor.Repositories.HasChild())
            {
                //
                descriptor.Repositories.ToList().ForEach(r =>
                {
                    //
                    source.AddXRepository(
                        descriptor: r,
                        lifeTime: lifeTime
                    );
                });
            }
        }

        public static void AddXRepository(
            this IServiceCollection source,
            XRepositoryDescriptor descriptor,
            ServiceLifetime lifeTime = ServiceLifetime.Scoped
        )
        {
            //
            // Preparing Runtime Types ...
            Type[] runtimeTypes = descriptor.GetType().GenericTypeArguments;

            //
            try
            {
                //
                typeof(XDataServiceHelper).InvokeGenericMethod(
                    methodName: "AddXRepository",
                    runtimeTypes: runtimeTypes,
                    args: [
                        source,
                        descriptor,
                        lifeTime
                    ]
                );

                //
                Log($"Repository of: {runtimeTypes[0]}, Registered Successfully ...");
            }
            catch (Exception ex)
            {
                Log($"Repository of: {runtimeTypes[0]}, Registration failed due {ex.Message} ...");
            }
        }

        public static void UseXDatabase(
            this IApplicationBuilder source,
            XDatabaseDescriptor descriptor,
            bool isDevelopmentEnvironment = false
        )
        {
            //
            // Validate ...
            var isValid =
                !source.IsNull() &&
                descriptor.IsValid();
            if (!isValid)
            {
                //
                Log("Invalid Database Configuration ...");
                XException.InvalidArgs.Throw();
            }

            //
            // Check Repositories Exists ...
            isValid = descriptor.HasRepositories();
            if (isValid)
            {
                //
                // Loop through Repositories ...
                descriptor.Repositories
                    .ToList()
                    .ForEach(r =>
                    {
                        //
                        source.UseXRepository(
                            descriptor: r,
                            isDevelopmentEnvironment: isDevelopmentEnvironment
                        );
                    });
            }
        }

        /// <summary>
        /// Use a Repository Middlewares by Providing it's Descriptor ...
        /// </summary>
        /// <param name="source"></param>
        /// <param name="descriptor"></param>
        /// <param name="isDevelopmentEnvironment"></param>
        public static void UseXRepository(
            this IApplicationBuilder source,
            XRepositoryDescriptor descriptor,
            bool isDevelopmentEnvironment = false
        )
        {
            //
            Log($"Start Using Repository of: {descriptor.Entity}");

            //
            var withPlayground = false;
            if (isDevelopmentEnvironment)
            {
                withPlayground = true;
            }

            //
            // Create an Scope for Services Acces ...
            using (var scope = source.ApplicationServices.CreateScope())
            {
                //
                // Inject XDataServiceConfiguration ForMake Sure DataService Registration ...
                var dataServiceConfiguration = scope.ServiceProvider.GetService<XDataServiceConfiguration>();
                var isValid = !dataServiceConfiguration.IsNullOrDefault();
                if (isValid)
                {
                    //
                    // Check Seeder Exists ...
                    // Execute Seeding Data Task if Exists ...
                    isValid = descriptor.HasSeeder();
                    if (isValid)
                    {
                        //
                        var seeder = (dynamic)scope.ServiceProvider.GetService(descriptor.SeederService);
                        isValid = seeder != null;
                        if (isValid)
                        {
                            //
                            Log($"Start Seeding {descriptor.Entity} ...");

                            //
                            // Seeding ...
                            seeder
                                .Seed()
                                .GetAwaiter()
                                .GetResult();
                        }
                    }

                    //
                    // Check GraphQL Support ...
                    isValid = descriptor.HasGraphSupport();
                    if (isValid)
                    {
                        //
                        // Use WebSockets ...
                        source.UseWebSockets();

                        //
                        // Inject GraphQL Type Helper ...
                        var helper = (dynamic)scope.ServiceProvider.GetService(descriptor.GraphTypeHelperService);
                        isValid = helper != null;
                        if (isValid)
                        {
                            //
                            var graphPath = $"{helper.GetGraphQLPath()}";
                            var graphBasePath = $"{dataServiceConfiguration.GraphQLBasePath}";
                            typeof(XDataServiceHelper).InvokeGenericMethod(
                                methodName: "UseXGraphQL",
                                runtimeTypes: [
                                    descriptor.Entity,
                            descriptor.Key,
                            descriptor.GraphType,
                            descriptor.GraphTypeKey,
                            descriptor.GraphQuery,
                            descriptor.GraphTypeHelperService,
                            descriptor.GraphTypeHelperImplementation,
                            descriptor.GraphSchema
                                ],
                                args: [
                                    source,
                                    graphBasePath,
                                    graphPath,
                                    withPlayground
                                ]
                            );

                            //
                            Log($"Register GraphQL: {graphPath}");
                        }
                    }
                }
            }
        }

        //
        #region Private ...
        /// <summary>
        /// a LogTag for xDataService ...
        /// </summary>
        private static string XLogTag = "xDataService";

        /// <summary>
        /// print a log in Console ...
        /// </summary>
        /// <param name="message"></param>
        private static void Log(string message)
        {
            Console.WriteLine($"{XLogTag} => {message}");
        }
        #endregion
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xDataService\Extensions\DbContextOptionExtensions.cs

using System;
using Microsoft.EntityFrameworkCore.Infrastructure;
using MySql.EntityFrameworkCore.Infrastructure;

namespace xDataService.Extensions {
    public static class DbContextOptionExtensions {
        /// <summary>
        /// convert dynamic object to MySqlDbContextOptionBuilder ...
        /// Only Used in EFCore ...
        /// </summary>
        /// <param name="source"></param>
        /// <returns></returns>
        public static Action<MySQLDbContextOptionsBuilder> ToMySQLDbContextOptionsBuilder (
            this Action<dynamic> source
        ) {
            return ((Action<MySQLDbContextOptionsBuilder>) source);
        }

        /// <summary>
        /// convert dynamic object to SqliteDbContextOptionBuilder ...
        /// Only Used in EFCore ...
        /// </summary>
        /// <param name="source"></param>
        /// <returns></returns>
        public static Action<SqliteDbContextOptionsBuilder> ToSqliteDbContextOptionsBuilder (
            this Action<dynamic> source
        ) {
            return ((Action<SqliteDbContextOptionsBuilder>) source);
        }

        /// <summary>
        /// convert dynamic object to SqlServerDbContextOptionBuilder ...
        /// Only Used in EFCore ...
        /// </summary>
        /// <param name="source"></param>
        /// <returns></returns>
        public static Action<SqlServerDbContextOptionsBuilder> ToSqlServerDbContextOptionsBuilder (
            this Action<dynamic> source
        ) {
            return ((Action<SqlServerDbContextOptionsBuilder>) source);
        }
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xDataService\Extensions\EntityExtensions.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using xCommons.Extensions;
using xModels.Base;

namespace xDataService.Extensions {
    public static class EntityExtensions {
        /// <summary>
        /// return all values of an entity properties as a json string ...
        /// </summary>
        /// <param name="item"></param>
        /// <typeparam name="T"></typeparam>
        /// <returns></returns>
        public static string GetPropValues<T> (this T item)
        where T : XBaseEntity<T> {
            //
            var props = item.GetType ().GetProperties ();
            var vals = props.Select (p => p.GetValue (item));

            //
            return vals.ToJSON ();
        }

        /// <summary>
        /// check values of all properties of an Entity contains specific value or not ...
        /// </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 : XBaseEntity<T> => item.GetPropValues ()
            .ToNormalString ()
            .Contains (value);

        /// <summary>
        /// Retrieve Default Column Map of specific Entity ...
        /// </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 : XBaseEntity<T> {
            //
            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>
        /// Check a Type is XBaseEntity or not ...
        /// </summary>
        /// <param name="source"></param>
        /// <returns></returns>
        public static bool IsXEntity(this Type source)
        {
            //
            var result = !source.IsNull();
            if (!result)
            {
                return result;
            }

            //
            var baseType = source.BaseType;
            while(!baseType.IsNull() && baseType != typeof(object))
            {
                //
                if (baseType.IsGenericType &&
                    baseType.GetGenericTypeDefinition() == typeof(XBaseEntity<>))
                {
                    result = true;
                    break;
                }

                //
                baseType = baseType.BaseType;
            }

            //
            return result;
        }
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xDataService\Extensions\IQueryableExtensions.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Reflection;
using System.Threading.Tasks;
using Microsoft.EntityFrameworkCore;
using xCommons.Extensions;
using xDataService.Configuration;
using xDataService.Constants;
using xExceptions.Constants;
using xModels.Base;
using xModels.Dtos;

namespace xDataService.Extensions
{
    public static class IQueryableExtensions
    {
        /// <summary>
        /// Apply Search Filter on a Query
        /// </summary>
        /// <param name="source"></param>
        /// <param name="filter"></param>
        /// <typeparam name="T"></typeparam>
        /// <returns></returns>
        public static IQueryable<T> ApplyFilter<T, TKey>(
            this IQueryable<T> source,
            string filter
        )
        where T : XBaseEntity<TKey>
        {
            //
            // Apply Filter ...
            return source.Where(r => r.PropValuesContains(filter));
        }

        /// <summary>
        /// Apply Search Filter on a Query
        /// </summary>
        /// <param name="source"></param>
        /// <param name="filter"></param>
        /// <typeparam name="T"></typeparam>
        /// <returns></returns>
        public static async Task<IQueryable<T>> ApplyFilterAsync<T, TKey>(
            this IQueryable<T> source,
            string filter
        )
        where T : XBaseEntity<TKey>
        {
            //
            // Where Clause ...
            Expression<Func<T, bool>> whereClause = r => r
            .PropValuesContains(filter);

            //
            // Generate Where Function ...
            var whereFunc = whereClause.Compile();

            //
            // Get Enumerable ...
            var enumerator = source
                .AsAsyncEnumerable();

            //
            var result = new List<T>();
            await
            foreach (var entity in enumerator)
            {
                //
                var isApproved = whereFunc(entity);
                if (isApproved)
                {
                    result.Add(entity);
                }
            }

            //
            return result.AsQueryable();
        }

        /// <summary>
        /// Apply Search Filter on a Enumerable
        /// </summary>
        /// <param name="source"></param>
        /// <param name="filter"></param>
        /// <typeparam name="T"></typeparam>
        /// <returns></returns>
        public static async Task<IEnumerable<T>> ApplyFilterAsync<T, TKey>(
            this IEnumerable<T> source,
            string filter
        )
        where T : XBaseEntity<TKey>
        {
            //
            // Where Clause ...
            Expression<Func<T, bool>> whereClause = r => r
            .PropValuesContains(filter);

            //
            // Generate Where Function ...
            var whereFunc = whereClause.Compile();

            //
            // Get Enumerable ...
            var enumerator = source
                .ToList()
                .AsQueryable();

            //
            var result = new List<T>();
            foreach (var entity in enumerator)
            {
                //
                var isApproved = whereFunc(entity);
                if (isApproved)
                {
                    result.Add(entity);
                }
            }

            //
            return result
                .AsEnumerable();
        }

        /// <summary>
        /// Apply Search Filter on a Enumerable
        /// </summary>
        /// <param name="source"></param>
        /// <param name="filter"></param>
        /// <typeparam name="T"></typeparam>
        /// <returns></returns>
        public static IEnumerable<T> ApplyFilter<T>(
            this IEnumerable<T> source,
            string filter
        )
        where T : class
        {
            //
            // Apply Filter ...
            return source.Where(r => r.PropValuesContains(filter));
        }

        /// <summary>
        /// provide a way to Order an IQueryable by string FieldName ...
        /// </summary>
        /// <param name="query"></param>
        /// <param name="propertyName"></param>
        /// <typeparam name="TSource"></typeparam>
        /// <returns></returns>
        public static IOrderedQueryable<TSource> OrderBy<TSource>(
            this IQueryable<TSource> query,
            string propertyName
        )
        {
            //
            var entityType = typeof(TSource);

            //
            // Create x => x.PropName
            var propertyInfo = entityType.GetProperty(propertyName);
            if (propertyInfo.IsNull())
            {
                XException.InvalidArgs.Throw();
            }

            //
            ParameterExpression arg = Expression.Parameter(entityType, "x");
            MemberExpression property = Expression.Property(arg, propertyName);
            var selector = Expression.Lambda(property, new ParameterExpression[] { arg });

            //
            // Get System.Linq.Queryable.OrderBy() method.
            var enumarableType = typeof(System.Linq.Queryable);
            var method = enumarableType.GetMethods()
                .Where(m => m.Name == "OrderBy" && m.IsGenericMethodDefinition)
                .Where(m =>
                {
                    //
                    var parameters = m.GetParameters().ToList();

                    //
                    // Put more restriction here to ensure selecting the right overload                
                    return parameters.Count == 2; // overload that has 2 parameters
                }).Single();

            //
            // The linq's OrderBy<TSource, TKey> has two generic types, which provided here ...
            MethodInfo genericMethod = method
                .MakeGenericMethod(entityType, propertyInfo.PropertyType);

            /* 
              Call query.OrderBy(selector), with query and selector: x=> x.PropName
              Note that we pass the selector as Expression to the method and we don't compile it.

              By doing so EF can extract "order by" columns and generate SQL for it.
              */
            var newQuery = (IOrderedQueryable<TSource>)genericMethod
                .Invoke(genericMethod, new object[] { query, selector });

            //
            return newQuery;
        }

        /// <summary>
        /// provide a way to Order an IEnumerable by string FieldName ...
        /// </summary>
        /// <param name="query"></param>
        /// <param name="propertyName"></param>
        /// <typeparam name="TSource"></typeparam>
        /// <returns></returns>
        public static IOrderedEnumerable<TSource> OrderBy<TSource>(
            this IEnumerable<TSource> query,
            string propertyName
        )
        {
            //
            var entityType = typeof(TSource);
            var propertyInfo = entityType.GetProperty(propertyName);
            if (propertyInfo.IsNull())
            {
                XException.InvalidArgs.Throw();
            }

            //
            return query.OrderBy(x => propertyInfo.GetValue(x, null));
        }

        /// <summary>
        /// provide a way to Order an IQueryable by string FieldName ...
        /// </summary>
        /// <param name="query"></param>
        /// <param name="propertyName"></param>
        /// <typeparam name="TSource"></typeparam>
        /// <returns></returns>
        public static IOrderedQueryable<TSource> OrderByDescending<TSource>(
            this IQueryable<TSource> query,
            string propertyName
        )
        {
            //
            var entityType = typeof(TSource);

            //
            // Create x => x.PropName
            var propertyInfo = entityType.GetProperty(propertyName);
            if (propertyInfo.IsNull())
            {
                XException.InvalidArgs.Throw();
            }

            //
            ParameterExpression arg = Expression.Parameter(entityType, "x");
            MemberExpression property = Expression.Property(arg, propertyName);
            var selector = Expression.Lambda(property, new ParameterExpression[] { arg });

            //
            // Get System.Linq.Queryable.OrderBy() method.
            var enumarableType = typeof(System.Linq.Queryable);
            var method = enumarableType.GetMethods()
                .Where(m => m.Name == "OrderByDescending" && m.IsGenericMethodDefinition)
                .Where(m =>
                {
                    //
                    var parameters = m.GetParameters().ToList();

                    //
                    // Put more restriction here to ensure selecting the right overload                
                    return parameters.Count == 2; // overload that has 2 parameters
                }).Single();

            //
            // The linq's OrderBy<TSource, TKey> has two generic types, which provided here ...
            MethodInfo genericMethod = method
                .MakeGenericMethod(entityType, propertyInfo.PropertyType);

            /* 
              Call query.OrderBy(selector), with query and selector: x=> x.PropName
              Note that we pass the selector as Expression to the method and we don't compile it.

              By doing so EF can extract "order by" columns and generate SQL for it.
              */
            var newQuery = (IOrderedQueryable<TSource>)genericMethod
                .Invoke(genericMethod, new object[] { query, selector });

            //
            return newQuery;
        }

        /// <summary>
        /// provide a way to Order an IEnumerable by string FieldName ...
        /// </summary>
        /// <param name="query"></param>
        /// <param name="propertyName"></param>
        /// <typeparam name="TSource"></typeparam>
        /// <returns></returns>
        public static IOrderedEnumerable<TSource> OrderByDescending<TSource>(
            this IEnumerable<TSource> query,
            string propertyName
        )
        {
            //
            var entityType = typeof(TSource);
            var propertyInfo = entityType.GetProperty(propertyName);
            if (propertyInfo.IsNull())
            {
                XException.InvalidArgs.Throw();
            }

            //
            return query.OrderByDescending(x => propertyInfo.GetValue(x, null));
        }

        /// <summary>
        /// Apply Sorting on a query
        /// </summary>
        /// <param name="source"></param>
        /// <param name="sortBy"></param>
        /// <param name="isAscending"></param>
        /// <param name="columnsMap"></param>
        /// <typeparam name="T"></typeparam>
        /// <returns></returns>
        public static IQueryable<T> ApplySorting<T, TKey>(
            this IQueryable<T> source,
            string sortBy,
            bool isAscending,
            IDictionary<string, Expression<Func<T, object>>> columnsMap = null
        )
        where T : XBaseEntity<TKey>
        {
            //
            if (columnsMap == null)
            {
                //
                columnsMap = source.FirstOrDefault()
                    .GetDefaultColumnsMap();

                //
                if (columnsMap == null)
                {
                    return source;
                }
            }

            //
            // Validate SortBy ...
            var sortByItem = columnsMap.Keys
                .FirstOrDefault(p =>
                    p.ToNormalString() == sortBy.ToNormalString());
            if (sortByItem.IsNullOrEmpty())
            {
                return source;
            }

            //
            // Apply Sorting ...
            if (isAscending)
            {
                return source.OrderBy(sortByItem);
            }
            else
            {
                return source.OrderByDescending(sortByItem);
            }
        }

        /// <summary>
        /// Apply Sorting on a query
        /// </summary>
        /// <param name="source"></param>
        /// <param name="sortBy"></param>
        /// <param name="isAscending"></param>
        /// <param name="columnsMap"></param>
        /// <typeparam name="T"></typeparam>
        /// <returns></returns>
        public static IEnumerable<T> ApplySorting<T, TKey>(
            this IEnumerable<T> source,
            string sortBy,
            bool isAscending,
            IDictionary<string, Expression<Func<T, object>>> columnsMap = null
        )
        where T : XBaseEntity<TKey>
        {
            //
            if (columnsMap == null)
            {
                //
                columnsMap = source.FirstOrDefault()
                    .GetDefaultColumnsMap();

                //
                if (columnsMap == null)
                {
                    return source;
                }
            }

            //
            // Validate SortBy ...
            var sortByItem = columnsMap.Keys
                .FirstOrDefault(p =>
                    p.ToNormalString() == sortBy.ToNormalString());
            if (sortByItem.IsNullOrEmpty())
            {
                return source;
            }

            //
            // Apply Sorting ...
            if (isAscending)
            {
                return source.OrderBy(sortByItem);
            }
            else
            {
                return source.OrderByDescending(sortByItem);
            }
        }

        /// <summary>
        /// Apply Sorting on a Enumerable
        /// </summary>
        /// <param name="source"></param>
        /// <param name="sortBy"></param>
        /// <param name="isAscending"></param>
        /// <param name="columnsMap"></param>
        /// <typeparam name="T"></typeparam>
        /// <returns></returns>
        public static IEnumerable<T> ApplySorting<T>(
            this IEnumerable<T> source,
            string sortBy,
            bool isAscending,
            IDictionary<string, Expression<Func<T, object>>> columnsMap = null
        )
        where T : class
        {
            //
            if (columnsMap == null)
            {
                //
                columnsMap = source.FirstOrDefault()
                    .GetDefaultColumnsMap();

                //
                if (columnsMap == null)
                {
                    return source;
                }
            }

            //
            // Validate SortBy ...
            var sortByItem = columnsMap.Keys
                .FirstOrDefault(p =>
                    p.ToNormalString() == sortBy.ToNormalString());
            if (sortByItem.IsNullOrEmpty())
            {
                return source;
            }

            //
            // Apply Sorting ...
            if (isAscending)
            {
                return source.OrderBy(sortByItem);
            }
            else
            {
                return source.OrderByDescending(sortByItem);
            }
        }

        /// <summary>
        /// Apply Paging on a qury
        /// </summary>
        /// <param name="source"></param>
        /// <param name="page"></param>
        /// <param name="pageSize"></param>
        /// <typeparam name="T"></typeparam>
        /// <returns></returns>
        public static IQueryable<T> ApplyPaging<T>(
            this IQueryable<T> source,
            int? page,
            int? pageSize
        )
        {
            //
            if (!page.HasValue ||
                page <= 0)
            {
                page = 1;
            }

            //
            if (!pageSize.HasValue ||
                pageSize <= 0 ||
                pageSize > XDataServiceConstants.MAX_AVAILABLE_PAGE_SIZE)
            {
                pageSize = XDataServiceConstants.DEFAULT_PAGE_SIZE;
            }

            //
            var pageVal = page.GetValueOrDefault();
            var pageSizeVal = pageSize.GetValueOrDefault();

            //
            return source
                .Skip((pageVal - 1) * pageSizeVal)
                .Take(pageSizeVal);
        }

        /// <summary>
        /// Apply Paging on a Enumerable
        /// </summary>
        /// <param name="source"></param>
        /// <param name="page"></param>
        /// <param name="pageSize"></param>
        /// <typeparam name="T"></typeparam>
        /// <returns></returns>
        public static IEnumerable<T> ApplyPaging<T>(
            this IEnumerable<T> source,
            int? page,
            int? pageSize
        )
        {
            //
            if (!page.HasValue ||
                page <= 0)
            {
                page = 1;
            }

            //
            if (!pageSize.HasValue ||
                pageSize <= 0 ||
                pageSize > XDataServiceConstants.MAX_AVAILABLE_PAGE_SIZE)
            {
                pageSize = XDataServiceConstants.DEFAULT_PAGE_SIZE;
            }

            //
            var pageVal = page.GetValueOrDefault();
            var pageSizeVal = pageSize.GetValueOrDefault();

            //
            return source
                .Skip((pageVal - 1) * pageSizeVal)
                .Take(pageSizeVal);
        }

        /// <summary>
        /// Count Query Pages based on Specified Total Number ...
        /// </summary>
        /// <param name="source"></param>
        /// <param name="totalItems"></param>
        /// <returns></returns>
        public static int CountPages(this XQuery source, int totalItems)
        {
            //
            int result = 0;

            //
            // Validate and Calculate ...
            if (!source.IsNull() && source.PageSize > 0 && totalItems > 0)
            {
                //
                result = totalItems / source.PageSize;
                if (totalItems % source.PageSize > 0)
                {
                    result++;
                }
            }

            //
            return result;
        }

        /// <summary>
        /// Normalize an XQuery based on Data Service Configurations ...
        /// </summary>
        /// <param name="source"></param>
        /// <param name="configuration"></param>
        /// <returns></returns>
        public static XQuery NormalizeQuery(
            this XQuery source,
            XDataServiceConfiguration configuration //
        )
        {
            //
            if (source.IsNull())
            {
                source = new XQuery();
            }

            //
            // Page Size Normalization ...
            if (source.PageSize < configuration.PagingConfiguration.MinAvailablePageSize)
            {
                source.PageSize = configuration.PagingConfiguration.MinAvailablePageSize;
            }
            if (source.PageSize > configuration.PagingConfiguration.MaxAvailablePageSize)
            {
                source.PageSize = configuration.PagingConfiguration.MaxAvailablePageSize;
            }

            //
            return source;
        }
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xDataService\Extensions\XDatabaseDescriptorExtensions.cs

using xCommons.Extensions;
using xDataService.Constants;
using xDataService.Models;

namespace xDataService.Extensions
{
    public static class XDatabaseDescriptorExtensions
    {
        /// <summary>
        /// Validate a Database Descriptor ...
        /// </summary>
        /// <param name="source"></param>
        /// <returns></returns>
        public static bool IsValid(this XDatabaseDescriptor source)
        {
            //
            var result =
                !source.IsNull() &&
                !source.Name.IsNullOrEmpty();

            //
            return result;
        }

        /// <summary>
        /// Chack a Descriptor Has Provider or not ...
        /// </summary>
        /// <param name="source"></param>
        /// <returns></returns>
        public static bool HasProvider(this XDatabaseDescriptor source)
        {
            //
            var result =
                source.IsValid() &&
                source.Provider != XDbProviders.None;

            //
            return result;
        }

        /// <summary>
        /// Check a Descriptor Has EF Core Context or not ...
        /// </summary>
        /// <param name="source"></param>
        /// <returns></returns>
        public static bool HasContext(this XDatabaseDescriptor source)
        {
            //
            var result =
                source.IsValid() &&
                source.HasProvider() &&
                source.Provider != XDbProviders.MongoDB &&
                !source.Context.IsNull();

            //
            return result;
        }

        /// <summary>
        /// Check a Descriptor Has Repositories or not ...
        /// </summary>
        /// <param name="source"></param>
        /// <returns></returns>
        public static bool HasRepositories(this XDatabaseDescriptor source)
        {
            //
            var result =
                source.IsValid() &&
                source.HasProvider() &&
                !source.Repositories.IsNull() &&
                source.Repositories.HasChild();

            //
            return result;
        }

        /// <summary>
        /// Check a Descriptor Has MongoDB Convention Packs ...
        /// </summary>
        /// <param name="source"></param>
        /// <returns></returns>
        public static bool HasConventionPacks(this XDatabaseDescriptor source)
        {
            //
            var result =
                source.IsValid() &&
                source.HasProvider() &&
                source.Provider == XDbProviders.MongoDB &&
                !source.ConventionPacks.IsNull();

            //
            return result;
        }
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xDataService\Extensions\XDataServiceConfigurationExtensions.cs

using System.Linq;
using xCommons.Extensions;
using xDataService.Configuration;
using xDataService.Constants;

namespace xDataService.Extensions {
    public static class XDataServiceConfigurationExtensions {
        /// <summary>
        /// Extract Provider enum from Provider Type ...
        /// </summary>
        /// <param name="source"></param>
        /// <returns></returns>
        public static XDbProviders ToDbProvider (this string source) {
            //
            if (source.IsNullOrEmpty ()) {
                return XDbProviders.None;
            }

            //
            source = source.ToNormalString ();

            //
            var result = source == ProviderType.MySQL.ToNormalString () ?
                XDbProviders.MySQL :
                source == ProviderType.SQLite.ToNormalString () ?
                XDbProviders.SQLite :
                source == ProviderType.SQLServer.ToNormalString () ?
                XDbProviders.SQLServer :
                source == ProviderType.MongoDB.ToNormalString () ?
                XDbProviders.MongoDB :
                XDbProviders.None;

            //
            return result;
        }

        /// <summary>
        /// Retrieve Mongo URI from ConnectionString
        /// </summary>
        /// <param name="source"></param>
        /// <returns></returns>
        public static string GetMongoDbURI (this XDataBaseConfiguration source) {
            //
            var parts = source.GetConnectionParts ();
            var result = parts
                .Where (p => p.Trim ().StartsWith ("Uri="))
                .FirstOrDefault ();
            result = result.Replace ("Uri=", "").Trim ();

            //
            return result;
        }

        /// <summary>
        /// Retrieve Mongo Database Name from Connaction string
        /// </summary>
        /// <param name="source"></param>
        /// <returns></returns>
        public static string GetMongoDbDatabase (this XDataBaseConfiguration source) {
            //
            var parts = source.GetConnectionParts ();
            var result = parts
                .Where (p => p.Trim ().StartsWith ("Database="))
                .FirstOrDefault ();
            result = result.Replace ("Database=", "").Trim ();

            //
            return result;
        }

        //
        #region Private ...
        private static string[] GetConnectionParts (this XDataBaseConfiguration source) {
            //
            var result = source.ConnectionString.Split (';');

            //
            return result;
        }
        #endregion
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xDataService\Extensions\XGraphQLExtensions.cs

using GraphQL;
using GraphQL.Types;
using xDataService.Constants;
using xModels.Dtos;

namespace xDataService.Extensions {
    public static class XGraphQLExtensions {
        public static TKey GetIdArgument<TKey> (this IResolveFieldContext<object> source) {
            return source.GetArgument<TKey> (XGraphQLHelper.GetIdArgument<IntGraphType>().Name);
        }

        public static bool GetIgnoreSoftDeletedArgument<T> (this IResolveFieldContext<T> source) {
            return source.GetArgument<bool> (XGraphQLHelper.IgnoreSoftDeletedArgument.Name);
        }

        public static string GetSearchQueryArgument<T> (this IResolveFieldContext<T> source) {
            return source.GetArgument<string> (XGraphQLHelper.SearchQueryArgument.Name);
        }

        public static XQuery GetQueryArgument<T> (this IResolveFieldContext<T> source) {
            return source.GetArgument<XQuery> (XGraphQLHelper.QueryArgument.Name);
        }
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xDataService\Extensions\XMongoDbExtensions.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using MongoDB.Bson;
using MongoDB.Driver;
using MongoDB.Driver.Core.Bindings;
using MongoDB.Driver.Core.Clusters;
using MongoDB.Driver.Core.Servers;
using MongoDB.Driver.Core.WireProtocol.Messages.Encoders;
using MongoDB.Driver.Linq;
using xDataService.Mongo;

namespace xDataService.Extensions {
    public static class XMongoDbExtensions {
        public static Guid ToGuid (this ObjectId source) {
            //
            var bytes = source
                .ToByteArray ()
                .Concat (new byte[] { 5, 5, 5, 5 })
                .ToArray ();

            //
            var result = new Guid (bytes);

            //
            return result;
        }

        public static ObjectId ToObjectId (this Guid source) {
            //
            var bytes = source
                .ToByteArray ()
                .Take (12)
                .ToArray ();

            //
            var result = new ObjectId (bytes);

            //
            return result;
        }

        public static IAsyncEnumerable<T> ToAsyncEnumerable<T> (this IAsyncCursorSource<T> asyncCursorSource) {
            return new XAsyncEnumerableAdapter<T> (asyncCursorSource);
        }

        public static async IAsyncEnumerable<T> ToAsyncEnumerable<T> (this IAsyncCursor<T> source) {
            while (await source.MoveNextAsync ()) {
                foreach (var current in source.Current) {
                    yield return current;
                }
            }
        }

        public static XMongoAsyncCursor<T> ToAsyncCursor<T> (this IQueryable<T> source) {
            return new XMongoAsyncCursor<T> (source);
        }
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xDataService\Extensions\XReferenceExtensions.cs

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using xCommons.Extensions;
using xDataService.Models;

namespace xDataService.Extensions
{
    public static class XReferenceExtensions
    {
        /// <summary>
        /// Converts an XReference<T> to String Representation ...
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="source"></param>
        /// <param name="splitter"></param>
        /// <returns></returns>
        public static string ToXReferenceString<T>(
            this XReference<T> source,
            char? splitter = '_'
        )
        {
            //
            var result = string.Empty;

            //
            // Normalize Splitter ...
            if (!splitter.HasValue)
            {
                splitter = '_';
            }

            //
            if (!source.IsNullOrDefault() && source.Index >= 0 && !source.ReferencedTo.IsNull())
            {
                result = $"{source.ProvidedFor}{splitter.Value}{source.ReferencedTo}{splitter.Value}{source.Index}";
            }

            //
            return result;
        }

        /// <summary>
        /// Parse an String and Extract to XReference<T> if it's Described ...
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="source"></param>
        /// <param name="splitter"></param>
        /// <returns></returns>
        public static XReference<T> FromXReference<T>(
            this string source,
            char? splitter = '_'
        )
        {
            //
            XReference<T> result = null;

            //
            // Normalize Splitter ...
            if (!splitter.HasValue)
            {
                splitter = '_';
            }

            //
            if (!source.IsNullOrEmpty())
            {
                //
                var parts = source.Split(splitter.Value);
                if (parts.Count() >= 3)
                {
                    //
                    T referencedTo;
                    try
                    {
                        referencedTo = (T)Convert.ChangeType(parts[1], typeof(T));
                    } catch
                    {
                        referencedTo = (T)TypeDescriptor.GetConverter(typeof(T)).ConvertFrom(parts[1]);                        
                    }

                    //
                    // Parse String Parts ...
                    result = new XReference<T>
                    {
                        ReferencedTo = referencedTo,
                        Index = (int)Convert.ChangeType(parts[2], typeof(int)),
                        ProvidedFor = (string)Convert.ChangeType(parts[0], typeof(string)),
                    };
                }
            }

            //
            return result;
        }

        /// <summary>
        /// Converts a Collection of XReference<T> to it's String Representation ...
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="source"></param>
        /// <returns></returns>
        public static string ToXReferenceString<T>(this IEnumerable<XReference<T>> source)
        {
            //
            var result = string.Empty;

            //
            if (!source.IsNull() && source.HasChild())
            {
                //
                var stringList = new List<string>();
                foreach (var s in source)
                {
                    //
                    var sr = ToXReferenceString(s);
                    if (!sr.IsNullOrEmpty())
                    {
                        stringList.Add(sr);
                    }
                }

                //
                result = stringList.ToListString();
            }

            //
            return result;
        }
        public static string ToXReferenceString<T>(this ICollection<XReference<T>> source)
        {
            //
            var result = source
                .AsEnumerable()
                .ToXReferenceString();

            //
            return result;
        }
        public static string ToXReferenceString<T>(this IList<XReference<T>> source)
        {
            //
            var result = source
                .AsEnumerable()
                .ToXReferenceString();

            //
            return result;
        }

        /// <summary>
        /// Parse an string to XReference<T> Collection Representation ...
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="source"></param>
        /// <returns></returns>
        public static IList<XReference<T>> ParseXReferenceList<T>(this string source)
        {
            //
            var result = new List<XReference<T>>();

            //
            if (!source.IsNullOrEmpty())
            {
                //
                var stringList = source.ParseListString<string>();
                if (!stringList.IsNull() && stringList.HasChild())
                {
                    //
                    foreach (var s in stringList)
                    {
                        //
                        var sr = FromXReference<T>(s);
                        if (!sr.IsNullOrDefault())
                        {
                            result.Add(sr);
                        }
                    }
                }
            }

            //
            return result;
        }
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xDataService\Extensions\XRepositoryDescriptorExtensions.cs

using xCommons.Extensions;
using xDataService.Db;
using xDataService.Interfaces;
using xDataService.Models;
using xDataService.Providers;
using xModels.Base;

namespace xDataService.Extensions
{
    public static class XRepositoryDescriptorExtensions
    {
        //
        #region Hasers ...
        /// <summary>
        /// Validate a Descriptor ...
        /// </summary>
        /// <param name="source"></param>
        /// <returns></returns>
        public static bool IsValid(this XRepositoryDescriptor source)
        {
            var result =
                !source.IsNull() &&
                !source.Key.IsNull() &&
                !source.Entity.IsNull();

            //
            return result;
        }

        /// <summary>
        /// Check a Descriptor Has Events Service or not ...
        /// </summary>
        /// <param name="source"></param>
        /// <returns></returns>
        public static bool HasEvents(this XRepositoryDescriptor source)
        {
            //
            var result =
                source.IsValid() &&
                !source.EventsService.IsNull() &&
                !source.EventsImplementation.IsNull();

            //
            return result;
        }

        /// <summary>
        /// Check a Descriptor Has EF Core Context or not ...
        /// </summary>
        /// <param name="source"></param>
        /// <returns></returns>
        public static bool HasContext(this XRepositoryDescriptor source)
        {
            //
            var result =
                source.IsValid() &&
                !source.Context.IsNull();

            //
            return result;
        }

        /// <summary>
        /// Check a Descriptor Has GraphQL Support or not ...
        /// </summary>
        /// <param name="source"></param>
        /// <returns></returns>
        public static bool HasGraphSupport(this XRepositoryDescriptor source)
        {
            //
            var result =
                source.IsValid() &&
                source.HasRepository() &&
                !source.GraphType.IsNull() &&
                !source.GraphQuery.IsNull() &&
                !source.GraphSchema.IsNull() &&
                !source.GraphTypeKey.IsNull() &&
                !source.GraphTypeHelperService.IsNull() &&
                !source.GraphTypeHelperImplementation.IsNull();

            //
            return result;
        }

        /// <summary>
        /// Check a Descriptor Has Key Generator Service or not ...
        /// </summary>
        /// <param name="source"></param>
        /// <returns></returns>
        public static bool HasKeyGenerator(this XRepositoryDescriptor source)
        {
            //
            var result =
                source.IsValid() &&
                !source.KeyGeneratorService.IsNull() &&
                !source.KeyGeneratorImplementation.IsNull();

            //
            return result;
        }

        /// <summary>
        /// Check a Descriptor Has Repository Service or not ...
        /// </summary>
        /// <param name="source"></param>
        /// <returns></returns>
        public static bool HasRepository(this XRepositoryDescriptor source)
        {
            //
            var result =
                source.IsValid() &&
                !source.RepositoryService.IsNull() &&
                !source.RepositoryImplementation.IsNull();

            //
            return result;
        }

        /// <summary>
        /// Check a Descriptor Has Seeder or not ...
        /// </summary>
        /// <param name="source"></param>
        /// <returns></returns>
        public static bool HasSeeder(this XRepositoryDescriptor source)
        {
            //
            var result =
                source.IsValid() &&
                source.HasRepository() &&
                !source.SeederService.IsNull() &&
                !source.SeederImplementation.IsNull();

            //
            return result;
        }
        #endregion

        //
        #region Builders ...
        public static XRepositoryDescriptor AddEntity<TEntity, TKey>(
            this XRepositoryDescriptor source
        )
        where TEntity : XBaseEntity<TKey>
        {
            //
            if (source.IsNull())
            {
                source = new XRepositoryDescriptor();
            }

            //
            source.Key = typeof(TKey);
            source.Entity = typeof(TEntity);

            //
            return source;
        }

        public static XRepositoryDescriptor AddEvents<TEntity, TKey, TEventsService, TEventsImplementation>(
            this XRepositoryDescriptor source
        )
        where TEntity : XBaseEntity<TKey>
        where TEventsService : IXBaseRepositoryEvents<TEntity>
        where TEventsImplementation : XBaseRepositoryEvents<TEntity>
        {
            //
            if (source.IsNull())
            {
                //
                source = new XRepositoryDescriptor();
                source = source.AddEntity<TEntity, TKey>();
            }

            //
            source.EventsService = typeof(TEventsService);
            source.EventsImplementation = typeof(TEventsImplementation);

            //
            return source;
        }

        public static XRepositoryDescriptor AddKeyGenerator<TEntity, TKey, TKeyGeneratorService, TKeyGeneratorImplementation>(
            this XRepositoryDescriptor source
        )
        where TEntity : XBaseEntity<TKey>
        where TKeyGeneratorService : IXKeyGenerator<TEntity, TKey>
        where TKeyGeneratorImplementation : XKeyGenerator<TEntity, TKey>
        {
            //
            if (source.IsNull())
            {
                //
                source = new XRepositoryDescriptor();
                source = source.AddEntity<TEntity, TKey>();
            }

            //
            source.KeyGeneratorService = typeof(TKeyGeneratorService);
            source.KeyGeneratorImplementation = typeof(TKeyGeneratorImplementation);

            //
            return source;
        }

        public static XRepositoryDescriptor AddSeeder<TEntity, TKey, TSeederService, TSeederImplementation>(
            this XRepositoryDescriptor source            
        )
        where TEntity : XBaseEntity<TKey>
        where TSeederService : IXBaseDbSeeder<TEntity, TKey>
        where TSeederImplementation : XBaseDbSeeder<TEntity, TKey>
        {
            //
            if (source.IsNull())
            {
                //
                source = new XRepositoryDescriptor();
                source = source.AddEntity<TEntity, TKey>();
            }

            //
            source.SeederService = typeof(TSeederService);
            source.SeederImplementation = typeof(TSeederImplementation);

            //
            return source;
        }

        public static XRepositoryDescriptor AddEFRepository<TEntity, TKey, TContext, TRepositoryService, TRepositoryImplementation>(
            this XRepositoryDescriptor source
        )
        where TContext : XDbContext
        where TEntity : XBaseEntity<TKey>
        where TRepositoryService : IXBaseRepository<TEntity, TKey>
        where TRepositoryImplementation : XBaseEFRepository<TEntity, TKey, TContext>
        {
            //
            if (source.IsNull())
            {
                //
                source = new XRepositoryDescriptor();
                source = source.AddEntity<TEntity, TKey>();
            }

            //
            source.RepositoryService = typeof(TRepositoryService);
            source.RepositoryImplementation = typeof(TRepositoryImplementation);

            //
            return source;
        }

        public static XRepositoryDescriptor AddMongoRepository<TEntity, TKey, TRepositoryService, TRepositoryImplementation>(
            this XRepositoryDescriptor source
        )
        where TEntity : XBaseEntity<TKey>
        where TRepositoryService : IXBaseRepository<TEntity, TKey>
        where TRepositoryImplementation : XBaseMongoRepository<TEntity, TKey>
        {
            //
            if (source.IsNull())
            {
                //
                source = new XRepositoryDescriptor();
                source = source.AddEntity<TEntity, TKey>();
            }

            //
            source.RepositoryService = typeof(TRepositoryService);
            source.RepositoryImplementation = typeof(TRepositoryImplementation);

            //
            return source;
        }

        public static XRepositoryDescriptor AddInMemoryRepository<TEntity, TKey, TRepositoryService, TRepositoryImplementation>(
            this XRepositoryDescriptor source
        )
        where TEntity : XBaseEntity<TKey>
        where TRepositoryService : IXBaseRepository<TEntity, TKey>
        where TRepositoryImplementation : XBaseInMemoryRepository<TEntity, TKey>
        {
            //
            if (source.IsNull())
            {
                //
                source = new XRepositoryDescriptor();
                source = source.AddEntity<TEntity, TKey>();
            }

            //
            source.RepositoryService = typeof(TRepositoryService);
            source.RepositoryImplementation = typeof(TRepositoryImplementation);

            //
            return source;
        }
        #endregion
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xDataService\GraphQL\XBaseGraphObjectType.cs

using GraphQL.Types;
using xModels.Base;

namespace xDataService.GraphQL
{
    /// <summary>
    /// Base Entity GraphType Object ...
    /// </summary>
    /// <typeparam name="TKey"></typeparam>
    public abstract class XBaseGraphObjectType<TEntity, TKey> : ObjectGraphType<TEntity>
        where TEntity : XBaseEntity<TKey> {
            public XBaseGraphObjectType () {
                //
                Name = $"{typeof(TEntity).Name}GraphType";

                //
                Field (x => x.Id);
                Field (x => x.Deleted);
            }
        }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xDataService\GraphQL\XBaseGraphQLEventType.cs

using GraphQL.Types;
using xDataService.Models;
using xModels.Base;

namespace xDataService.GraphQL {
    public class XBaseGraphQLEventType<TEntity, TKey, TGraphType> : ObjectGraphType<XBaseEventModel<TEntity>>
        where TGraphType : IGraphType
    where TEntity : XBaseEntity<TKey> {
        public XBaseGraphQLEventType () {
            //
            Name = nameof (XBaseGraphQLEventType<TEntity, TKey, TGraphType>);

            //
            Field (x => x.Model, type : typeof (TGraphType));
        }
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xDataService\GraphQL\XBaseGraphQLQuery.cs

using System;
using System.Linq.Expressions;
using GraphQL.Types;
using xCommons.Extensions;
using xDataService.Configuration;
using xDataService.Constants;
using xDataService.Extensions;
using xDataService.Interfaces;
using xDataService.Models;
using xModels.Base;

namespace xDataService.GraphQL
{
    public abstract class XBaseGraphQLQuery<TEntity, TKey, TGraph, TGraphKey> : ObjectGraphType, IXBaseGraphQLQuery<TEntity, TKey, TGraph, TGraphKey>
    where TEntity : XBaseEntity<TKey>
    where TGraph : IGraphType
    where TGraphKey : IGraphType
    {
        //
        protected readonly XDataServiceConfiguration configuration;
        protected readonly IXBaseRepository<TEntity, TKey> repository;
        protected readonly IXBaseGraphQLTypeHelper<TEntity, TKey> helper;

        //
        public XBaseGraphQLQuery(
            XDataServiceConfiguration configuration,
            IXBaseRepository<TEntity, TKey> repository,
            IXBaseGraphQLTypeHelper<TEntity, TKey> helper
        )
        {
            //
            this.helper = helper;
            this.repository = repository;
            this.configuration = configuration;

            //
            Name = GetType().Name;

            //
            #region Retrieve ...
            //
            // Get ...
            FieldAsync<TGraph>(
                name: helper.GetInQuerySingleName(),
                arguments: new QueryArguments(
                    XGraphQLHelper.GetIdArgument<TGraphKey>(),
                    XGraphQLHelper.IgnoreSoftDeletedArgument
                ),
                resolve: async context =>
                await repository
                .GetAsync(
                    includeBuilder: null,
                    id: context.GetIdArgument<TKey>(),
                    ignoreSoftDeleteds: context.GetIgnoreSoftDeletedArgument()
                )
                .ToDynamicObject()
            );

            //
            // GetAll ...
            FieldAsync<ListGraphType<TGraph>>(
                name: helper.GetInQueryCollectionName(),
                arguments: new QueryArguments(
                    XGraphQLHelper.IgnoreSoftDeletedArgument
                ),
                resolve: async context =>
                await repository
                .GetAllAsync(
                    orderBuilder: null,
                    includeBuilder: null,
                    ignoreSoftDeleteds: context.GetIgnoreSoftDeletedArgument()
                )
                .ToDynamicObject()
            );

            //
            // FindOne ...
            FieldAsync<TGraph>(
                name: helper.GetFindOneName(),
                arguments: new QueryArguments(
                    XGraphQLHelper.SearchQueryArgument,
                    XGraphQLHelper.IgnoreSoftDeletedArgument
                ),
                resolve: async (context) =>
                {
                    //
                    var searchQuery = context.GetSearchQueryArgument();
                    Expression<Func<TEntity, bool>> whereClase = pe => pe
                        .PropValuesContains(searchQuery);

                    //
                    return await repository
                        .FindOneAsync(
                            includeBuilder: null,
                            predicate: whereClase,
                            ignoreSoftDeleteds: context.GetIgnoreSoftDeletedArgument()
                        )
                        .ToDynamicObject();
                }
            );

            //
            // FindMany ...
            FieldAsync<ListGraphType<TGraph>>(
                name: helper.GetFindManyName(),
                arguments: new QueryArguments(
                    XGraphQLHelper.SearchQueryArgument,
                    XGraphQLHelper.IgnoreSoftDeletedArgument
                ),
                resolve: async (context) =>
                {
                    //
                    var searchQuery = context.GetSearchQueryArgument();
                    Expression<Func<TEntity, bool>> whereClase = pe => pe
                        .PropValuesContains(searchQuery);

                    //
                    return await repository
                        .FindManyAsync(
                            orderBuilder: null,
                            includeBuilder: null,
                            predicate: whereClase,
                            ignoreSoftDeleteds: context.GetIgnoreSoftDeletedArgument()
                        )
                        .ToDynamicObject();
                }
            );

            //
            // Query ...
            FieldAsync<XGraphQueryResult<TEntity, TGraph>>(
                name: helper.GetQueryName(),
                arguments: new QueryArguments(
                    XGraphQLHelper.QueryArgument,
                    XGraphQLHelper.IgnoreSoftDeletedArgument
                ),
                resolve: async context =>
                await repository
                .QueryAsync(
                    predicate: null,
                    orderBuilder: null,
                    includeBuilder: null,
                    query: context.GetQueryArgument(),
                    ignoreSoftDeleteds: context.GetIgnoreSoftDeletedArgument()
                )
                .ToDynamicObject()
            );

            //
            // Count ...
            FieldAsync<IntGraphType>(
                name: helper.GetCountName(),
                arguments: new QueryArguments(
                    XGraphQLHelper.IgnoreSoftDeletedArgument
                ),
                resolve: async context =>
                await repository
                .CountAsync(
                    ignoreSoftDeleteds: context.GetIgnoreSoftDeletedArgument()
                )
            );

            //
            // Exists ...
            FieldAsync<BooleanGraphType>(
                name: helper.GetExistsName(),
                arguments: new QueryArguments(
                    XGraphQLHelper.GetIdArgument<TGraphKey>(),
                    XGraphQLHelper.IgnoreSoftDeletedArgument
                ),
                resolve: async context =>
                await repository.IsExistsAsync(
                    id: context.GetIdArgument<TKey>(),
                    ignoreSoftDeleteds: context.GetIgnoreSoftDeletedArgument()
                )
            );
            #endregion
        }
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xDataService\GraphQL\XBaseGraphQLSubscription.cs

using System.Collections.Generic;
using GraphQL.Resolvers;
using GraphQL.Types;
using xCommons.Extensions;
using xDataService.Providers;
using xDataService.Interfaces;
using xDataService.Models;
using xModels.Base;

namespace xDataService.GraphQL {
    public abstract class XBaseGraphQLSubscription<TEntity, TKey, TGraph> : ObjectGraphType
    where TGraph : IGraphType
    where TEntity : XBaseEntity<TKey> {
        public XBaseGraphQLSubscription (IXBaseRepositoryEvents<TEntity> eventProvider = null) {
            //
            Name = GetType ().Name;

            //
            // Check if base repository patter registered ...
            if (!eventProvider.IsNull ()) {
                //
                // Add ...
                AddField (new EventStreamFieldType {
                    //
                    Name = nameof (XBaseRepositoryEvents<TEntity>.AddEvent),
                        Type = typeof (XBaseGraphQLEventType<TEntity, TKey, TGraph>),
                        Resolver = new FuncFieldResolver<XBaseEventModel<TEntity>> (
                            context => context.Source as XBaseEventModel<TEntity>
                        ),
                        Subscriber = new EventStreamResolver<XBaseEventModel<TEntity>> (context => {
                            return eventProvider.OnAddObservable;
                        })
                });

                //
                // Add Many ...
                AddField (new EventStreamFieldType {
                    //
                    Name = nameof (XBaseRepositoryEvents<TEntity>.AddManyEvent),
                        Type = typeof (XBaseGraphQLEventType<TEntity, TKey, TGraph>),
                        Resolver = new FuncFieldResolver<XBaseEventModel<IEnumerable<TEntity>>> (
                            context => context.Source as XBaseEventModel<IEnumerable<TEntity>>
                        ),
                        Subscriber = new EventStreamResolver<XBaseEventModel<IEnumerable<TEntity>>> (context => {
                            return eventProvider.OnAddManyObservable;
                        })
                });

                //
                // Update ...
                AddField (new EventStreamFieldType {
                    //
                    Name = nameof (XBaseRepositoryEvents<TEntity>.UpdateEvent),
                        Type = typeof (XBaseGraphQLEventType<TEntity, TKey, TGraph>),
                        Resolver = new FuncFieldResolver<XBaseEventModel<TEntity>> (
                            context => context.Source as XBaseEventModel<TEntity>
                        ),
                        Subscriber = new EventStreamResolver<XBaseEventModel<TEntity>> (context => {
                            return eventProvider.OnUpdateObservable;
                        })
                });

                //
                // Update Mnay ...
                AddField (new EventStreamFieldType {
                    //
                    Name = nameof (XBaseRepositoryEvents<TEntity>.UpdateManyEvent),
                        Type = typeof (XBaseGraphQLEventType<TEntity, TKey, TGraph>),
                        Resolver = new FuncFieldResolver<XBaseEventModel<IEnumerable<TEntity>>> (
                            context => context.Source as XBaseEventModel<IEnumerable<TEntity>>
                        ),
                        Subscriber = new EventStreamResolver<XBaseEventModel<IEnumerable<TEntity>>> (context => {
                            return eventProvider.OnUpdateManyObservable;
                        })
                });

                //
                // Remove ...
                AddField (new EventStreamFieldType {
                    //
                    Name = nameof (XBaseRepositoryEvents<TEntity>.RemoveEvent),
                        Type = typeof (XBaseGraphQLEventType<TEntity, TKey, TGraph>),
                        Resolver = new FuncFieldResolver<XBaseEventModel<TEntity>> (
                            context => context.Source as XBaseEventModel<TEntity>
                        ),
                        Subscriber = new EventStreamResolver<XBaseEventModel<TEntity>> (context => {
                            return eventProvider.OnRemoveObservable;
                        })
                });

                //
                // Remove Many ...
                AddField (new EventStreamFieldType {
                    //
                    Name = nameof (XBaseRepositoryEvents<TEntity>.RemoveManyEvent),
                        Type = typeof (XBaseGraphQLEventType<TEntity, TKey, TGraph>),
                        Resolver = new FuncFieldResolver<XBaseEventModel<IEnumerable<TEntity>>> (
                            context => context.Source as XBaseEventModel<IEnumerable<TEntity>>
                        ),
                        Subscriber = new EventStreamResolver<XBaseEventModel<IEnumerable<TEntity>>> (context => {
                            return eventProvider.OnRemoveManyObservable;
                        })
                });
            }
        }
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xDataService\GraphQL\XBaseGraphQLTypeHelper.cs

using xCommons.Extensions;
using xDataService.Configuration;
using xDataService.Interfaces;
using xModels.Base;

namespace xDataService.GraphQL
{
    public abstract class XBaseGraphQLTypeHelper<TEntity, TKey> : IXBaseGraphQLTypeHelper<TEntity, TKey>
    where TEntity : XBaseEntity<TKey>
    {
        //
        private readonly XDataServiceConfiguration configuration;

        //
        protected XBaseGraphQLTypeHelper(
            XDataServiceConfiguration configuration = null
        )
        {
            this.configuration = configuration;
        }

        //
        public abstract string GetInQueryCollectionName();

        public abstract string GetInQuerySingleName();

        //
        public string GetFindOneName()
        {
            return $"find{GetInQuerySingleName().ToNormalString().Capitalize()}";
        }

        public string GetFindManyName()
        {
            return $"find{GetInQueryCollectionName().ToNormalString().Capitalize()}";
        }

        public string GetQueryName()
        {
            return $"query{GetInQueryCollectionName().ToNormalString().Capitalize()}";
        }

        public string GetCountName()
        {
            return $"count{GetInQueryCollectionName().ToNormalString().Capitalize()}";
        }

        public string GetExistsName()
        {
            return $"exists{GetInQuerySingleName().ToNormalString().Capitalize()}";
        }

        public string GetGraphQLPath(string baseGraphPath = null)
        {
            //
            baseGraphPath = baseGraphPath.IsNullOrEmpty() ?
                configuration.IsNull() || configuration.GraphQLBasePath.IsNullOrEmpty() ?
                "" :
                configuration.GraphQLBasePath :
                baseGraphPath;

            //
            var basePath = baseGraphPath
                .EndsWith("/") ?
                baseGraphPath
                .Substring(0, baseGraphPath.Length - 1) :
                baseGraphPath;

            //
            return $"{basePath}/{GetInQueryCollectionName().ToNormalString()}";
        }
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xDataService\Helpers\XCursorHelper.cs

using System;
using System.Collections.Generic;
using System.Linq;
using xCommons.Extensions;

namespace xDataService.Helpers {
    public partial class XCursorHelper {
        public static string ToCursor<T> (T id) {
            //
            // Check Numbers ...
            if (id.ToString ().IsDigits ()) {
                return Convert
                    .ToBase64String (BitConverter
                        .GetBytes (Convert.ToInt32 (id))
                    );
            } else
                //
                // Check Guid ...
                if (id.ToString ().IsGuid ()) {
                    return Convert
                        .ToBase64String (new Guid (id.ToString ())
                            .ToByteArray ());
                } else
            //
            // Assume as String ...
            {
                return Convert
                    .ToBase64String (id
                        .ToString ().ToBytes ());
            }
        }

        public static T FromCursor<T> (string cursor) {
            //
            // Check Numbers ...
            var returnType = typeof (T);
            if (returnType == typeof (int) ||
                returnType == typeof (long) ||
                returnType == typeof (decimal)) {
                return Convert.ChangeType ((BitConverter
                        .ToInt32 (Convert
                            .FromBase64String (cursor),
                            0
                        ))
                    .ToDynamicObject (), returnType);
            } else
                //
                // Check Guid ...
                if (returnType == typeof (Guid)) {
                    return Convert.ChangeType ((new Guid (
                            Convert.FromBase64String (cursor)
                        ))
                        .ToDynamicObject (), returnType);
                } else
            //
            // Assume as String ...
            {
                return Convert.ChangeType ((
                        Convert.FromBase64String (cursor)
                    )
                    .ToDynamicObject (), returnType);
            }
        }

        public static (string firstCursor, string lastCursor) GetFirstAndLastCursor<T> (IEnumerable<T> ids) {
            //
            if (ids?.Any () != true) {
                return (null, null);
            }

            //
            var firstCursor = ToCursor (ids.First ());
            var lastCursor = ToCursor (ids.Last ());

            //
            return (firstCursor, lastCursor);
        }
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xDataService\Helpers\XDataServiceHelper.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using GraphQL;
using GraphQL.Server;
using GraphQL.Server.Ui.Playground;
using GraphQL.Server.Ui.Voyager;
using GraphQL.Types;
using Microsoft.AspNetCore.Builder;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.DependencyInjection;
using MongoDB.Bson.Serialization;
using MongoDB.Bson.Serialization.Conventions;
using MySql.EntityFrameworkCore.Extensions;
using xCommons.Extensions;
using xDataService.Constants;
using xDataService.Db;
using xDataService.Extensions;
using xDataService.GraphQL;
using xDataService.Interfaces;
using xDataService.Models;
using xDataService.Providers;
using xExceptions.Constants;
using xModels.Base;

namespace xDataService.Helpers
{
    public static class XDataServiceHelper
    {
        /// <summary>
        /// Register DbContext ...
        /// </summary>
        /// <param name="source"></param>
        /// <param name="databaseDescriptor"></param>
        /// <param name="lifetime"></param>
        /// <typeparam name="TContext"></typeparam>
        public static void AddXDbContext<TContext>(
            IServiceCollection source,
            XDatabaseDescriptor databaseDescriptor,
            ServiceLifetime lifetime = ServiceLifetime.Scoped
        )
        where TContext : XDbContext
        {
            //
            var isValid =
                databaseDescriptor.IsValid() &&
                databaseDescriptor.HasProvider();
            if (!isValid)
            {
                XException.InvalidConfiguration.Throw();
            }

            //
            switch (databaseDescriptor.Provider)
            {
                //
                // MySQL ...
                case XDbProviders.MySQL:
                    //
                    source.AddEntityFrameworkMySQL();
                    source.AddDbContext<TContext>(cfg =>
                    {
                        //
                        cfg.UseMySQL(
                            databaseDescriptor.ConnectionString,
                            databaseDescriptor.OptionsBuilder
                        );
                    }, lifetime);
                    break;

                //
                // SQLite ...
                case XDbProviders.SQLite:
                    //
                    source.AddEntityFrameworkSqlite();
                    source.AddDbContext<TContext>(cfg =>
                    {
                        //
                        cfg.UseSqlite(
                            databaseDescriptor.ConnectionString,
                            databaseDescriptor.OptionsBuilder
                        );
                    }, lifetime);
                    break;

                //
                // Oracle ...
                case XDbProviders.Oracle:
                    //
                    source.AddEntityFrameworkOracle();
                    source.AddDbContext<TContext>(cfg =>
                    {
                        //
                        cfg.UseOracle(
                            databaseDescriptor.ConnectionString,
                            databaseDescriptor.OptionsBuilder
                        );
                    }, lifetime);
                    break;

                //
                // SQLServer ...
                case XDbProviders.SQLServer:
                    //
                    source.AddEntityFrameworkSqlServer();
                    source.AddDbContext<TContext>(cfg =>
                    {
                        //
                        cfg.UseSqlServer(
                            databaseDescriptor.ConnectionString,
                            databaseDescriptor.OptionsBuilder
                        );
                    }, lifetime);
                    break;

                //
                // Mongo DB ...
                case XDbProviders.MongoDB:
                    //
                    #region XBaseEntity Mappers ...
                    //
                    // Map ID as BsonId here ...
                    BsonClassMap.RegisterClassMap<XBaseEntity<Guid>>(cm =>
                    {
                        //
                        cm.AutoMap();
                        cm.MapIdMember(c => c.Id);
                    });
                    BsonClassMap.RegisterClassMap<XBaseEntity<int>>(cm =>
                    {
                        //
                        cm.AutoMap();
                        cm.MapIdMember(c => c.Id);
                    });
                    BsonClassMap.RegisterClassMap<XBaseEntity<long>>(cm =>
                    {
                        //
                        cm.AutoMap();
                        cm.MapIdMember(c => c.Id);
                    });
                    BsonClassMap.RegisterClassMap<XBaseEntity<string>>(cm =>
                    {
                        //
                        cm.AutoMap();
                        cm.MapIdMember(c => c.Id);
                    });
                    #endregion

                    //
                    // Check Has Convention Packs ...
                    isValid = databaseDescriptor.HasConventionPacks();
                    if (isValid)
                    {
                        //
                        ConventionRegistry.Register(
                            nameof(
                                databaseDescriptor.ConventionPacks
                            ),
                            databaseDescriptor.ConventionPacks,
                            type => !type.FullName
                            .IsNullOrEmpty()
                        );
                    }
                    break;
            }

            //
            isValid =
                databaseDescriptor.Provider == XDbProviders.MySQL ||
                databaseDescriptor.Provider == XDbProviders.SQLite ||
                databaseDescriptor.Provider == XDbProviders.Oracle ||
                databaseDescriptor.Provider == XDbProviders.SQLServer;
            if (isValid)
            {
                //
                AddXUnitOfWorks<TContext>(
                    source,
                    lifetime
                );
            }
        }

        //
        #region Repository ...
        /// <summary>
        /// Register Repository ...
        /// </summary>
        /// <param name="source"></param>
        /// <param name="repositoryDescriptor"></param>
        /// <param name="lifetime"></param>
        /// <typeparam name="TEntity"></typeparam>
        /// <typeparam name="TKey"></typeparam>
        /// <returns></returns>
        public static void AddXRepository<TEntity, TKey>(
            IServiceCollection source,
            XRepositoryDescriptor<TEntity, TKey> repositoryDescriptor,
            ServiceLifetime lifetime = ServiceLifetime.Scoped
        )
        where TEntity : XBaseEntity<TKey>
        {
            //
            var isValid = repositoryDescriptor.IsValid();
            if (!isValid)
            {
                return;
            }
        }

        /// <summary>
        /// Register Repository ...
        /// </summary>
        /// <param name="source"></param>
        /// <param name="repositoryDescriptor"></param>
        /// <param name="lifetime"></param>
        /// <typeparam name="TEntity"></typeparam>
        /// <typeparam name="TKey"></typeparam>
        /// <typeparam name="TKeyGeneratorService"></typeparam>
        /// <typeparam name="TKeyGeneratorImplementation"></typeparam>
        /// <returns></returns>
        public static void AddXRepository<
            TEntity,
            TKey,
            TKeyGeneratorService,
            TKeyGeneratorImplementation
        >(
            IServiceCollection source,
            XRepositoryDescriptor<TEntity, TKey, TKeyGeneratorService, TKeyGeneratorImplementation> repositoryDescriptor,
            ServiceLifetime lifetime = ServiceLifetime.Scoped
        )
        where TEntity : XBaseEntity<TKey>
        where TKeyGeneratorService : IXKeyGenerator<TEntity, TKey>
        where TKeyGeneratorImplementation : XKeyGenerator<TEntity, TKey>
        {
            //
            var isValid = repositoryDescriptor.IsValid();
            if (!isValid)
            {
                return;
            }

            //
            // Register KeyGenerator ...
            isValid = repositoryDescriptor.HasKeyGenerator();
            if (isValid)
            {
                //
                AddXKeyGenerator<TEntity, TKey, TKeyGeneratorService, TKeyGeneratorImplementation>(
                    source,
                    repositoryDescriptor,
                    lifetime
                );
            }
        }

        /// <summary>
        /// Register Repository ...
        /// </summary>
        /// <param name="source"></param>
        /// <param name="repositoryDescriptor"></param>
        /// <param name="lifetime"></param>
        /// <typeparam name="TEntity"></typeparam>
        /// <typeparam name="TKey"></typeparam>
        /// <typeparam name="TKeyGeneratorService"></typeparam>
        /// <typeparam name="TKeyGeneratorImplementation"></typeparam>
        /// <typeparam name="TEventsService"></typeparam>
        /// <typeparam name="TEventsImplementation"></typeparam>
        /// <returns></returns>
        public static void AddXRepository<
            TEntity,
            TKey,
            TKeyGeneratorService,
            TKeyGeneratorImplementation,
            TEventsService,
            TEventsImplementation
        >(
            IServiceCollection source,
            XRepositoryDescriptor<TEntity, TKey, TKeyGeneratorService, TKeyGeneratorImplementation, TEventsService, TEventsImplementation> repositoryDescriptor,
            ServiceLifetime lifetime = ServiceLifetime.Scoped
        )
        where TEntity : XBaseEntity<TKey>
        where TEventsService : IXBaseRepositoryEvents<TEntity>
        where TKeyGeneratorService : IXKeyGenerator<TEntity, TKey>
        where TEventsImplementation : XBaseRepositoryEvents<TEntity>
        where TKeyGeneratorImplementation : XKeyGenerator<TEntity, TKey>
        {
            //
            var isValid = repositoryDescriptor.IsValid();
            if (!isValid)
            {
                return;
            }

            //
            // Register KeyGenerator ...
            isValid = repositoryDescriptor.HasKeyGenerator();
            if (isValid)
            {
                //
                AddXKeyGenerator<TEntity, TKey, TKeyGeneratorService, TKeyGeneratorImplementation>(
                    source,
                    repositoryDescriptor,
                    lifetime
                );
            }

            //
            // Register Events ...
            isValid = repositoryDescriptor.HasEvents();
            if (isValid)
            {
                //
                AddXEvents<TEntity, TKey, TEventsService, TEventsImplementation>(
                    source,
                    repositoryDescriptor,
                    lifetime
                );
            }
        }

        /// <summary>
        /// Register Repository ...
        /// </summary>
        /// <param name="source"></param>
        /// <param name="repositoryDescriptor"></param>
        /// <param name="lifetime"></param>
        /// <typeparam name="TEntity"></typeparam>
        /// <typeparam name="TKey"></typeparam>
        /// <typeparam name="TKeyGeneratorService"></typeparam>
        /// <typeparam name="TKeyGeneratorImplementation"></typeparam>
        /// <typeparam name="TEventsService"></typeparam>
        /// <typeparam name="TEventsImplementation"></typeparam>
        /// <typeparam name="TGraph"></typeparam>
        /// <typeparam name="TGraphKey"></typeparam>
        /// <typeparam name="TGraphQuery"></typeparam>
        /// <typeparam name="TGraphTypeHelperService"></typeparam>
        /// <typeparam name="TGraphTypeHelperImplementation"></typeparam>
        /// <typeparam name="TGraphSchema"></typeparam>
        /// <returns></returns>
        public static void AddXRepository<
            TEntity,
            TKey,
            TKeyGeneratorService,
            TKeyGeneratorImplementation,
            TEventsService,
            TEventsImplementation,
            TGraph,
            TGraphKey,
            TGraphQuery,
            TGraphTypeHelperService,
            TGraphTypeHelperImplementation,
            TGraphSchema
        >(
            IServiceCollection source,
            XRepositoryDescriptor<TEntity, TKey, TKeyGeneratorService, TKeyGeneratorImplementation, TEventsService, TEventsImplementation, TGraph, TGraphKey, TGraphQuery, TGraphTypeHelperService, TGraphTypeHelperImplementation, TGraphSchema> repositoryDescriptor,
            ServiceLifetime lifetime = ServiceLifetime.Scoped
        )
        where TGraphSchema : Schema
        where TGraphKey : IGraphType
        where TEntity : XBaseEntity<TKey>
        where TGraph : XBaseGraphObjectType<TEntity, TKey>
        where TEventsService : IXBaseRepositoryEvents<TEntity>
        where TKeyGeneratorService : IXKeyGenerator<TEntity, TKey>
        where TEventsImplementation : XBaseRepositoryEvents<TEntity>
        where TKeyGeneratorImplementation : XKeyGenerator<TEntity, TKey>
        where TGraphTypeHelperService : IXBaseGraphQLTypeHelper<TEntity, TKey>
        where TGraphQuery : XBaseGraphQLQuery<TEntity, TKey, TGraph, TGraphKey>
        where TGraphTypeHelperImplementation : XBaseGraphQLTypeHelper<TEntity, TKey>
        {
            //
            var isValid = repositoryDescriptor.IsValid();
            if (!isValid)
            {
                return;
            }

            //
            // Register KeyGenerator ...
            isValid = repositoryDescriptor.HasKeyGenerator();
            if (isValid)
            {
                //
                AddXKeyGenerator<TEntity, TKey, TKeyGeneratorService, TKeyGeneratorImplementation>(
                    source,
                    repositoryDescriptor,
                    lifetime
                );
            }

            //
            // Register Events ...
            isValid = repositoryDescriptor.HasEvents();
            if (isValid)
            {
                //
                AddXEvents<TEntity, TKey, TEventsService, TEventsImplementation>(
                    source,
                    repositoryDescriptor,
                    lifetime
                );
            }

            //
            // Register Graph ...
            isValid = repositoryDescriptor.HasGraphSupport();
            if (isValid)
            {
                //
                AddXGraphQL<TEntity, TKey, TGraph, TGraphKey, TGraphQuery, TGraphTypeHelperService, TGraphTypeHelperImplementation, TGraphSchema>(
                    source,
                    repositoryDescriptor,
                    lifetime
                );
            }
        }

        /// <summary>
        /// Register Repository ...
        /// </summary>
        /// <param name="source"></param>
        /// <param name="repositoryDescriptor"></param>
        /// <param name="lifetime"></param>
        /// <typeparam name="TEntity"></typeparam>
        /// <typeparam name="TKey"></typeparam>
        /// <typeparam name="TKeyGeneratorService"></typeparam>
        /// <typeparam name="TKeyGeneratorImplementation"></typeparam>
        /// <typeparam name="TEventsService"></typeparam>
        /// <typeparam name="TEventsImplementation"></typeparam>
        /// <typeparam name="TGraph"></typeparam>
        /// <typeparam name="TGraphKey"></typeparam>
        /// <typeparam name="TGraphQuery"></typeparam>
        /// <typeparam name="TGraphTypeHelperService"></typeparam>
        /// <typeparam name="TGraphTypeHelperImplementation"></typeparam>
        /// <typeparam name="TGraphSchema"></typeparam>
        /// <typeparam name="TRepositoryService"></typeparam>
        /// <typeparam name="TRepositoryImplementation"></typeparam>
        /// <returns></returns>
        public static void AddXRepository<
            TEntity,
            TKey,
            TKeyGeneratorService,
            TKeyGeneratorImplementation,
            TEventsService,
            TEventsImplementation,
            TGraph,
            TGraphKey,
            TGraphQuery,
            TGraphTypeHelperService,
            TGraphTypeHelperImplementation,
            TGraphSchema,
            TRepositoryService,
            TRepositoryImplementation
        >(
            IServiceCollection source,
            XInMemoryRepositoryDescriptor<TEntity, TKey, TKeyGeneratorService, TKeyGeneratorImplementation, TEventsService, TEventsImplementation, TGraph, TGraphKey, TGraphQuery, TGraphTypeHelperService, TGraphTypeHelperImplementation, TGraphSchema, TRepositoryService, TRepositoryImplementation> repositoryDescriptor,
            ServiceLifetime lifetime = ServiceLifetime.Scoped
        )
        where TGraphSchema : Schema
        where TGraphKey : IGraphType
        where TEntity : XBaseEntity<TKey>
        where TGraph : XBaseGraphObjectType<TEntity, TKey>
        where TEventsService : IXBaseRepositoryEvents<TEntity>
        where TKeyGeneratorService : IXKeyGenerator<TEntity, TKey>
        where TRepositoryService : IXBaseRepository<TEntity, TKey>
        where TEventsImplementation : XBaseRepositoryEvents<TEntity>
        where TKeyGeneratorImplementation : XKeyGenerator<TEntity, TKey>
        where TGraphTypeHelperService : IXBaseGraphQLTypeHelper<TEntity, TKey>
        where TGraphQuery : XBaseGraphQLQuery<TEntity, TKey, TGraph, TGraphKey>
        where TRepositoryImplementation : XBaseInMemoryRepository<TEntity, TKey>
        where TGraphTypeHelperImplementation : XBaseGraphQLTypeHelper<TEntity, TKey>
        {
            //
            var isValid = repositoryDescriptor.IsValid();
            if (!isValid)
            {
                return;
            }

            //
            // Register KeyGenerator ...
            isValid = repositoryDescriptor.HasKeyGenerator();
            if (isValid)
            {
                //
                AddXKeyGenerator<TEntity, TKey, TKeyGeneratorService, TKeyGeneratorImplementation>(
                    source,
                    repositoryDescriptor,
                    lifetime
                );
            }

            //
            // Register Events ...
            isValid = repositoryDescriptor.HasEvents();
            if (isValid)
            {
                //
                AddXEvents<TEntity, TKey, TEventsService, TEventsImplementation>(
                    source,
                    repositoryDescriptor,
                    lifetime
                );
            }

            //
            // Register Graph ...
            isValid = repositoryDescriptor.HasGraphSupport();
            if (isValid)
            {
                //
                AddXGraphQL<TEntity, TKey, TGraph, TGraphKey, TGraphQuery, TGraphTypeHelperService, TGraphTypeHelperImplementation, TGraphSchema>(
                    source,
                    repositoryDescriptor,
                    lifetime
                );
            }

            //
            // Register Repository ...
            isValid = repositoryDescriptor.HasRepository();
            if (isValid)
            {
                //
                source.Add(
                    new ServiceDescriptor(
                        repositoryDescriptor.RepositoryService,
                        repositoryDescriptor.RepositoryImplementation,
                        lifetime
                    )
                );
            }
        }

        /// <summary>
        /// Register Repository ...
        /// </summary>
        /// <param name="source"></param>
        /// <param name="repositoryDescriptor"></param>
        /// <param name="lifetime"></param>
        /// <typeparam name="TEntity"></typeparam>
        /// <typeparam name="TKey"></typeparam>
        /// <typeparam name="TKeyGeneratorService"></typeparam>
        /// <typeparam name="TKeyGeneratorImplementation"></typeparam>
        /// <typeparam name="TEventsService"></typeparam>
        /// <typeparam name="TEventsImplementation"></typeparam>
        /// <typeparam name="TGraph"></typeparam>
        /// <typeparam name="TGraphKey"></typeparam>
        /// <typeparam name="TGraphQuery"></typeparam>
        /// <typeparam name="TGraphTypeHelperService"></typeparam>
        /// <typeparam name="TGraphTypeHelperImplementation"></typeparam>
        /// <typeparam name="TGraphSchema"></typeparam>
        /// <typeparam name="TRepositoryService"></typeparam>
        /// <typeparam name="TRepositoryImplementation"></typeparam>
        /// <typeparam name="TSeederService"></typeparam>
        /// <typeparam name="TSeederImplementation"></typeparam>
        /// <returns></returns>
        public static void AddXRepository<
            TEntity,
            TKey,
            TKeyGeneratorService,
            TKeyGeneratorImplementation,
            TEventsService,
            TEventsImplementation,
            TGraph,
            TGraphKey,
            TGraphQuery,
            TGraphTypeHelperService,
            TGraphTypeHelperImplementation,
            TGraphSchema,
            TRepositoryService,
            TRepositoryImplementation,
            TSeederService,
            TSeederImplementation
        >(
            IServiceCollection source,
            XInMemoryRepositoryDescriptor<TEntity, TKey, TKeyGeneratorService, TKeyGeneratorImplementation, TEventsService, TEventsImplementation, TGraph, TGraphKey, TGraphQuery, TGraphTypeHelperService, TGraphTypeHelperImplementation, TGraphSchema, TRepositoryService, TRepositoryImplementation, TSeederService, TSeederImplementation> repositoryDescriptor,
            ServiceLifetime lifetime = ServiceLifetime.Scoped
        )
        where TGraphSchema : Schema
        where TGraphKey : IGraphType
        where TEntity : XBaseEntity<TKey>
        where TSeederService : IXBaseDbSeeder<TEntity, TKey>
        where TSeederImplementation : XBaseDbSeeder<TEntity, TKey>
        where TGraph : XBaseGraphObjectType<TEntity, TKey>
        where TEventsService : IXBaseRepositoryEvents<TEntity>
        where TKeyGeneratorService : IXKeyGenerator<TEntity, TKey>
        where TRepositoryService : IXBaseRepository<TEntity, TKey>
        where TEventsImplementation : XBaseRepositoryEvents<TEntity>
        where TKeyGeneratorImplementation : XKeyGenerator<TEntity, TKey>
        where TGraphTypeHelperService : IXBaseGraphQLTypeHelper<TEntity, TKey>
        where TGraphQuery : XBaseGraphQLQuery<TEntity, TKey, TGraph, TGraphKey>
        where TRepositoryImplementation : XBaseInMemoryRepository<TEntity, TKey>
        where TGraphTypeHelperImplementation : XBaseGraphQLTypeHelper<TEntity, TKey>
        {
            //
            var isValid = repositoryDescriptor.IsValid();
            if (!isValid)
            {
                return;
            }

            //
            // Register KeyGenerator ...
            isValid = repositoryDescriptor.HasKeyGenerator();
            if (isValid)
            {
                //
                AddXKeyGenerator<TEntity, TKey, TKeyGeneratorService, TKeyGeneratorImplementation>(
                    source,
                    repositoryDescriptor,
                    lifetime
                );
            }

            //
            // Register Events ...
            isValid = repositoryDescriptor.HasEvents();
            if (isValid)
            {
                //
                AddXEvents<TEntity, TKey, TEventsService, TEventsImplementation>(
                    source,
                    repositoryDescriptor,
                    lifetime
                );
            }

            //
            // Register Graph ...
            isValid = repositoryDescriptor.HasGraphSupport();
            if (isValid)
            {
                //
                AddXGraphQL<TEntity, TKey, TGraph, TGraphKey, TGraphQuery, TGraphTypeHelperService, TGraphTypeHelperImplementation, TGraphSchema>(
                    source,
                    repositoryDescriptor,
                    lifetime
                );
            }

            //
            // Register Repository ...
            isValid = repositoryDescriptor.HasRepository();
            if (isValid)
            {
                //
                source.Add(
                    new ServiceDescriptor(
                        repositoryDescriptor.RepositoryService,
                        repositoryDescriptor.RepositoryImplementation,
                        lifetime
                    )
                );
            }

            //
            // DbSeeder ...
            isValid = repositoryDescriptor.HasSeeder();
            if (isValid)
            {
                //
                source.Add(
                    new ServiceDescriptor(
                        repositoryDescriptor.SeederService,
                        repositoryDescriptor.SeederImplementation,
                        lifetime
                    )
                );
            }
        }

        /// <summary>
        /// Register Repository ...
        /// </summary>
        /// <param name="source"></param>
        /// <param name="repositoryDescriptor"></param>
        /// <param name="lifetime"></param>
        /// <typeparam name="TEntity"></typeparam>
        /// <typeparam name="TKey"></typeparam>
        /// <typeparam name="TKeyGeneratorService"></typeparam>
        /// <typeparam name="TKeyGeneratorImplementation"></typeparam>
        /// <typeparam name="TEventsService"></typeparam>
        /// <typeparam name="TEventsImplementation"></typeparam>
        /// <typeparam name="TGraph"></typeparam>
        /// <typeparam name="TGraphKey"></typeparam>
        /// <typeparam name="TGraphQuery"></typeparam>
        /// <typeparam name="TGraphTypeHelperService"></typeparam>
        /// <typeparam name="TGraphTypeHelperImplementation"></typeparam>
        /// <typeparam name="TGraphSchema"></typeparam>
        /// <typeparam name="TRepositoryService"></typeparam>
        /// <typeparam name="TRepositoryImplementation"></typeparam>
        /// <returns></returns>
        public static void AddXRepository<
            TEntity,
            TKey,
            TKeyGeneratorService,
            TKeyGeneratorImplementation,
            TEventsService,
            TEventsImplementation,
            TGraph,
            TGraphKey,
            TGraphQuery,
            TGraphTypeHelperService,
            TGraphTypeHelperImplementation,
            TGraphSchema,
            TRepositoryService,
            TRepositoryImplementation
        >(
            IServiceCollection source,
            XMongoRepositoryDescriptor<TEntity, TKey, TKeyGeneratorService, TKeyGeneratorImplementation, TEventsService, TEventsImplementation, TGraph, TGraphKey, TGraphQuery, TGraphTypeHelperService, TGraphTypeHelperImplementation, TGraphSchema, TRepositoryService, TRepositoryImplementation> repositoryDescriptor,
            ServiceLifetime lifetime = ServiceLifetime.Scoped
        )
        where TGraphSchema : Schema
        where TGraphKey : IGraphType
        where TEntity : XBaseEntity<TKey>
        where TGraph : XBaseGraphObjectType<TEntity, TKey>
        where TEventsService : IXBaseRepositoryEvents<TEntity>
        where TKeyGeneratorService : IXKeyGenerator<TEntity, TKey>
        where TRepositoryService : IXBaseRepository<TEntity, TKey>
        where TEventsImplementation : XBaseRepositoryEvents<TEntity>
        where TKeyGeneratorImplementation : XKeyGenerator<TEntity, TKey>
        where TRepositoryImplementation : XBaseMongoRepository<TEntity, TKey>
        where TGraphTypeHelperService : IXBaseGraphQLTypeHelper<TEntity, TKey>
        where TGraphQuery : XBaseGraphQLQuery<TEntity, TKey, TGraph, TGraphKey>
        where TGraphTypeHelperImplementation : XBaseGraphQLTypeHelper<TEntity, TKey>
        {
            //
            var isValid = repositoryDescriptor.IsValid();
            if (!isValid)
            {
                return;
            }

            //
            // Register KeyGenerator ...
            isValid = repositoryDescriptor.HasKeyGenerator();
            if (isValid)
            {
                //
                AddXKeyGenerator<TEntity, TKey, TKeyGeneratorService, TKeyGeneratorImplementation>(
                    source,
                    repositoryDescriptor,
                    lifetime
                );
            }

            //
            // Register Events ...
            isValid = repositoryDescriptor.HasEvents();
            if (isValid)
            {
                //
                AddXEvents<TEntity, TKey, TEventsService, TEventsImplementation>(
                    source,
                    repositoryDescriptor,
                    lifetime
                );
            }

            //
            // Register Graph ...
            isValid = repositoryDescriptor.HasGraphSupport();
            if (isValid)
            {
                //
                AddXGraphQL<TEntity, TKey, TGraph, TGraphKey, TGraphQuery, TGraphTypeHelperService, TGraphTypeHelperImplementation, TGraphSchema>(
                    source,
                    repositoryDescriptor,
                    lifetime
                );
            }

            //
            // Register Repository ...
            isValid = repositoryDescriptor.HasRepository();
            if (isValid)
            {
                //
                source.Add(
                    new ServiceDescriptor(
                        repositoryDescriptor.RepositoryService,
                        repositoryDescriptor.RepositoryImplementation,
                        lifetime
                    )
                );
            }
        }

        /// <summary>
        /// Register Repository ...
        /// </summary>
        /// <param name="source"></param>
        /// <param name="repositoryDescriptor"></param>
        /// <param name="lifetime"></param>
        /// <typeparam name="TEntity"></typeparam>
        /// <typeparam name="TKey"></typeparam>
        /// <typeparam name="TKeyGeneratorService"></typeparam>
        /// <typeparam name="TKeyGeneratorImplementation"></typeparam>
        /// <typeparam name="TEventsService"></typeparam>
        /// <typeparam name="TEventsImplementation"></typeparam>
        /// <typeparam name="TGraph"></typeparam>
        /// <typeparam name="TGraphKey"></typeparam>
        /// <typeparam name="TGraphQuery"></typeparam>
        /// <typeparam name="TGraphTypeHelperService"></typeparam>
        /// <typeparam name="TGraphTypeHelperImplementation"></typeparam>
        /// <typeparam name="TGraphSchema"></typeparam>
        /// <typeparam name="TRepositoryService"></typeparam>
        /// <typeparam name="TRepositoryImplementation"></typeparam>
        /// <typeparam name="TSeederService"></typeparam>
        /// <typeparam name="TSeederImplementation"></typeparam>
        /// <returns></returns>
        public static void AddXRepository<
            TEntity,
            TKey,
            TKeyGeneratorService,
            TKeyGeneratorImplementation,
            TEventsService,
            TEventsImplementation,
            TGraph,
            TGraphKey,
            TGraphQuery,
            TGraphTypeHelperService,
            TGraphTypeHelperImplementation,
            TGraphSchema,
            TRepositoryService,
            TRepositoryImplementation,
            TSeederService,
            TSeederImplementation
        >(
            IServiceCollection source,
            XMongoRepositoryDescriptor<TEntity, TKey, TKeyGeneratorService, TKeyGeneratorImplementation, TEventsService, TEventsImplementation, TGraph, TGraphKey, TGraphQuery, TGraphTypeHelperService, TGraphTypeHelperImplementation, TGraphSchema, TRepositoryService, TRepositoryImplementation, TSeederService, TSeederImplementation> repositoryDescriptor,
            ServiceLifetime lifetime = ServiceLifetime.Scoped
        )
        where TGraphSchema : Schema
        where TGraphKey : IGraphType
        where TEntity : XBaseEntity<TKey>
        where TGraph : XBaseGraphObjectType<TEntity, TKey>
        where TSeederService : IXBaseDbSeeder<TEntity, TKey>
        where TEventsService : IXBaseRepositoryEvents<TEntity>
        where TKeyGeneratorService : IXKeyGenerator<TEntity, TKey>
        where TRepositoryService : IXBaseRepository<TEntity, TKey>
        where TSeederImplementation : XBaseDbSeeder<TEntity, TKey>
        where TEventsImplementation : XBaseRepositoryEvents<TEntity>
        where TKeyGeneratorImplementation : XKeyGenerator<TEntity, TKey>
        where TRepositoryImplementation : XBaseMongoRepository<TEntity, TKey>
        where TGraphTypeHelperService : IXBaseGraphQLTypeHelper<TEntity, TKey>
        where TGraphQuery : XBaseGraphQLQuery<TEntity, TKey, TGraph, TGraphKey>
        where TGraphTypeHelperImplementation : XBaseGraphQLTypeHelper<TEntity, TKey>
        {
            //
            var isValid = repositoryDescriptor.IsValid();
            if (!isValid)
            {
                return;
            }

            //
            // Register KeyGenerator ...
            isValid = repositoryDescriptor.HasKeyGenerator();
            if (isValid)
            {
                //
                AddXKeyGenerator<TEntity, TKey, TKeyGeneratorService, TKeyGeneratorImplementation>(
                    source,
                    repositoryDescriptor,
                    lifetime
                );
            }

            //
            // Register Events ...
            isValid = repositoryDescriptor.HasEvents();
            if (isValid)
            {
                //
                AddXEvents<TEntity, TKey, TEventsService, TEventsImplementation>(
                    source,
                    repositoryDescriptor,
                    lifetime
                );
            }

            //
            // Register Graph ...
            isValid = repositoryDescriptor.HasGraphSupport();
            if (isValid)
            {
                //
                AddXGraphQL<TEntity, TKey, TGraph, TGraphKey, TGraphQuery, TGraphTypeHelperService, TGraphTypeHelperImplementation, TGraphSchema>(
                    source,
                    repositoryDescriptor,
                    lifetime
                );
            }

            //
            // Register Repository ...
            isValid = repositoryDescriptor.HasRepository();
            if (isValid)
            {
                //
                source.Add(
                    new ServiceDescriptor(
                        repositoryDescriptor.RepositoryService,
                        repositoryDescriptor.RepositoryImplementation,
                        lifetime
                    )
                );
            }

            //
            // DbSeeder ...
            isValid = repositoryDescriptor.HasSeeder();
            if (isValid)
            {
                //
                source.Add(
                    new ServiceDescriptor(
                        repositoryDescriptor.SeederService,
                        repositoryDescriptor.SeederImplementation,
                        lifetime
                    )
                );
            }
        }

        /// <summary>
        /// Register Repository ...
        /// </summary>
        /// <param name="source"></param>
        /// <param name="repositoryDescriptor"></param>
        /// <param name="lifetime"></param>
        /// <typeparam name="TEntity"></typeparam>
        /// <typeparam name="TKey"></typeparam>
        /// <typeparam name="TKeyGeneratorService"></typeparam>
        /// <typeparam name="TKeyGeneratorImplementation"></typeparam>
        /// <typeparam name="TEventsService"></typeparam>
        /// <typeparam name="TEventsImplementation"></typeparam>
        /// <typeparam name="TGraph"></typeparam>
        /// <typeparam name="TGraphKey"></typeparam>
        /// <typeparam name="TGraphQuery"></typeparam>
        /// <typeparam name="TGraphTypeHelperService"></typeparam>
        /// <typeparam name="TGraphTypeHelperImplementation"></typeparam>
        /// <typeparam name="TGraphSchema"></typeparam>
        /// <typeparam name="TRepositoryService"></typeparam>
        /// <typeparam name="TRepositoryImplementation"></typeparam>
        /// <typeparam name="TContext"></typeparam>
        /// <returns></returns>
        public static void AddXRepository<
            TEntity,
            TKey,
            TKeyGeneratorService,
            TKeyGeneratorImplementation,
            TEventsService,
            TEventsImplementation,
            TGraph,
            TGraphKey,
            TGraphQuery,
            TGraphTypeHelperService,
            TGraphTypeHelperImplementation,
            TGraphSchema,
            TRepositoryService,
            TRepositoryImplementation,
            TContext
        >(
            IServiceCollection source,
            XEFRepositoryDescriptor<TEntity, TKey, TKeyGeneratorService, TKeyGeneratorImplementation, TEventsService, TEventsImplementation, TGraph, TGraphKey, TGraphQuery, TGraphTypeHelperService, TGraphTypeHelperImplementation, TGraphSchema, TRepositoryService, TRepositoryImplementation, TContext> repositoryDescriptor,
            ServiceLifetime lifetime = ServiceLifetime.Scoped
        )
        where TGraphSchema : Schema
        where TContext : XDbContext
        where TGraphKey : IGraphType
        where TEntity : XBaseEntity<TKey>
        where TGraph : XBaseGraphObjectType<TEntity, TKey>
        where TEventsService : IXBaseRepositoryEvents<TEntity>
        where TKeyGeneratorService : IXKeyGenerator<TEntity, TKey>
        where TRepositoryService : IXBaseRepository<TEntity, TKey>
        where TEventsImplementation : XBaseRepositoryEvents<TEntity>
        where TKeyGeneratorImplementation : XKeyGenerator<TEntity, TKey>
        where TGraphTypeHelperService : IXBaseGraphQLTypeHelper<TEntity, TKey>
        where TGraphQuery : XBaseGraphQLQuery<TEntity, TKey, TGraph, TGraphKey>
        where TRepositoryImplementation : XBaseEFRepository<TEntity, TKey, TContext>
        where TGraphTypeHelperImplementation : XBaseGraphQLTypeHelper<TEntity, TKey>
        {
            //
            var isValid = repositoryDescriptor.IsValid();
            if (!isValid)
            {
                return;
            }

            //
            // Register KeyGenerator ...
            isValid = repositoryDescriptor.HasKeyGenerator();
            if (isValid)
            {
                //
                AddXKeyGenerator<TEntity, TKey, TKeyGeneratorService, TKeyGeneratorImplementation>(
                    source,
                    repositoryDescriptor,
                    lifetime
                );
            }

            //
            // Register Events ...
            isValid = repositoryDescriptor.HasEvents();
            if (isValid)
            {
                //
                AddXEvents<TEntity, TKey, TEventsService, TEventsImplementation>(
                    source,
                    repositoryDescriptor,
                    lifetime
                );
            }

            //
            // Register Graph ...
            isValid = repositoryDescriptor.HasGraphSupport();
            if (isValid)
            {
                //
                AddXGraphQL<TEntity, TKey, TGraph, TGraphKey, TGraphQuery, TGraphTypeHelperService, TGraphTypeHelperImplementation, TGraphSchema>(
                    source,
                    repositoryDescriptor,
                    lifetime
                );
            }

            //
            // Register Repository ...
            isValid = repositoryDescriptor.HasRepository();
            if (isValid)
            {
                //
                source.Add(
                    new ServiceDescriptor(
                        repositoryDescriptor.RepositoryService,
                        repositoryDescriptor.RepositoryImplementation,
                        lifetime
                    )
                );
            }
        }

        /// <summary>
        /// Register Repository ...
        /// </summary>
        /// <param name="source"></param>
        /// <param name="repositoryDescriptor"></param>
        /// <param name="lifetime"></param>
        /// <typeparam name="TEntity"></typeparam>
        /// <typeparam name="TKey"></typeparam>
        /// <typeparam name="TKeyGeneratorService"></typeparam>
        /// <typeparam name="TKeyGeneratorImplementation"></typeparam>
        /// <typeparam name="TEventsService"></typeparam>
        /// <typeparam name="TEventsImplementation"></typeparam>
        /// <typeparam name="TGraph"></typeparam>
        /// <typeparam name="TGraphKey"></typeparam>
        /// <typeparam name="TGraphQuery"></typeparam>
        /// <typeparam name="TGraphTypeHelperService"></typeparam>
        /// <typeparam name="TGraphTypeHelperImplementation"></typeparam>
        /// <typeparam name="TGraphSchema"></typeparam>
        /// <typeparam name="TRepositoryService"></typeparam>
        /// <typeparam name="TRepositoryImplementation"></typeparam>
        /// <typeparam name="TContext"></typeparam>
        /// <typeparam name="TSeederService"></typeparam>
        /// <typeparam name="TSeederImplementation"></typeparam>
        /// <returns></returns>
        public static void AddXRepository<
            TEntity,
            TKey,
            TKeyGeneratorService,
            TKeyGeneratorImplementation,
            TEventsService,
            TEventsImplementation,
            TGraph,
            TGraphKey,
            TGraphQuery,
            TGraphTypeHelperService,
            TGraphTypeHelperImplementation,
            TGraphSchema,
            TRepositoryService,
            TRepositoryImplementation,
            TContext,
            TSeederService,
            TSeederImplementation
        >(
            IServiceCollection source,
            XEFRepositoryDescriptor<TEntity, TKey, TKeyGeneratorService, TKeyGeneratorImplementation, TEventsService, TEventsImplementation, TGraph, TGraphKey, TGraphQuery, TGraphTypeHelperService, TGraphTypeHelperImplementation, TGraphSchema, TRepositoryService, TRepositoryImplementation, TContext, TSeederService, TSeederImplementation> repositoryDescriptor,
            ServiceLifetime lifetime = ServiceLifetime.Scoped
        )
        where TGraphSchema : Schema
        where TContext : XDbContext
        where TGraphKey : IGraphType
        where TEntity : XBaseEntity<TKey>
        where TGraph : XBaseGraphObjectType<TEntity, TKey>
        where TSeederService : IXBaseDbSeeder<TEntity, TKey>
        where TEventsService : IXBaseRepositoryEvents<TEntity>
        where TSeederImplementation : XBaseDbSeeder<TEntity, TKey>
        where TKeyGeneratorService : IXKeyGenerator<TEntity, TKey>
        where TRepositoryService : IXBaseRepository<TEntity, TKey>
        where TEventsImplementation : XBaseRepositoryEvents<TEntity>
        where TKeyGeneratorImplementation : XKeyGenerator<TEntity, TKey>
        where TGraphTypeHelperService : IXBaseGraphQLTypeHelper<TEntity, TKey>
        where TGraphQuery : XBaseGraphQLQuery<TEntity, TKey, TGraph, TGraphKey>
        where TRepositoryImplementation : XBaseEFRepository<TEntity, TKey, TContext>
        where TGraphTypeHelperImplementation : XBaseGraphQLTypeHelper<TEntity, TKey>
        {
            //
            var isValid = repositoryDescriptor.IsValid();
            if (!isValid)
            {
                return;
            }

            //
            // Register KeyGenerator ...
            isValid = repositoryDescriptor.HasKeyGenerator();
            if (isValid)
            {
                //
                AddXKeyGenerator<TEntity, TKey, TKeyGeneratorService, TKeyGeneratorImplementation>(
                    source,
                    repositoryDescriptor,
                    lifetime
                );
            }

            //
            // Register Events ...
            isValid = repositoryDescriptor.HasEvents();
            if (isValid)
            {
                //
                AddXEvents<TEntity, TKey, TEventsService, TEventsImplementation>(
                    source,
                    repositoryDescriptor,
                    lifetime
                );
            }

            //
            // Register Graph ...
            isValid = repositoryDescriptor.HasGraphSupport();
            if (isValid)
            {
                //
                AddXGraphQL<TEntity, TKey, TGraph, TGraphKey, TGraphQuery, TGraphTypeHelperService, TGraphTypeHelperImplementation, TGraphSchema>(
                    source,
                    repositoryDescriptor,
                    lifetime
                );
            }

            //
            // Register Repository ...
            isValid = repositoryDescriptor.HasRepository();
            if (isValid)
            {
                //
                source.Add(
                    new ServiceDescriptor(
                        repositoryDescriptor.RepositoryService,
                        repositoryDescriptor.RepositoryImplementation,
                        lifetime
                    )
                );
            }

            //
            // DbSeeder ...
            isValid = repositoryDescriptor.HasSeeder();
            if (isValid)
            {
                //
                source.Add(
                    new ServiceDescriptor(
                        repositoryDescriptor.SeederService,
                        repositoryDescriptor.SeederImplementation,
                        lifetime
                    )
                );
            }
        }

        /// <summary>
        /// Use GraphQL ...
        /// </summary>
        /// <typeparam name="TEntity"></typeparam>
        /// <typeparam name="TKey"></typeparam>
        /// <typeparam name="TGraph"></typeparam>
        /// <typeparam name="TGraphKey"></typeparam>
        /// <typeparam name="TGraphQuery"></typeparam>
        /// <typeparam name="TGraphTypeHelperService"></typeparam>
        /// <typeparam name="TGraphTypeHelperImplementation"></typeparam>
        /// <typeparam name="TGraphSchema"></typeparam>
        /// <param name="source"></param>
        /// <param name="graphBasePath"></param>
        /// <param name="graphPath"></param>
        /// <param name="withPlayGround"></param>
        /// <param name="options"></param>
        public static void UseXGraphQL<
            TEntity,
            TKey,
            TGraph,
            TGraphKey,
            TGraphQuery,
            TGraphTypeHelperService,
            TGraphTypeHelperImplementation,
            TGraphSchema
        >(
            IApplicationBuilder source,
            string graphBasePath,
            string graphPath,
            bool withPlayGround = false
        )
        where TGraphSchema : Schema
        where TGraphKey : IGraphType
        where TEntity : XBaseEntity<TKey>
        where TGraph : XBaseGraphObjectType<TEntity, TKey>
        where TGraphTypeHelperService : IXBaseGraphQLTypeHelper<TEntity, TKey>
        where TGraphQuery : XBaseGraphQLQuery<TEntity, TKey, TGraph, TGraphKey>
        where TGraphTypeHelperImplementation : XBaseGraphQLTypeHelper<TEntity, TKey>
        {
            //
            source.UseGraphQL<TGraphSchema>(graphPath);
            source.UseGraphQLWebSockets<TGraphSchema>();

            //
            if (withPlayGround)
            {
                //
                source.UseGraphQLPlayground(new GraphQLPlaygroundOptions
                {
                    Path = "/ui/playground",
                    GraphQLEndPoint = graphBasePath
                });

                //
                source.UseGraphQLVoyager(new GraphQLVoyagerOptions
                {
                    Path = "/ui/voyager",
                    GraphQLEndPoint = graphBasePath
                });
            }
        }
        #endregion

        //
        #region Entity Assembly Detector ...
        /// <summary>
        /// Extract Assemblies which Contains Entity ...
        /// </summary>
        /// <returns></returns>
        public static List<Assembly> ExtractEntityAssemblies()
        {
            //
            var result = new List<Assembly>();

            //
            var allAssemblies = AppDomain.CurrentDomain.GetAssemblies();
            foreach (var assembly in allAssemblies)
            {
                //
                try
                {
                    //
                    bool hasEntity = assembly
                        .GetExportedTypes()
                        .Any(t => t.IsXEntity());
                    if (hasEntity)
                    {
                        result.Add(assembly);
                    }
                }
                catch { }
            }

            //
            return result;
        }

        /// <summary>
        /// Register All Entities using Model Builder ...
        /// </summary>
        /// <param name="modelBuilder"></param>
        public static void RegisterAllEntities(this ModelBuilder modelBuilder)
        {
            //
            // Extract Entity Container Assemblies ...
            var entityAssemblies = ExtractEntityAssemblies();
            foreach(var assembly in entityAssemblies)
            {
                modelBuilder.ApplyConfigurationsFromAssembly(assembly);
            }
        }

        #endregion

        //
        #region Private ...
        /// <summary>
        /// Register Unit of Works ...
        /// </summary>
        /// <param name="source"></param>
        /// <param name="lifetime"></param>
        /// <typeparam name="TContext"></typeparam>
        public static void AddXUnitOfWorks<TContext>(
            IServiceCollection source,
            ServiceLifetime lifetime = ServiceLifetime.Scoped
        )
        where TContext : XDbContext
        {
            //
            source.Add(
                new ServiceDescriptor(
                    typeof(IXUnitOfWorks<TContext>),
                    typeof(XUnitOfWorks<TContext>),
                    lifetime
                )
            );
        }

        /// <summary>
        /// Register Key Generator Service ...
        /// </summary>
        /// <param name="source"></param>
        /// <param name="repositoryDescriptor"></param>
        /// <param name="lifetime"></param>
        /// <typeparam name="TEntity"></typeparam>
        /// <typeparam name="TKey"></typeparam>
        /// <typeparam name="TKeyGeneratorService"></typeparam>
        /// <typeparam name="TKeyGeneratorImplementation"></typeparam>
        /// <returns></returns>
        public static void AddXKeyGenerator<
            TEntity,
            TKey,
            TKeyGeneratorService,
            TKeyGeneratorImplementation
        >(
            IServiceCollection source,
            XRepositoryDescriptor<TEntity, TKey> repositoryDescriptor,
            ServiceLifetime lifetime = ServiceLifetime.Scoped
        )
        where TEntity : XBaseEntity<TKey>
        where TKeyGeneratorService : IXKeyGenerator<TEntity, TKey>
        where TKeyGeneratorImplementation : XKeyGenerator<TEntity, TKey>
        {
            //
            // Validate ...
            var isValid =
                !source.IsNull() &&
                !repositoryDescriptor.IsNull() &&
                !repositoryDescriptor.KeyGeneratorService.IsNull() &&
                !repositoryDescriptor.KeyGeneratorImplementation.IsNull();
            if (!isValid)
            {
                return;
            }

            //
            // Register ...
            source.Add(
                new ServiceDescriptor(
                    repositoryDescriptor.KeyGeneratorService,
                    repositoryDescriptor.KeyGeneratorImplementation,
                    lifetime
                )
            );
        }

        /// <summary>
        /// Register Events Service ...
        /// </summary>
        /// <param name="source"></param>
        /// <param name="repositoryDescriptor"></param>
        /// <param name="lifetime"></param>
        /// <typeparam name="TEntity"></typeparam>
        /// <typeparam name="TKey"></typeparam>
        /// <typeparam name="TEventsService"></typeparam>
        /// <typeparam name="TEventsImplementation"></typeparam>
        /// <returns></returns>
        public static void AddXEvents<
            TEntity,
            TKey,
            TEventsService,
            TEventsImplementation
        >(
            IServiceCollection source,
            XRepositoryDescriptor<TEntity, TKey> repositoryDescriptor,
            ServiceLifetime lifetime = ServiceLifetime.Scoped
        )
        where TEntity : XBaseEntity<TKey>
        where TEventsService : IXBaseRepositoryEvents<TEntity>
        where TEventsImplementation : XBaseRepositoryEvents<TEntity>
        {
            //
            // Validate ...
            var isValid =
                !source.IsNull() &&
                !repositoryDescriptor.IsNull() &&
                !repositoryDescriptor.EventsService.IsNull() &&
                !repositoryDescriptor.EventsImplementation.IsNull();
            if (!isValid)
            {
                return;
            }

            //
            // Register ...
            source.Add(
                new ServiceDescriptor(
                    repositoryDescriptor.EventsService,
                    repositoryDescriptor.EventsImplementation,
                    lifetime
                )
            );
        }

        /// <summary>
        /// Register GraphQL Service ...
        /// </summary>
        /// <param name="source"></param>
        /// <param name="repositoryDescriptor"></param>
        /// <param name="lifetime"></param>
        /// <typeparam name="TEntity"></typeparam>
        /// <typeparam name="TKey"></typeparam>
        /// <typeparam name="TGraph"></typeparam>
        /// <typeparam name="TGraphKey"></typeparam>
        /// <typeparam name="TGraphQuery"></typeparam>
        /// <typeparam name="TGraphTypeHelperService"></typeparam>
        /// <typeparam name="TGraphTypeHelperImplementation"></typeparam>
        /// <typeparam name="TGraphSchema"></typeparam>
        /// <returns></returns>
        public static void AddXGraphQL<
            TEntity,
            TKey,
            TGraph,
            TGraphKey,
            TGraphQuery,
            TGraphTypeHelperService,
            TGraphTypeHelperImplementation,
            TGraphSchema
        >(
            IServiceCollection source,
            XRepositoryDescriptor<TEntity, TKey> repositoryDescriptor,
            ServiceLifetime lifetime = ServiceLifetime.Scoped
        )
        where TGraphSchema : Schema
        where TGraphKey : IGraphType
        where TEntity : XBaseEntity<TKey>
        where TGraph : XBaseGraphObjectType<TEntity, TKey>
        where TGraphTypeHelperService : IXBaseGraphQLTypeHelper<TEntity, TKey>
        where TGraphQuery : XBaseGraphQLQuery<TEntity, TKey, TGraph, TGraphKey>
        where TGraphTypeHelperImplementation : XBaseGraphQLTypeHelper<TEntity, TKey>
        {
            //
            // Validate ...
            var isValid =
                !source.IsNull() &&
                !repositoryDescriptor.IsNull() &&
                !repositoryDescriptor.GraphType.IsNull() &&
                !repositoryDescriptor.GraphQuery.IsNull() &&
                !repositoryDescriptor.GraphSchema.IsNull() &&
                !repositoryDescriptor.GraphTypeKey.IsNull() &&
                !repositoryDescriptor.GraphTypeHelperService.IsNull() &&
                !repositoryDescriptor.GraphTypeHelperImplementation.IsNull();
            if (!isValid)
            {
                return;
            }

            //
            // Register Graph Type ...
            source.Add(
                new ServiceDescriptor(
                    lifetime: lifetime, // ServiceLifetime.Singleton,
                    serviceType: repositoryDescriptor.GraphType,
                    implementationType: repositoryDescriptor.GraphType
                )
            );

            //
            // Register Graph Events ...
            source.Add(
                new ServiceDescriptor(
                    lifetime: lifetime, // ServiceLifetime.Singleton,
                    serviceType: typeof(XBaseGraphQLEventType<TEntity, TKey, TGraph>),
                    implementationType: typeof(XBaseGraphQLEventType<TEntity, TKey, TGraph>)
                )
            );

            //
            // Register Graph Type Helper ...
            source.Add(
                new ServiceDescriptor(
                    lifetime: ServiceLifetime.Singleton,
                    serviceType: repositoryDescriptor.GraphTypeHelperService,
                    implementationType: repositoryDescriptor.GraphTypeHelperImplementation
                )
            );

            //
            // Register Graph Query ...
            source.Add(
                new ServiceDescriptor(
                    lifetime: lifetime,
                    serviceType: repositoryDescriptor.GraphQuery,
                    implementationType: repositoryDescriptor.GraphQuery
                )
            );

            //
            // Register Graph Schema ...
            source.Add(
                new ServiceDescriptor(
                    lifetime: lifetime,
                    serviceType: repositoryDescriptor.GraphSchema,
                    implementationType: repositoryDescriptor.GraphSchema
                )
            );

            //
            source.AddScoped<IDocumentExecuter, DocumentExecuter>();

            //
            // Register Graph Type Schema ...
            var builder = source.GetRegisteredService<IGraphQLBuilder>();
            if (builder.IsNull())
            {
                //
                Action<GraphQLOptions> options = x =>
                {
                    //
                    x.EnableMetrics = true;
                    x.UnhandledExceptionDelegate = context =>
                    {
                        Console.WriteLine("XGraphQL Error: " + context.OriginalException.Message);
                    };
                };
                builder = source.AddGraphQL(options)
                    .AddNewtonsoftJson(deserializerSettings => { }, serializerSettings => { })
                    .AddWebSockets()
                    .AddDataLoader()
                    .AddGraphTypes(lifetime);
            }
            builder.AddGraphTypes(
                serviceLifetime: lifetime,
                typeFromAssembly: repositoryDescriptor.GraphSchema
            );
        }
        #endregion
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xDataService\Helpers\XGraphQLHelper.cs

using GraphQL.Types;
using xDataService.Models;
using xModels.Dtos;

namespace xDataService.Constants {
    public static class XGraphQLHelper {
        public static QueryArgument<TKey> GetIdArgument<TKey> ()
        where TKey : IGraphType {
            return new QueryArgument<TKey> {
                Name = "id",
                Description = "the id of entity, which you want to retrieve ..."
            };
        }

        public static QueryArgument<BooleanGraphType> IgnoreSoftDeletedArgument = new QueryArgument<BooleanGraphType> {
            Name = "ignoreSoftDeleteds",
            DefaultValue = true,
            Description = "determines result should ignore soft deleted items or not ..."
        };

        public static QueryArgument<StringGraphType> SearchQueryArgument = new QueryArgument<StringGraphType> {
            Name = "searchQuery",
            Description = "the value which had to looking for ..."
        };

        public static QueryArgument<XGraphQueryType> QueryArgument = new QueryArgument<XGraphQueryType> {
            Name = "query",
            DefaultValue = new XQuery (),
            Description = "determines query structure info for retrieving data ..."
        };
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xDataService\Interfaces\IXBaseDbSeeder.cs

using System.Threading.Tasks;
using xDataService.Configuration;
using xModels.Base;

namespace xDataService.Interfaces
{
    /// <summary>
    /// Db Seeder used to seed data on Database on startup time ...
    /// </summary>
    public interface IXBaseDbSeeder<TEntity, TKey>
    where TEntity : XBaseEntity<TKey>
    {
        /// <summary>
        /// Holds Entity Name ...
        /// </summary>
        string Entity { get; }

        /// <summary>
        /// Holds Database Name ...
        /// </summary>
        string Database { get; }

        /// <summary>
        /// Repository Service for Data Manipulation ...
        /// </summary>
        IXBaseRepository<TEntity, TKey> Repository { get; }
        
        /// <summary>
        /// DataServiceConfiguration ...
        /// </summary>
        XDataServiceConfiguration DataServiceConfiguration { get; }

        /// <summary>
        /// do all seeding action by helping of Repositories here ...
        /// </summary>
        /// <returns></returns>
        Task Seed();
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xDataService\Interfaces\IXBaseGraphQLQuery.cs

using GraphQL.Types;
using xModels.Base;

namespace xDataService.Interfaces
{
    public interface IXBaseGraphQLQuery<TEntity, TKey, TGraph, TGraphKey>
    where TEntity : XBaseEntity<TKey>
    where TGraph : IGraphType
    where TGraphKey : IGraphType
    { }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xDataService\Interfaces\IXBaseGraphQLTypeHelper.cs

using xModels.Base;

namespace xDataService.Interfaces
{
    public interface IXBaseGraphQLTypeHelper<TEntity, TKey>
    where TEntity : XBaseEntity<TKey>
    {
        string GetInQuerySingleName();
        
        string GetInQueryCollectionName();

        string GetFindOneName();

        string GetFindManyName();

        string GetQueryName();

        string GetCountName();

        string GetExistsName();

        string GetGraphQLPath(string baseGraphPath = null);
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xDataService\Interfaces\IXBaseReferencedProvider.cs

using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;
using xDataService.Models;
using xModels.Dtos;

namespace xDataService.Interfaces
{
    /// <summary>
    /// in Some Cases we have Entities Which Can Referenced for Specified 
    /// Provider and Types ...
    /// this interface Globaly introduce all available Actions for those ...
    /// 
    /// TKey: type of Provider Models Keys ...
    /// TModel: type of Dto which Referenced ...
    /// </summary>
    public interface IXBaseReferencedProvider<TModel, TKey>
    {
        //
        #region Props ...
        /// <summary>
        /// Provider Identifier ...
        /// </summary>
        string Provider { get; }
        #endregion

        //
        #region Referenced Actions ...
        /// <summary>
        /// Get Specified Indexed Reference for Specific Provided ID ...
        /// </summary>
        /// <param name="providedForId"></param>
        /// <param name="forIndex"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        Task<TModel> GetReference(
            TKey providedForId,
            int forIndex = 0,
            CancellationToken cancellationToken = default
        );

        /// <summary>
        /// Retrieve all Exists References of Specific Provided ID ...
        /// </summary>
        /// <param name="providedForId"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        Task<IEnumerable<TModel>> GetAllReferences(
            TKey providedForId,
            CancellationToken cancellationToken = default
        );

        /// <summary>
        /// Extract all Referencing Models for Specified Key ...
        /// </summary>
        /// <param name="providedForId"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns> 
        Task<IEnumerable<XReference<TKey>>> GetAllReferencings(
            TKey providedForId,
            CancellationToken cancellationToken = default
        );

        /// <summary>
        /// Count References ...
        /// </summary>
        /// <param name="providedForId"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        Task<int> CountReferences(
            TKey providedForId,
            CancellationToken cancellationToken = default
        );

        /// <summary>
        /// Retrieve References of Specific Provided ID as Query ...
        /// </summary>
        /// <param name="query"></param>
        /// <param name="providedForId"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        Task<XQueryResult<TModel>> QueryReferences(
            XQuery query,
            TKey providedForId,
            CancellationToken cancellationToken = default
        );

        /// <summary>
        /// Add Reference a Model to Specific Provided ID ...
        /// </summary>
        /// <param name="model"></param>
        /// <param name="providedForId"></param>
        /// <param name="connectionId"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        Task<bool> AddReference(
            TModel model,
            TKey providedForId,
            string connectionId = null,
            CancellationToken cancellationToken = default
        );

        /// <summary>
        /// Add Reference a Model to Specific XRefence<TKey/> ...
        /// </summary>
        /// <param name="model"></param>
        /// <param name="reference"></param>
        /// <param name="connectionId"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        Task<bool> AddReference(
            TModel model,
            XReference<TKey> reference,
            string connectionId = null,
            CancellationToken cancellationToken = default
        );

        /// <summary>
        /// Remove Reference a Model for Specific Provided ID ...
        /// </summary>
        /// <param name="model"></param>
        /// <param name="providedForId"></param>
        /// <param name="connectionId"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        Task<bool> RemoveReference(
            TModel model,
            TKey providedForId,
            string connectionId = null,
            CancellationToken cancellationToken = default
        );

        /// <summary>
        /// Remove Reference a Model for Specific XRefence<TKey/> ...
        /// </summary>
        /// <param name="model"></param>
        /// <param name="reference"></param>
        /// <param name="connectionId"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        Task<bool> RemoveReference(
            TModel model,
            XReference<TKey> reference,
            string connectionId = null,
            CancellationToken cancellationToken = default
        );

        /// <summary>
        /// Remove All References to Specified Key ...
        /// </summary>
        /// <param name="providedForId"></param>
        /// <param name="connectionId"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        Task<bool> RemoveReferences(
            TKey providedForId,
            string connectionId = null,
            CancellationToken cancellationToken = default
        );
        #endregion
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xDataService\Interfaces\IXBaseRepository.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Runtime.CompilerServices;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.EntityFrameworkCore.Query;
using xModels.Base;
using xModels.Dtos;

namespace xDataService.Interfaces
{
    public interface IXBaseRepository : IDisposable { }

    /// <summary>
    /// Base Repository Pattern Contracts in XDashboard's Data Service ...
    /// use for Data Manipulation ...
    /// </summary>
    /// <typeparam name="T"></typeparam>
    /// <typeparam name="TKey"></typeparam>
    public interface IXBaseRepository<T, TKey> : IXBaseRepository
    where T : XBaseEntity<TKey>
    {
        //
        #region Add ...
        /// <summary>
        /// add a new Entity ...
        /// </summary>
        /// <param name="item"></param>
        /// <param name="saveChanges"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        Task<T> AddAsync(
            T item,
            bool saveChanges = true,
            CancellationToken cancellationToken = default
        );

        /// <summary>
        /// add or update an Entity (add if not exists/update if exists) ...
        /// </summary>
        /// <param name="item"></param>
        /// <param name="saveChanges"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        Task<T> AddOrUpdateAsync(
            T item,
            bool saveChanges = true,
            CancellationToken cancellationToken = default
        );

        /// <summary>
        /// add a range of new Entities ...
        /// </summary>
        /// <param name="items"></param>
        /// <param name="saveChanges"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        Task AddRangeAsync(
            IEnumerable<T> items,
            bool saveChanges = true,
            CancellationToken cancellationToken = default
        );
        #endregion

        //
        #region Update ...
        /// <summary>
        /// Update an Entity values ...
        /// </summary>
        /// <param name="id"></param>
        /// <param name="item"></param>
        /// <param name="saveChanges"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        Task<T> UpdateAsync(
            TKey id,
            T item,
            bool saveChanges = true,
            CancellationToken cancellationToken = default
        );

        /// <summary>
        /// Update a range of Entities ...
        /// </summary>
        /// <param name="items"></param>
        /// <param name="saveChanges"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        Task<bool> UpdateRangeAsync(
            IEnumerable<T> items,
            bool saveChanges = true,
            CancellationToken cancellationToken = default
        );
        #endregion

        //
        #region Remove ...
        /// <summary>
        /// remove an Entity by it's Id ...
        /// </summary>
        /// <param name="id"></param>
        /// <param name="softDelete"></param>
        /// <param name="saveChanges"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        Task<T> RemoveAsync(
            TKey id,
            bool softDelete = true,
            bool saveChanges = true,
            CancellationToken cancellationToken = default
        );

        /// <summary>
        /// remove an Entity ...
        /// </summary>
        /// <param name="item"></param>
        /// <param name="softDelete"></param>
        /// <param name="saveChanges"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        Task<T> RemoveAsync(
            T item,
            bool softDelete = true,
            bool saveChanges = true,
            CancellationToken cancellationToken = default
        );

        /// <summary>
        /// remove a range of exists Entities ...
        /// </summary>
        /// <param name="items"></param>
        /// <param name="softDelete"></param>
        /// <param name="saveChanges"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        Task RemoveRangeAsync(
            IEnumerable<T> items,
            bool softDelete = true,
            bool saveChanges = true,
            CancellationToken cancellationToken = default
        );
        #endregion

        //
        #region Count ...
        /// <summary>
        /// count all exists Entities ...
        /// </summary>
        /// <param name="ignoreSoftDeleteds"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        Task<int> CountAsync(
            bool ignoreSoftDeleteds = true,
            CancellationToken cancellationToken = default
        );

        /// <summary>
        /// count all exists Entities Pages by providing page size ...
        /// </summary>
        /// <param name="pageSize"></param>
        /// <param name="totalItems"></param>
        /// <param name="ignoreSoftDeleteds"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        Task<int> PagesCountAsync(
            int pageSize,
            int? totalItems = null,
            bool ignoreSoftDeleteds = true,
            CancellationToken cancellationToken = default
        );
        #endregion

        //
        #region Retrieve ...
        /// <summary>
        /// retrieve whole items as queryable ...
        /// </summary>
        /// <param name="asNoTracking">a flag for Tracking behaviour</param>
        /// <param name="predicate">an Expression for Filter Items ...</param>
        /// <param name="orderBuilder">an Order Builder expression for Ordering Query ...</param>
        /// <param name="includeBuilder">an Include Builder expression for Including Navigation Properties ...</param>
        /// <returns></returns>
        IQueryable<T> AsQueryable(
            bool asNoTracking = true,
            Expression<Func<T, bool>> predicate = null,
            Func<IQueryable<T>, IOrderedQueryable<T>> orderBuilder = null,
            Func<IQueryable<T>, IIncludableQueryable<T, object>> includeBuilder = null
        );

        /// <summary>
        /// retrieve an Entity by it's Id ...
        /// </summary>
        /// <param name="id"></param>
        /// <param name="ignoreSoftDeleteds"></param>
        /// <param name="includeBuilder"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        Task<T> GetAsync(
            TKey id,
            bool ignoreSoftDeleteds = true,
            Func<IQueryable<T>, IIncludableQueryable<T, object>> includeBuilder = null,
            CancellationToken cancellationToken = default
        );

        /// <summary>
        /// retrieve all exists Entities ...
        /// </summary>
        /// <param name="ignoreSoftDeleteds"></param>
        /// <param name="orderBuilder"></param>
        /// <param name="includeBuilder"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        Task<IEnumerable<T>> GetAllAsync(
            bool ignoreSoftDeleteds = true,
            Func<IQueryable<T>, IOrderedQueryable<T>> orderBuilder = null,
            Func<IQueryable<T>, IIncludableQueryable<T, object>> includeBuilder = null,
            CancellationToken cancellationToken = default
        );

        /// <summary>
        /// retrieve all exists Entities
        /// as Async Enumerable ...
        /// </summary>
        /// <param name="ignoreSoftDeleteds"></param>
        /// <param name="orderBuilder"></param>
        /// <param name="includeBuilder"></param>
        /// <returns></returns>
        IAsyncEnumerable<T> GetAllAsAsyncEnumerable(
            bool ignoreSoftDeleteds = true,
            Func<IQueryable<T>, IOrderedQueryable<T>> orderBuilder = null,
            Func<IQueryable<T>, IIncludableQueryable<T, object>> includeBuilder = null
        );

        /// <summary>
        /// find an Entity by providing a Conditional Expression ...
        /// </summary>
        /// <param name="predicate"></param>
        /// <param name="ignoreSoftDeleteds"></param>
        /// <param name="includeBuilder"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        Task<T> FindOneAsync(
            Expression<Func<T, bool>> predicate,
            bool ignoreSoftDeleteds = true,
            Func<IQueryable<T>, IIncludableQueryable<T, object>> includeBuilder = null,
            CancellationToken cancellationToken = default
        );

        /// <summary>
        /// find a collection of Entities by proving a Conditional Expression ...
        /// </summary>
        /// <param name="predicate"></param>
        /// <param name="ignoreSoftDeleteds"></param>
        /// <param name="orderBuilder"></param>
        /// <param name="includeBuilder"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        Task<IEnumerable<T>> FindManyAsync(
            Expression<Func<T, bool>> predicate,
            bool ignoreSoftDeleteds = true,
            Func<IQueryable<T>, IOrderedQueryable<T>> orderBuilder = null,
            Func<IQueryable<T>, IIncludableQueryable<T, object>> includeBuilder = null,
            CancellationToken cancellationToken = default
        );

        /// <summary>
        /// retrieve Entities based on XQuery Pagination structure ...
        /// </summary>
        /// <param name="query"></param>
        /// <param name="ignoreSoftDeleteds"></param>
        /// <param name="predicate"></param>
        /// <param name="orderBuilder"></param>
        /// <param name="includeBuilder"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        Task<XQueryResult<T>> QueryAsync(
            XQuery query,
            bool ignoreSoftDeleteds = true,
            Expression<Func<T, bool>> predicate = null,
            Func<IQueryable<T>, IOrderedQueryable<T>> orderBuilder = null,
            Func<IQueryable<T>, IIncludableQueryable<T, object>> includeBuilder = null,
            CancellationToken cancellationToken = default
        );
        #endregion

        //
        #region Exists ...
        /// <summary>
        /// Check an Entity exists or not ...
        /// </summary>
        /// <param name="id"></param>
        /// <param name="ignoreSoftDeleteds"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        Task<bool> IsExistsAsync(
            TKey id,
            bool ignoreSoftDeleteds = true,
            CancellationToken cancellationToken = default
        );
        #endregion

        //
        #region Unit Of Work ...
        /// <summary>
        /// Save all unsaved Transactions on DbContext ...
        /// used fo Unit Of Works Design Pattern ...
        /// </summary>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        Task<int> SaveChangesAsync(
            CancellationToken cancellationToken = default
        );
        #endregion

        //
        #region Key ...
        /// <summary>
        /// Retrieve Key of Entity ...
        /// </summary>
        /// <param name="item"></param>
        /// <returns></returns>
        TKey GetKey(T item);

        /// <summary>
        /// Set Key of Entity ...
        /// </summary>
        /// <param name="item"></param>
        /// <param name="id"></param>
        void SetKey(
            ref T item,
            TKey id
        );

        /// <summary>
        /// Handle Checking Key ...
        /// </summary>
        /// <param name="item"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        Task<T> HandleKeyAsync(
            T item,
            CancellationToken cancellationToken = default
        );
        #endregion

        //
        #region Detach ...
        /// <summary>
        /// Detach an Entity ...
        /// </summary>
        /// <param name="item"></param>
        void Detach(T item);

        /// <summary>
        /// Detach an Enumerable of Entities ...
        /// </summary>
        /// <param name="items"></param>
        void Detach(IEnumerable<T> items);

        /// <summary>
        /// Detach a Query Result of Entity ...
        /// </summary>
        /// <param name="query"></param>
        void Detach(XQueryResult<T> query);
        #endregion
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xDataService\Interfaces\IXBaseRepositoryController.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore.Query;
using xModels.Base;
using xModels.Dtos;

namespace xDataService.Interfaces
{
    /// <summary>
    /// an Interface for Base Repository Actions Providing Using Controllers ...
    /// </summary>
    /// <typeparam name="TEntity"></typeparam>
    /// <typeparam name="TDto"></typeparam>
    /// <typeparam name="TKey"></typeparam>
    public interface IXBaseRepositoryController<TEntity, TKey>
    where TEntity : XBaseEntity<TKey>
    {
        //
        IXBaseRepository<TEntity, TKey> Repository { get; }
        Func<IQueryable<TEntity>, IOrderedQueryable<TEntity>> DefaultOrderBuilder { get; }
        Func<IQueryable<TEntity>, IIncludableQueryable<TEntity, object>> DefaultIncludeBuilder { get; }

        //
        #region Add ...
        Task<ActionResult<TEntity>> Add(
            [FromBody] TEntity item,
            CancellationToken cancellationToken = default
        );

        Task<ActionResult<TEntity>> AddOrUpdate(
            [FromBody] TEntity item,
            CancellationToken cancellationToken = default
        );

        Task<ActionResult> AddMany(
            [FromBody] XBaseRangeRequest<TEntity> request,
            CancellationToken cancellationToken = default
        );
        #endregion

        //
        #region Retrieve ...
        Task<ActionResult<TEntity>> Get(
            [FromRoute] TKey id,
            [FromQuery] bool ignoreSoftDeleteds = true,
            [FromQuery] bool useDefaultIncludes = false,
            CancellationToken cancellationToken = default
        );

        Task<ActionResult<IEnumerable<TEntity>>> GetAll(
            [FromQuery] bool ignoreSoftDeleteds = true,
            [FromQuery] bool useDefaultOrders = false,
            [FromQuery] bool useDefaultIncludes = false,
            CancellationToken cancellationToken = default
        );

        Task<ActionResult<TEntity>> FindOne(
            [FromRoute] string query,
            [FromQuery] bool ignoreSoftDeleteds = true,
            [FromQuery] bool useDefaultIncludes = false,
            CancellationToken cancellationToken = default
        );

        Task<ActionResult<IEnumerable<TEntity>>> FindMany(
            [FromRoute] string query,
            [FromQuery] bool ignoreSoftDeleteds = true,
            [FromQuery] bool useDefaultOrders = false,
            [FromQuery] bool useDefaultIncludes = false,
            CancellationToken cancellationToken = default
        );

        Task<ActionResult<XQueryResult<TEntity>>> Query(
            [FromQuery] XQuery query,
            [FromQuery] bool ignoreSoftDeleteds = true,
            [FromQuery] bool useDefaultOrders = false,
            [FromQuery] bool useDefaultIncludes = false,
            CancellationToken cancellationToken = default
        );
        #endregion

        //
        #region Update ...
        Task<ActionResult<TEntity>> Update(
            [FromRoute] TKey id,
            [FromBody] TEntity item,
            CancellationToken cancellationToken = default
        );

        Task<ActionResult<bool>> UpdateMany(
            [FromBody] XBaseRangeRequest<TEntity> request,
            CancellationToken cancellationToken = default
        );
        #endregion

        //
        #region Exists ...
        Task<ActionResult<bool>> IsExists(
            [FromRoute] TKey id,
            [FromQuery] bool ignoreSoftDeleteds = true,
            CancellationToken cancellationToken = default
        );
        #endregion

        //
        #region Remove ...
        Task<ActionResult<TEntity>> Remove(
            [FromRoute] TKey id,
            [FromQuery] bool softDelete = true,
            CancellationToken cancellationToken = default
        );

        Task<ActionResult> RemoveMany(
            [FromBody] XBaseRangeRequest<TEntity> request,
            [FromQuery] bool softDelete = true,
            CancellationToken cancellationToken = default
        );
        #endregion
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xDataService\Interfaces\IXBaseRepositoryEvents.cs

using System;
using System.Collections.Generic;
using xDataService.Models;

namespace xDataService.Interfaces {
    public interface IXBaseRepositoryEvents<T> {
        //
        void AddEvent (XBaseEventModel<T> model);
        void UpdateEvent (XBaseEventModel<T> model);
        void RemoveEvent (XBaseEventModel<T> model);

        //
        void AddManyEvent (XBaseEventModel<IEnumerable<T>> model);
        void UpdateManyEvent (XBaseEventModel<IEnumerable<T>> model);
        void RemoveManyEvent (XBaseEventModel<IEnumerable<T>> model);

        //
        IObservable<XBaseEventModel<T>> OnAddObservable { get; }
        IObservable<XBaseEventModel<T>> OnUpdateObservable { get; }
        IObservable<XBaseEventModel<T>> OnRemoveObservable { get; }

        //
        IObservable<XBaseEventModel<IEnumerable<T>>> OnAddManyObservable { get; }
        IObservable<XBaseEventModel<IEnumerable<T>>> OnUpdateManyObservable { get; }
        IObservable<XBaseEventModel<IEnumerable<T>>> OnRemoveManyObservable { get; }
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xDataService\Interfaces\IXBaseRepositoryService.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Runtime.CompilerServices;
using System.Threading;
using System.Threading.Tasks;
using AutoMapper;
using Microsoft.EntityFrameworkCore.Query;
using xModels.Base;
using xModels.Dtos;

namespace xDataService.Interfaces
{
    /// <summary>
    /// an Interface for Manipulating Data Using Services based on Dto Mapping ...
    /// </summary>
    /// <typeparam name="TEntity"></typeparam>
    /// <typeparam name="TDto"></typeparam>
    /// <typeparam name="TKey"></typeparam>
    public interface IXBaseRepositoryService<TEntity, TDto, TKey> : IDisposable
    where TEntity : XBaseEntity<TKey>
    where TDto : XBaseEntityDto<TKey>
    {
        //
        #region Properties ...
        /// <summary>
        /// Mapper Instance ...
        /// </summary>
        IMapper Mapper { get; }

        /// <summary>
        /// Repository Implementation for Data Manipulations ...
        /// </summary>
        IXBaseRepository<TEntity, TKey> Repository { get; }

        /// <summary>
        /// Mapping Profile Configuration ...
        /// 
        /// this Configuration used for Mapping TEntity to Dto and reverse ...
        /// default mapping prepared on Constructing time, other custom maps
        /// must handled manually if required ...
        /// </summary>
        MapperConfiguration MapperConfiguration { get; }
        #endregion

        //
        #region Actions ...
        //
        #region Add ...
        /// <summary>
        /// add a new Dto ...
        /// </summary>
        /// <param name="item"></param>
        /// <param name="saveChanges"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        Task<TDto> AddAsync(
            TDto item,
            bool saveChanges = true,
            CancellationToken cancellationToken = default
        );

        /// <summary>
        /// add or update a Dto (add if not exists/update if exists) ...
        /// </summary>
        /// <param name="item"></param>
        /// <param name="saveChanges"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        Task<TDto> AddOrUpdateAsync(
            TDto item,
            bool saveChanges = true,
            CancellationToken cancellationToken = default
        );

        /// <summary>
        /// add a range of new Dtos ...
        /// </summary>
        /// <param name="items"></param>
        /// <param name="saveChanges"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        Task AddRangeAsync(
            IEnumerable<TDto> items,
            bool saveChanges = true,
            CancellationToken cancellationToken = default
        );
        #endregion

        //
        #region Update ...
        /// <summary>
        /// Update an Dto values ...
        /// </summary>
        /// <param name="id"></param>
        /// <param name="item"></param>
        /// <param name="saveChanges"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        Task<TDto> UpdateAsync(
            TKey id,
            TDto item,
            bool saveChanges = true,
            CancellationToken cancellationToken = default
        );

        /// <summary>
        /// Update a range of Dtos ...
        /// </summary>
        /// <param name="items"></param>
        /// <param name="saveChanges"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        Task<bool> UpdateRangeAsync(
            IEnumerable<TDto> items,
            bool saveChanges = true,
            CancellationToken cancellationToken = default
        );
        #endregion

        //
        #region Remove ...
        /// <summary>
        /// remove an Dto by it's Id ...
        /// </summary>
        /// <param name="id"></param>
        /// <param name="softDelete"></param>
        /// <param name="saveChanges"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        Task<TDto> RemoveAsync(
            TKey id,
            bool softDelete = true,
            bool saveChanges = true,
            CancellationToken cancellationToken = default
        );

        /// <summary>
        /// remove an Dto ...
        /// </summary>
        /// <param name="item"></param>
        /// <param name="softDelete"></param>
        /// <param name="saveChanges"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        Task<TDto> RemoveAsync(
            TDto item,
            bool softDelete = true,
            bool saveChanges = true,
            CancellationToken cancellationToken = default
        );

        /// <summary>
        /// remove a range of exists Dtos ...
        /// </summary>
        /// <param name="items"></param>
        /// <param name="softDelete"></param>
        /// <param name="saveChanges"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        Task RemoveRangeAsync(
            IEnumerable<TDto> items,
            bool softDelete = true,
            bool saveChanges = true,
            CancellationToken cancellationToken = default
        );
        #endregion

        //
        #region Count ...
        /// <summary>
        /// count all exists Dtos ...
        /// </summary>
        /// <param name="ignoreSoftDeleteds"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        Task<int> CountAsync(
            bool ignoreSoftDeleteds = true,
            CancellationToken cancellationToken = default
        );

        /// <summary>
        /// count all exists Entities Pages by providing page size ...
        /// </summary>
        /// <param name="pageSize"></param>
        /// <param name="totalItems"></param>
        /// <param name="ignoreSoftDeleteds"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        Task<int> PagesCountAsync(
            int pageSize,
            int? totalItems = null,
            bool ignoreSoftDeleteds = true,
            CancellationToken cancellationToken = default
        );
        #endregion

        //
        #region Retrieve ...
        /// <summary>
        /// retrieve an Dto by it's Id ...
        /// </summary>
        /// <param name="id"></param>
        /// <param name="ignoreSoftDeleteds"></param>
        /// <param name="includeBuilder"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        Task<TDto> GetAsync(
            TKey id,
            bool ignoreSoftDeleteds = true,
            Func<IQueryable<TEntity>, IIncludableQueryable<TEntity, object>> includeBuilder = null,
            CancellationToken cancellationToken = default
        );

        /// <summary>
        /// retrieve all exists Dtos ...
        /// </summary>
        /// <param name="ignoreSoftDeleteds"></param>
        /// <param name="orderBuilder"></param>
        /// <param name="includeBuilder"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        Task<IEnumerable<TDto>> GetAllAsync(
            bool ignoreSoftDeleteds = true,
            Func<IQueryable<TEntity>, IOrderedQueryable<TEntity>> orderBuilder = null,
            Func<IQueryable<TEntity>, IIncludableQueryable<TEntity, object>> includeBuilder = null,
            CancellationToken cancellationToken = default
        );

        /// <summary>
        /// retrieve all exists Dtos
        /// as Async Enumerable ...
        /// </summary>
        /// <param name="ignoreSoftDeleteds"></param>
        /// <param name="orderBuilder"></param>
        /// <param name="includeBuilder"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        IAsyncEnumerable<TDto> GetAllAsAsyncEnumerable(
            bool ignoreSoftDeleteds = true,
            Func<IQueryable<TEntity>, IOrderedQueryable<TEntity>> orderBuilder = null,
            Func<IQueryable<TEntity>, IIncludableQueryable<TEntity, object>> includeBuilder = null,
            CancellationToken cancellationToken = default
        );

        /// <summary>
        /// find an Dto by providing a Conditional Expression ...
        /// </summary>
        /// <param name="predicate"></param>
        /// <param name="ignoreSoftDeleteds"></param>
        /// <param name="includeBuilder"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        Task<TDto> FindOneAsync(
            Expression<Func<TEntity, bool>> predicate,
            bool ignoreSoftDeleteds = true,
            Func<IQueryable<TEntity>, IIncludableQueryable<TEntity, object>> includeBuilder = null,
            CancellationToken cancellationToken = default
        );

        /// <summary>
        /// find a collection of Dtos by proving a Conditional Expression ...
        /// </summary>
        /// <param name="predicate"></param>
        /// <param name="ignoreSoftDeleteds"></param>
        /// <param name="orderBuilder"></param>
        /// <param name="includeBuilder"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        Task<IEnumerable<TDto>> FindManyAsync(
            Expression<Func<TEntity, bool>> predicate,
            bool ignoreSoftDeleteds = true,
            Func<IQueryable<TEntity>, IOrderedQueryable<TEntity>> orderBuilder = null,
            Func<IQueryable<TEntity>, IIncludableQueryable<TEntity, object>> includeBuilder = null,
            CancellationToken cancellationToken = default
        );

        /// <summary>
        /// retrieve Dtos based on XQuery Pagination structure ...
        /// </summary>
        /// <param name="query"></param>
        /// <param name="ignoreSoftDeleteds"></param>
        /// <param name="predicate"></param>
        /// <param name="orderBuilder"></param>
        /// <param name="includeBuilder"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        Task<XQueryResult<TDto>> QueryAsync(
            XQuery query,
            bool ignoreSoftDeleteds = true,
            Expression<Func<TEntity, bool>> predicate = null,
            Func<IQueryable<TEntity>, IOrderedQueryable<TEntity>> orderBuilder = null,
            Func<IQueryable<TEntity>, IIncludableQueryable<TEntity, object>> includeBuilder = null,
            CancellationToken cancellationToken = default
        );
        #endregion

        //
        #region Exists ...
        /// <summary>
        /// Check a Dto exists or not ...
        /// </summary>
        /// <param name="id"></param>
        /// <param name="ignoreSoftDeleteds"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        Task<bool> IsExistsAsync(
            TKey id,
            bool ignoreSoftDeleteds = true,
            CancellationToken cancellationToken = default
        );
        #endregion
        #endregion
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xDataService\Interfaces\IXBaseServiceController.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore.Query;
using xModels.Base;
using xModels.Dtos;

namespace xDataService.Interfaces
{
    /// <summary>
    /// an Interface for Base RepositoryService Actions Providing Using Controllers ...
    /// </summary>
    /// <typeparam name="TEntity"></typeparam>
    /// <typeparam name="TDto"></typeparam>
    /// <typeparam name="TKey"></typeparam>
    public interface IXBaseServiceController<TEntity, TDto, TKey>
        where TEntity : XBaseEntity<TKey>
        where TDto : XBaseEntityDto<TKey>
    {
        //
        IXBaseRepositoryService<TEntity, TDto, TKey> RepositoryService { get; }
        Func<IQueryable<TEntity>, IOrderedQueryable<TEntity>> DefaultOrderBuilder { get; }
        Func<IQueryable<TEntity>, IIncludableQueryable<TEntity, object>> DefaultIncludeBuilder { get; }

        //
        #region Add ...
        Task<ActionResult<TDto>> Add(
            TDto item,
            CancellationToken cancellationToken = default
        );

        Task<ActionResult<TDto>> AddOrUpdate(
            TDto item,
            CancellationToken cancellationToken = default
        );

        Task<ActionResult> AddMany(
            XBaseRangeRequest<TDto> request,
            CancellationToken cancellationToken = default
        );
        #endregion

        //
        #region Retrieve ...
        Task<ActionResult<TDto>> Get(
            [FromRoute] TKey id,
            [FromQuery] bool ignoreSoftDeleteds = true,
            [FromQuery] bool useDefaultIncludes = false,
            CancellationToken cancellationToken = default
        );

        Task<ActionResult<IEnumerable<TDto>>> GetAll(
            [FromQuery] bool ignoreSoftDeleteds = true,
            [FromQuery] bool useDefaultOrders = false,
            [FromQuery] bool useDefaultIncludes = false,
            CancellationToken cancellationToken = default
        );

        Task<ActionResult<TDto>> FindOne(
            [FromRoute] string query,
            [FromQuery] bool ignoreSoftDeleteds = true,
            [FromQuery] bool useDefaultIncludes = false,
            CancellationToken cancellationToken = default
        );

        Task<ActionResult<IEnumerable<TDto>>> FindMany(
            [FromRoute] string query,
            [FromQuery] bool ignoreSoftDeleteds = true,
            [FromQuery] bool useDefaultOrders = false,
            [FromQuery] bool useDefaultIncludes = false,
            CancellationToken cancellationToken = default
        );

        Task<ActionResult<XQueryResult<TDto>>> Query(
            [FromQuery] XQuery query,
            [FromQuery] bool ignoreSoftDeleteds = true,
            [FromQuery] bool useDefaultOrders = false,
            [FromQuery] bool useDefaultIncludes = false,
            CancellationToken cancellationToken = default
        );
        #endregion

        //
        #region Update ...
        Task<ActionResult<TDto>> Update(
            [FromRoute] TKey id,
            [FromBody] TDto item,
            CancellationToken cancellationToken = default
        );

        Task<ActionResult<bool>> UpdateMany(
            [FromBody] XBaseRangeRequest<TDto> request,
            CancellationToken cancellationToken = default
        );
        #endregion

        //
        #region Exists ...
        Task<ActionResult<bool>> IsExists(
            [FromRoute] TKey id,
            [FromQuery] bool ignoreSoftDeletedss = true,
            CancellationToken cancellationToken = default
        );
        #endregion

        //
        #region Remove ...
        Task<ActionResult<TDto>> Remove(
            [FromRoute] TKey id,
            [FromQuery] bool softDelete = true,
            CancellationToken cancellationToken = default
        );

        Task<ActionResult> RemoveMany(
            [FromBody] XBaseRangeRequest<TDto> request,
            [FromQuery] bool softDelete = true,
            CancellationToken cancellationToken = default
        );
        #endregion
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xDataService\Interfaces\IXDatabaseDescriptor.cs

using System;
using System.Collections.Generic;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using MongoDB.Bson.Serialization.Conventions;
using xDataService.Configuration;
using xDataService.Constants;
using xDataService.Db;
using xDataService.Models;

namespace xDataService.Interfaces
{
    /// <summary>
    /// Data Base Descriptor ...
    /// </summary>
    public interface IXDatabaseDescriptor
    {
        //
        #region Props ...
        /// <summary>
        /// Database Name ...
        /// </summary>
        /// <value></value>
        string Name { get; set; }

        /// <summary>
        /// Database Provider ...
        /// </summary>
        /// <value></value>
        XDbProviders Provider { get; set; }

        /// <summary>
        /// Db Context Type ...
        /// </summary>
        /// <value></value>
        Type Context { get; set; }

        /// <summary>
        /// Database Connecion String ...
        /// </summary>
        /// <value></value>
        string ConnectionString { get; set; }

        /// <summary>
        /// Data Service Configuration ...
        /// </summary>
        /// <value></value>
        XDataBaseConfiguration Configuration { get; set; }

        /// <summary>
        /// Repositories Descriptions ...
        /// </summary>
        /// <value></value>
        IList<XRepositoryDescriptor> Repositories { get; set; }

        /// <summary>
        /// Mongo Convention Packs ...
        /// </summary>
        ConventionPack ConventionPacks { get; set; }

        /// <summary>
        /// DbContext Options Builder ...
        /// </summary>
        /// <value></value>
        Action<dynamic> OptionsBuilder { get; set; }
        #endregion

        //
        #region Configure ...
        /// <summary>
        /// Configure Database Descriptor using Registered Services ...
        /// </summary>
        /// <param name="services"></param>
        void Configure(
            IServiceCollection services
        );

        /// <summary>
        /// Configure Database Descriptor using IConfiguration ...
        /// </summary>
        /// <param name="configuration"></param>
        void Configure(
            IConfiguration configuration
        );

        /// <summary>
        /// Configure Database Descriptor using Database Configuration ...
        /// </summary>
        /// <param name="configuration"></param>
        void Configure(
            XDataBaseConfiguration configuration
        );

        /// <summary>
        /// Configure Database Descriptor using Provider and Connection String ...
        /// </summary>
        /// <param name="provider"></param>
        /// <param name="connectionString"></param>
        void Configure(
            XDbProviders provider,
            string connectionString
        );
        #endregion        
    }

    /// <summary>
    /// Data Base Descriptor ...
    /// </summary>
    /// <typeparam name="TContext"></typeparam>
    public interface IXDatabaseDescriptor<TContext> : IXDatabaseDescriptor
    where TContext : XDbContext
    { }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xDataService\Interfaces\IXEntityRegisterar.cs

using System;
using System.Collections.Generic;
using Microsoft.EntityFrameworkCore;
using xModels.Base;

namespace xDataService.Interfaces
{
    /// <summary>
    /// an Interface to Intruduce Entities for Dynamic Registration ...
    /// </summary>
    public interface IXEntityRegisterar
    {
        /// <summary>
        /// Database Name ...
        /// </summary>
        string Name { get; }

        /// <summary>
        /// Returns all entity types this plugin wants registered in the DbContext
        /// </summary>        
        IEnumerable<Type> GetEntityTypes();

        /// <summary>
        /// Optional: Apply additional per-entity configuration
        /// </summary>
        void ConfigureEntities(ModelBuilder modelBuilder);

        /// <summary>
        /// Add XDataService Based Entity to List ...
        /// </summary>
        /// <typeparam name="TEntity"></typeparam>
        /// <typeparam name="TKey"></typeparam>
        void AddEntity<TEntity, TKey>()
        where TEntity : XBaseEntity<TKey>;
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xDataService\Interfaces\IXKeyGenerator.cs

using System.Threading;
using System.Threading.Tasks;
using xModels.Base;

namespace xDataService.Interfaces
{
    /// <summary>
    /// Typed Base Key Generator ...
    /// </summary>
    /// <typeparam name="TEntity"></typeparam>
    /// <typeparam name="TKey"></typeparam>
    public interface IXKeyGenerator<TEntity, TKey>
    where TEntity : XBaseEntity<TKey>
    {
        bool IsEmpty(TKey id);
        Task<TKey> GenerateKey(
            IXBaseRepository<TEntity, TKey> repository,
            CancellationToken cancellationToken = default
        );
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xDataService\Interfaces\IXSequentialGuid.cs

using System;

namespace xDataService.Interfaces {
    /// <summary>
    /// this service provide Sequential GUID mechanism for Entity Ids ...
    /// </summary>
    public interface IXSequentialGuid {
        Guid GetCurrentGuid ();
        Guid Next ();
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xDataService\Interfaces\IXUnitOfWorks.cs

using System;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.EntityFrameworkCore;
using xDataService.Db;
using xModels.Base;

namespace xDataService.Interfaces {
    /// <summary>
    /// Provide Unit Of Works Design Pattern for Db Transactions ...
    /// Only Used on EFCore ...
    /// </summary>
    /// <typeparam name="TDbContext"></typeparam>
    public interface IXUnitOfWorks<TDbContext> : IDisposable
    where TDbContext : XDbContext {
        TDbContext DbContext { get; }
        DbSet<T> GetDbSet<T, TKey> () where T : XBaseEntity<TKey>;
        int SaveChanges ();
        Task<int> SaveChangesAsync (
            CancellationToken cancellationToken = default
        );
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xDataService\Models\XBaseEventModel.cs

namespace xDataService.Models {
    /// <summary>
    /// Pass Data on Repository Events ...
    /// </summary>
    /// <typeparam name="T"></typeparam>
    public class XBaseEventModel<T> {
        public T Model { get; set; }

        public XBaseEventModel (T model) {
            Model = model;
        }
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xDataService\Models\XDatabaseDescriptor.cs

using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using MongoDB.Bson.Serialization.Conventions;
using xCommons.Extensions;
using xDataService.Configuration;
using xDataService.Constants;
using xDataService.Db;
using xDataService.DI;
using xDataService.Interfaces;

namespace xDataService.Models
{
    /// <summary>
    /// Data Base Descriptor ...
    /// </summary>
    public abstract class XDatabaseDescriptor : IXDatabaseDescriptor
    {
        //
        #region Props ...
        /// <summary>
        /// Database Name ...
        /// </summary>
        /// <value></value>
        public virtual string Name { get; set; }

        /// <summary>
        /// Database Provider ...
        /// </summary>
        /// <value></value>
        public virtual XDbProviders Provider { get; set; }

        /// <summary>
        /// Db Context...
        /// </summary>
        /// <value></value>
        public virtual Type Context { get; set; } = null;

        /// <summary>
        /// Database Connecion String ...
        /// </summary>
        /// <value></value>
        public virtual string ConnectionString { get; set; }

        /// <summary>
        /// Data Service Configuration ...
        /// </summary>
        /// <value></value>
        public virtual XDataBaseConfiguration Configuration { get; set; }

        /// <summary>
        /// Repositories Descriptions ...
        /// </summary>
        /// <value></value>
        public virtual IList<XRepositoryDescriptor> Repositories { get; set; } = null;

        /// <summary>
        /// Mongo Convention Packs ...
        /// </summary>
        public ConventionPack ConventionPacks { get; set; } = null;

        /// <summary>
        /// DbContext Options Builder ...
        /// </summary>
        /// <value></value>
        public Action<dynamic> OptionsBuilder { get; set; } = null;
        #endregion

        //
        #region Constructor ...
        /// <summary>
        /// Constructor of Descriptor ...
        /// </summary>
        /// <param name="name"></param>
        /// <param name="configuration"></param>
        /// <param name="repositories"></param>
        public XDatabaseDescriptor(
            string name,
            IList<XRepositoryDescriptor> repositories = null
        )
        {
            //
            Name = name;
            Repositories = repositories;
        }
        #endregion

        //
        #region Configure ...
        /// <summary>
        /// Configure Database Descriptor using Registered Services ...
        /// </summary>
        /// <param name="services"></param>
        public void Configure(
            IServiceCollection services
        )
        {
            //
            bool isValid = !Name.IsNullOrEmpty();
            if (!isValid)
            {
                return;
            }

            //
            var xDataServiceConfiguration = services.GetRegisteredService<XDataServiceConfiguration>();
            isValid =
                !xDataServiceConfiguration.IsNullOrDefault() &&
                xDataServiceConfiguration.Databases.HasChild() &&
                xDataServiceConfiguration.Databases.Keys.Any(k => k == Name);
            if (!isValid)
            {
                return;
            }

            //
            var database = xDataServiceConfiguration.Databases[Name];
            isValid = !database.IsNullOrDefault();
            if (!isValid)
            {
                return;
            }

            //
            Configure(database);
        }

        /// <summary>
        /// Configure Database Descriptor using IConfiguration ...
        /// </summary>
        /// <param name="configuration"></param>
        public void Configure(
            IConfiguration configuration
        )
        {
            //
            bool isValid = !Name.IsNullOrEmpty();
            if (!isValid)
            {
                return;
            }

            //
            var xDataServiceConfiguration = configuration.GetXDataServiceConfiguration();
            isValid =
                !xDataServiceConfiguration.IsNullOrDefault() &&
                xDataServiceConfiguration.Databases.HasChild() &&
                xDataServiceConfiguration.Databases.Keys.Any(k => k == Name);
            if (!isValid)
            {
                return;
            }

            //
            var database = xDataServiceConfiguration.Databases[Name];
            isValid = !database.IsNullOrDefault();
            if (!isValid)
            {
                return;
            }

            //
            Configure(database);
        }

        /// <summary>
        /// Configure Database Descriptor using Database Configuration ...
        /// </summary>
        /// <param name="configuration"></param>
        public void Configure(
            XDataBaseConfiguration configuration
        )
        {
            //
            Configuration = configuration;
            Provider = configuration.Provider;
            ConnectionString = configuration.ConnectionString;
        }

        /// <summary>
        /// Configure Database Descriptor using Provider and Connection String ...
        /// </summary>
        /// <param name="provider"></param>
        /// <param name="connectionString"></param>
        public void Configure(
            XDbProviders provider,
            string connectionString
        )
        {
            //
            Provider = provider;
            ConnectionString = connectionString;
            Configuration = new XDataBaseConfiguration
            {
                Provider = provider,
                ConnectionString = connectionString
            };
        }
        #endregion
    }

    /// <summary>
    /// Data Base Descriptor ...
    /// </summary>
    /// <typeparam name="TContext"></typeparam>
    public abstract class XDatabaseDescriptor<TContext> : XDatabaseDescriptor, IXDatabaseDescriptor<TContext>
    where TContext : XDbContext
    {
        /// <summary>
        /// Constructor of Descriptor ...
        /// </summary>
        /// <param name="name"></param>
        /// <param name="configuration"></param>
        /// <param name="context"></param>
        /// <param name="repositories"></param>
        public XDatabaseDescriptor(
            string name,
            IList<XRepositoryDescriptor> repositories = null
        ) : base(
            name: name,
            repositories: repositories
        )
        {
            Context = typeof(TContext);
        }
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xDataService\Models\XGraphQueryResult.cs

using GraphQL.Types;
using xModels.Dtos;

namespace xDataService.Models {
    public class XGraphQueryResult<TEntity, TGraph> : ObjectGraphType<XQueryResult<TEntity>>
        where TGraph : IGraphType {
            public XGraphQueryResult () {
                //
                Name = $"{typeof(TGraph).Name}QueryResult";

                //
                Field<ListGraphType<TGraph>> (nameof (XQueryResult<TEntity>.Items));
                Field (x => x.Page);
                Field (x => x.PageSize);
                Field (x => x.TotalPages);
                Field (x => x.TotalFilteredItems);
                Field (x => x.TotalItems);
            }
        }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xDataService\Models\XGraphQueryType.cs

using GraphQL.Types;
using xModels.Dtos;

namespace xDataService.Models {
    public class XGraphQueryType : InputObjectGraphType<XQuery> {
        public XGraphQueryType () {
            //
            Name = "query";

            //
            Field (x => x.Filter);
            Field (x => x.ContainsDetail);
            Field (x => x.SortBy);
            Field (x => x.IsAscending);
            Field (x => x.Page);
            Field (x => x.PageSize);
        }
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xDataService\Models\XReference.cs

namespace xDataService.Models
{
    public class XReference<T>
    {
        public int Index { get; set; }
        public T ReferencedTo { get; set; }
        public string ProvidedFor { get; set; }
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xDataService\Models\XRepositoryDescriptor.cs

using System;
using GraphQL.Types;
using xDataService.Db;
using xDataService.GraphQL;
using xDataService.Interfaces;
using xDataService.Providers;
using xModels.Base;

namespace xDataService.Models
{
    /// <summary>
    /// a Global non Generic Repository Descriptor ...
    /// </summary>
    public class XRepositoryDescriptor
    {
        /// <summary>
        /// Entity Key Type ...
        /// </summary>
        /// <value></value>
        public Type Key { get; set; } = null;

        /// <summary>
        /// Entity Type ...
        /// </summary>
        /// <value></value>
        public Type Entity { get; set; } = null;

        /// <summary>
        /// Context Type ...
        /// </summary>
        /// <value></value>
        public Type Context { get; set; } = null;

        /// <summary>
        /// Graph Type Key ...
        /// </summary>
        /// <value></value>
        public Type GraphTypeKey { get; set; } = null;

        /// <summary>
        /// Graph Type ...
        /// </summary>
        /// <value></value>
        public Type GraphType { get; set; } = null;

        /// <summary>
        /// Entity Type GraphQL Schema ...
        /// </summary>
        /// <value></value>
        public Type GraphSchema { get; set; } = null;

        /// <summary>
        /// Entity GraphQL Type Helper ...
        /// </summary>
        /// <value></value>
        public Type GraphTypeHelperService { get; set; } = null;

        /// <summary>
        /// Entity GraphQL Type Helper ...
        /// </summary>
        /// <value></value>
        public Type GraphTypeHelperImplementation { get; set; } = null;

        /// <summary>
        /// Entity GrapQL Query ...
        /// </summary>
        /// <value></value>
        public Type GraphQuery { get; set; } = null;

        /// <summary>
        /// Repository Event Provider ...
        /// </summary>
        /// <value></value>
        public Type EventsService { get; set; } = null;

        /// <summary>
        /// Repository Event Provider ...
        /// </summary>
        /// <value></value>
        public Type EventsImplementation { get; set; } = null;

        /// <summary>
        /// Repository Key Generator for Entity ...
        /// </summary>
        /// <value></value>
        public Type KeyGeneratorService { get; set; } = null;

        /// <summary>
        /// Repository Key Generator for Entity ...
        /// </summary>
        /// <value></value>
        public Type KeyGeneratorImplementation { get; set; } = null;

        /// <summary>
        /// Repository Data Access Design Pattern ...
        /// </summary>
        /// <value></value>
        public Type RepositoryService { get; set; } = null;

        /// <summary>
        /// Repository Data Access Design Pattern ...
        /// </summary>
        /// <value></value>
        public Type RepositoryImplementation { get; set; } = null;

        /// <summary>
        /// Database Data Seeder ...
        /// </summary>
        public Type SeederService { get; set; } = null;

        /// <summary>
        /// Database Data Seeder ...
        /// </summary>
        public Type SeederImplementation { get; set; } = null;
    }

    /// <summary>
    /// a Repository Descriptor ...
    /// </summary>
    /// <typeparam name="TEntity"></typeparam>
    /// <typeparam name="TKey"></typeparam>
    public class XRepositoryDescriptor<TEntity, TKey> : XRepositoryDescriptor
    where TEntity : XBaseEntity<TKey>
    {
        public XRepositoryDescriptor() : base()
        {
            //
            Key = typeof(TKey);
            Entity = typeof(TEntity);
        }
    }

    /// <summary>
    /// a Repository Descriptor ...
    /// </summary>
    public class XRepositoryDescriptor<
        TEntity,
        TKey,
        TKeyGeneratorService,
        TKeyGeneratorImplementation
    > : XRepositoryDescriptor<TEntity, TKey>
    where TEntity : XBaseEntity<TKey>
    where TKeyGeneratorService : IXKeyGenerator<TEntity, TKey>
    where TKeyGeneratorImplementation : XKeyGenerator<TEntity, TKey>
    {
        public XRepositoryDescriptor() : base()
        {
            //
            KeyGeneratorService = typeof(TKeyGeneratorService);
            KeyGeneratorImplementation = typeof(TKeyGeneratorImplementation);
        }
    }

    /// <summary>
    /// a Repository Descriptor ...
    /// </summary>
    public class XRepositoryDescriptor<
        TEntity,
        TKey,
        TKeyGeneratorService,
        TKeyGeneratorImplementation,
        TEventsService,
        TEventsImplementation
    > : XRepositoryDescriptor<
        TEntity,
        TKey,
        TKeyGeneratorService,
        TKeyGeneratorImplementation
    >
    where TEntity : XBaseEntity<TKey>
    where TEventsService : IXBaseRepositoryEvents<TEntity>
    where TKeyGeneratorService : IXKeyGenerator<TEntity, TKey>
    where TEventsImplementation : XBaseRepositoryEvents<TEntity>
    where TKeyGeneratorImplementation : XKeyGenerator<TEntity, TKey>
    {
        public XRepositoryDescriptor() : base()
        {
            //
            EventsService = typeof(TEventsService);
            EventsImplementation = typeof(TEventsImplementation);
        }
    }

    /// <summary>
    /// a Repository Descriptor ...
    /// </summary>
    public class XRepositoryDescriptor<
        TEntity,
        TKey,
        TKeyGeneratorService,
        TKeyGeneratorImplementation,
        TEventsService,
        TEventsImplementation,
        TGraph,
        TGraphKey,
        TGraphQuery,
        TGraphTypeHelperService,
        TGraphTypeHelperImplementation,
        TGraphSchema
    > : XRepositoryDescriptor<
        TEntity,
        TKey,
        TKeyGeneratorService,
        TKeyGeneratorImplementation,
        TEventsService,
        TEventsImplementation
    >
    where TGraphSchema : Schema
    where TGraphKey : IGraphType
    where TEntity : XBaseEntity<TKey>
    where TGraph : XBaseGraphObjectType<TEntity, TKey>
    where TEventsService : IXBaseRepositoryEvents<TEntity>
    where TKeyGeneratorService : IXKeyGenerator<TEntity, TKey>
    where TEventsImplementation : XBaseRepositoryEvents<TEntity>
    where TKeyGeneratorImplementation : XKeyGenerator<TEntity, TKey>
    where TGraphTypeHelperService : IXBaseGraphQLTypeHelper<TEntity, TKey>
    where TGraphQuery : XBaseGraphQLQuery<TEntity, TKey, TGraph, TGraphKey>
    where TGraphTypeHelperImplementation : XBaseGraphQLTypeHelper<TEntity, TKey>
    {
        public XRepositoryDescriptor() : base()
        {
            //
            GraphType = typeof(TGraph);
            GraphTypeKey = typeof(TGraphKey);
            GraphQuery = typeof(TGraphQuery);
            GraphSchema = typeof(TGraphSchema);
            GraphTypeHelperService = typeof(TGraphTypeHelperService);
            GraphTypeHelperImplementation = typeof(TGraphTypeHelperImplementation);
        }
    }

    /// <summary>
    /// a Repository Descriptor ...
    /// </summary>
    public class XInMemoryRepositoryDescriptor<
        TEntity,
        TKey,
        TKeyGeneratorService,
        TKeyGeneratorImplementation,
        TEventsService,
        TEventsImplementation,
        TGraph,
        TGraphKey,
        TGraphQuery,
        TGraphTypeHelperService,
        TGraphTypeHelperImplementation,
        TGraphSchema,
        TRepositoryService,
        TRepositoryImplementation
    > : XRepositoryDescriptor<
        TEntity,
        TKey,
        TKeyGeneratorService,
        TKeyGeneratorImplementation,
        TEventsService,
        TEventsImplementation,
        TGraph,
        TGraphKey,
        TGraphQuery,
        TGraphTypeHelperService,
        TGraphTypeHelperImplementation,
        TGraphSchema
    >
    where TGraphSchema : Schema
    where TGraphKey : IGraphType
    where TEntity : XBaseEntity<TKey>
    where TGraph : XBaseGraphObjectType<TEntity, TKey>
    where TEventsService : IXBaseRepositoryEvents<TEntity>
    where TKeyGeneratorService : IXKeyGenerator<TEntity, TKey>
    where TRepositoryService : IXBaseRepository<TEntity, TKey>
    where TEventsImplementation : XBaseRepositoryEvents<TEntity>
    where TKeyGeneratorImplementation : XKeyGenerator<TEntity, TKey>
    where TGraphTypeHelperService : IXBaseGraphQLTypeHelper<TEntity, TKey>
    where TRepositoryImplementation : XBaseInMemoryRepository<TEntity, TKey>
    where TGraphQuery : XBaseGraphQLQuery<TEntity, TKey, TGraph, TGraphKey>
    where TGraphTypeHelperImplementation : XBaseGraphQLTypeHelper<TEntity, TKey>
    {
        public XInMemoryRepositoryDescriptor() : base()
        {
            //
            RepositoryService = typeof(TRepositoryService);
            RepositoryImplementation = typeof(TRepositoryImplementation);
        }
    }

    /// <summary>
    /// a Repository Descriptor ...
    /// </summary>
    public class XInMemoryRepositoryDescriptor<
        TEntity,
        TKey,
        TKeyGeneratorService,
        TKeyGeneratorImplementation,
        TEventsService,
        TEventsImplementation,
        TGraph,
        TGraphKey,
        TGraphQuery,
        TGraphTypeHelperService,
        TGraphTypeHelperImplementation,
        TGraphSchema,
        TRepositoryService,
        TRepositoryImplementation,
        TSeederService,
        TSeederImplementation
    > : XRepositoryDescriptor<
        TEntity,
        TKey,
        TKeyGeneratorService,
        TKeyGeneratorImplementation,
        TEventsService,
        TEventsImplementation,
        TGraph,
        TGraphKey,
        TGraphQuery,
        TGraphTypeHelperService,
        TGraphTypeHelperImplementation,
        TGraphSchema
    >
    where TGraphSchema : Schema
    where TGraphKey : IGraphType
    where TEntity : XBaseEntity<TKey>
    where TGraph : XBaseGraphObjectType<TEntity, TKey>
    where TSeederService : IXBaseDbSeeder<TEntity, TKey>
    where TEventsService : IXBaseRepositoryEvents<TEntity>
    where TKeyGeneratorService : IXKeyGenerator<TEntity, TKey>
    where TRepositoryService : IXBaseRepository<TEntity, TKey>
    where TSeederImplementation : XBaseDbSeeder<TEntity, TKey>
    where TEventsImplementation : XBaseRepositoryEvents<TEntity>
    where TKeyGeneratorImplementation : XKeyGenerator<TEntity, TKey>
    where TGraphTypeHelperService : IXBaseGraphQLTypeHelper<TEntity, TKey>
    where TRepositoryImplementation : XBaseInMemoryRepository<TEntity, TKey>
    where TGraphQuery : XBaseGraphQLQuery<TEntity, TKey, TGraph, TGraphKey>
    where TGraphTypeHelperImplementation : XBaseGraphQLTypeHelper<TEntity, TKey>
    {
        public XInMemoryRepositoryDescriptor() : base()
        {
            //
            SeederService = typeof(TSeederService);
            SeederImplementation = typeof(TSeederImplementation);

            //
            RepositoryService = typeof(TRepositoryService);
            RepositoryImplementation = typeof(TRepositoryImplementation);
        }
    }

    /// <summary>
    /// a Repository Descriptor ...
    /// </summary>
    public class XMongoRepositoryDescriptor<
        TEntity,
        TKey,
        TKeyGeneratorService,
        TKeyGeneratorImplementation,
        TEventsService,
        TEventsImplementation,
        TGraph,
        TGraphKey,
        TGraphQuery,
        TGraphTypeHelperService,
        TGraphTypeHelperImplementation,
        TGraphSchema,
        TRepositoryService,
        TRepositoryImplementation
    > : XRepositoryDescriptor<
        TEntity,
        TKey,
        TKeyGeneratorService,
        TKeyGeneratorImplementation,
        TEventsService,
        TEventsImplementation,
        TGraph,
        TGraphKey,
        TGraphQuery,
        TGraphTypeHelperService,
        TGraphTypeHelperImplementation,
        TGraphSchema
    >
    where TGraphSchema : Schema
    where TGraphKey : IGraphType
    where TEntity : XBaseEntity<TKey>
    where TGraph : XBaseGraphObjectType<TEntity, TKey>
    where TEventsService : IXBaseRepositoryEvents<TEntity>
    where TKeyGeneratorService : IXKeyGenerator<TEntity, TKey>
    where TRepositoryService : IXBaseRepository<TEntity, TKey>
    where TEventsImplementation : XBaseRepositoryEvents<TEntity>
    where TKeyGeneratorImplementation : XKeyGenerator<TEntity, TKey>
    where TRepositoryImplementation : XBaseMongoRepository<TEntity, TKey>
    where TGraphTypeHelperService : IXBaseGraphQLTypeHelper<TEntity, TKey>
    where TGraphQuery : XBaseGraphQLQuery<TEntity, TKey, TGraph, TGraphKey>
    where TGraphTypeHelperImplementation : XBaseGraphQLTypeHelper<TEntity, TKey>
    {
        public XMongoRepositoryDescriptor() : base()
        {
            //
            RepositoryService = typeof(TRepositoryService);
            RepositoryImplementation = typeof(TRepositoryImplementation);
        }
    }

    /// <summary>
    /// a Repository Descriptor ...
    /// </summary>
    public class XMongoRepositoryDescriptor<
        TEntity,
        TKey,
        TKeyGeneratorService,
        TKeyGeneratorImplementation,
        TEventsService,
        TEventsImplementation,
        TGraph,
        TGraphKey,
        TGraphQuery,
        TGraphTypeHelperService,
        TGraphTypeHelperImplementation,
        TGraphSchema,
        TRepositoryService,
        TRepositoryImplementation,
        TSeederService,
        TSeederImplementation
    > : XRepositoryDescriptor<
        TEntity,
        TKey,
        TKeyGeneratorService,
        TKeyGeneratorImplementation,
        TEventsService,
        TEventsImplementation,
        TGraph,
        TGraphKey,
        TGraphQuery,
        TGraphTypeHelperService,
        TGraphTypeHelperImplementation,
        TGraphSchema
    >
    where TGraphSchema : Schema
    where TGraphKey : IGraphType
    where TEntity : XBaseEntity<TKey>
    where TGraph : XBaseGraphObjectType<TEntity, TKey>
    where TSeederService : IXBaseDbSeeder<TEntity, TKey>
    where TEventsService : IXBaseRepositoryEvents<TEntity>
    where TSeederImplementation : XBaseDbSeeder<TEntity, TKey>
    where TKeyGeneratorService : IXKeyGenerator<TEntity, TKey>
    where TRepositoryService : IXBaseRepository<TEntity, TKey>
    where TEventsImplementation : XBaseRepositoryEvents<TEntity>
    where TKeyGeneratorImplementation : XKeyGenerator<TEntity, TKey>
    where TRepositoryImplementation : XBaseMongoRepository<TEntity, TKey>
    where TGraphTypeHelperService : IXBaseGraphQLTypeHelper<TEntity, TKey>
    where TGraphQuery : XBaseGraphQLQuery<TEntity, TKey, TGraph, TGraphKey>
    where TGraphTypeHelperImplementation : XBaseGraphQLTypeHelper<TEntity, TKey>
    {
        public XMongoRepositoryDescriptor() : base()
        {
            //
            SeederService = typeof(TSeederService);
            SeederImplementation = typeof(TSeederImplementation);

            //
            RepositoryService = typeof(TRepositoryService);
            RepositoryImplementation = typeof(TRepositoryImplementation);
        }
    }

    /// <summary>
    /// a Repository Descriptor ...
    /// </summary>
    public class XEFRepositoryDescriptor<
        TEntity,
        TKey,
        TKeyGeneratorService,
        TKeyGeneratorImplementation,
        TEventsService,
        TEventsImplementation,
        TGraph,
        TGraphKey,
        TGraphQuery,
        TGraphTypeHelperService,
        TGraphTypeHelperImplementation,
        TGraphSchema,
        TRepositoryService,
        TRepositoryImplementation,
        TContext
    > : XRepositoryDescriptor<
        TEntity,
        TKey,
        TKeyGeneratorService,
        TKeyGeneratorImplementation,
        TEventsService,
        TEventsImplementation,
        TGraph,
        TGraphKey,
        TGraphQuery,
        TGraphTypeHelperService,
        TGraphTypeHelperImplementation,
        TGraphSchema
    >
    where TGraphSchema : Schema
    where TContext : XDbContext
    where TGraphKey : IGraphType
    where TEntity : XBaseEntity<TKey>
    where TGraph : XBaseGraphObjectType<TEntity, TKey>
    where TEventsService : IXBaseRepositoryEvents<TEntity>
    where TKeyGeneratorService : IXKeyGenerator<TEntity, TKey>
    where TRepositoryService : IXBaseRepository<TEntity, TKey>
    where TEventsImplementation : XBaseRepositoryEvents<TEntity>
    where TKeyGeneratorImplementation : XKeyGenerator<TEntity, TKey>
    where TGraphTypeHelperService : IXBaseGraphQLTypeHelper<TEntity, TKey>
    where TGraphQuery : XBaseGraphQLQuery<TEntity, TKey, TGraph, TGraphKey>
    where TRepositoryImplementation : XBaseEFRepository<TEntity, TKey, TContext>
    where TGraphTypeHelperImplementation : XBaseGraphQLTypeHelper<TEntity, TKey>
    {
        public XEFRepositoryDescriptor() : base()
        {
            //
            Context = typeof(TContext);
            RepositoryService = typeof(TRepositoryService);
            RepositoryImplementation = typeof(TRepositoryImplementation);
        }
    }

    /// <summary>
    /// a Repository Descriptor ...
    /// </summary>
    public class XEFRepositoryDescriptor<
        TEntity,
        TKey,
        TKeyGeneratorService,
        TKeyGeneratorImplementation,
        TEventsService,
        TEventsImplementation,
        TGraph,
        TGraphKey,
        TGraphQuery,
        TGraphTypeHelperService,
        TGraphTypeHelperImplementation,
        TGraphSchema,
        TRepositoryService,
        TRepositoryImplementation,
        TContext,
        TSeederService,
        TSeederImplementation
    > : XRepositoryDescriptor<
        TEntity,
        TKey,
        TKeyGeneratorService,
        TKeyGeneratorImplementation,
        TEventsService,
        TEventsImplementation,
        TGraph,
        TGraphKey,
        TGraphQuery,
        TGraphTypeHelperService,
        TGraphTypeHelperImplementation,
        TGraphSchema
    >
    where TGraphSchema : Schema
    where TContext : XDbContext
    where TGraphKey : IGraphType
    where TEntity : XBaseEntity<TKey>
    where TGraph : XBaseGraphObjectType<TEntity, TKey>
    where TSeederService : IXBaseDbSeeder<TEntity, TKey>
    where TEventsService : IXBaseRepositoryEvents<TEntity>
    where TSeederImplementation : XBaseDbSeeder<TEntity, TKey>
    where TKeyGeneratorService : IXKeyGenerator<TEntity, TKey>
    where TRepositoryService : IXBaseRepository<TEntity, TKey>
    where TEventsImplementation : XBaseRepositoryEvents<TEntity>
    where TKeyGeneratorImplementation : XKeyGenerator<TEntity, TKey>
    where TGraphTypeHelperService : IXBaseGraphQLTypeHelper<TEntity, TKey>
    where TGraphQuery : XBaseGraphQLQuery<TEntity, TKey, TGraph, TGraphKey>
    where TRepositoryImplementation : XBaseEFRepository<TEntity, TKey, TContext>
    where TGraphTypeHelperImplementation : XBaseGraphQLTypeHelper<TEntity, TKey>
    {
        public XEFRepositoryDescriptor() : base()
        {
            //
            SeederService = typeof(TSeederService);
            SeederImplementation = typeof(TSeederImplementation);

            //
            Context = typeof(TContext);
            RepositoryService = typeof(TRepositoryService);
            RepositoryImplementation = typeof(TRepositoryImplementation);
        }
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xDataService\Mongo\XAsyncEnumerableAdapter.cs

using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;
using MongoDB.Driver;

namespace xDataService.Mongo {
    public class XAsyncEnumerableAdapter<T> : IAsyncEnumerable<T> {
        //
        private readonly IAsyncCursorSource<T> asyncCursorSource;

        //
        public XAsyncEnumerableAdapter (IAsyncCursorSource<T> asyncCursorSource) {
            this.asyncCursorSource = asyncCursorSource;
        }

        //
        public IAsyncEnumerator<T> GetAsyncEnumerator (CancellationToken cancellationToken) =>
        new XAsyncEnumeratorAdapter<T> (asyncCursorSource, cancellationToken);
    }

    public class XAsyncEnumeratorAdapter<T> : IAsyncEnumerator<T> {
        private readonly IAsyncCursorSource<T> asyncCursorSource;
        private readonly CancellationToken cancellationToken;
        private IAsyncCursor<T> asyncCursor;
        private IEnumerator<T> batchEnumerator;

        public T Current => batchEnumerator.Current;

        public XAsyncEnumeratorAdapter (
            IAsyncCursorSource<T> asyncCursorSource,
            CancellationToken cancellationToken
        ) {
            //
            this.asyncCursorSource = asyncCursorSource;
            this.cancellationToken = cancellationToken;
        }

        public async ValueTask<bool> MoveNextAsync () {
            //
            if (asyncCursor == null) {
                asyncCursor = await asyncCursorSource
                    .ToCursorAsync (cancellationToken);
            }

            //
            if (batchEnumerator != null &&
                batchEnumerator.MoveNext ()) {
                return true;
            }

            //
            if (asyncCursor != null &&
                await asyncCursor.MoveNextAsync (cancellationToken)) {
                //
                batchEnumerator?.Dispose ();
                batchEnumerator = asyncCursor.Current.GetEnumerator ();

                //
                return batchEnumerator.MoveNext ();
            }

            //
            return false;
        }

        public async ValueTask DisposeAsync () {
            //
            await Task.CompletedTask;
            asyncCursor?.Dispose ();
            asyncCursor = null;
        }
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xDataService\Mongo\XMongoAsyncCursor.cs

using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;
using MongoDB.Driver;

namespace xDataService.Mongo {
    public class XMongoAsyncCursor<T> : IAsyncCursor<T> {
        public IEnumerable<T> Current { get; }
        private IEnumerator<T> CurrentEnumerator { get; }

        public XMongoAsyncCursor (IEnumerable<T> source) {
            this.Current = source;
            this.CurrentEnumerator = source.GetEnumerator ();
        }

        public void Dispose () {
            CurrentEnumerator.Dispose ();
        }

        public bool MoveNext (CancellationToken cancellationToken = default) {
            return CurrentEnumerator.MoveNext ();
        }

        public Task<bool> MoveNextAsync (CancellationToken cancellationToken = default) {
            return Task.Run (
                () => CurrentEnumerator.MoveNext (),
                cancellationToken : cancellationToken
            );
        }
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xDataService\Mongo\XMongoQueryable.cs

using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Threading;
using System.Threading.Tasks;
using MongoDB.Driver;
using MongoDB.Driver.Linq;
using xModels.Base;

namespace xDataService.Mongo {
    public class XMongoQueryable<TEntity, TKey> : IMongoQueryable<TEntity>
        where TEntity : XBaseEntity<TKey> {
            private readonly IMongoCollection<TEntity> collection;

            public Type ElementType { get; }
            public IQueryable<TEntity> Items { get; }
            public Expression Expression { get; }
            public IQueryProvider Provider { get; }

            public XMongoQueryable (
                IQueryable<TEntity> items,
                IMongoCollection<TEntity> collection
            ) {
                //
                this.Items = items;
                this.collection = collection;

                //
                Provider = items.Provider;
                Expression = items.Expression;
                ElementType = items.ElementType;
            }

            public IEnumerator<TEntity> GetEnumerator () {
                return Items.GetEnumerator ();
            }

            public QueryableExecutionModel GetExecutionModel () {
                return collection.AsQueryable ().GetExecutionModel ();
            }

            public IAsyncCursor<TEntity> ToCursor (CancellationToken cancellationToken = default) {
                return new XMongoAsyncCursor<TEntity> (Items);
            }

            public Task<IAsyncCursor<TEntity>> ToCursorAsync (CancellationToken cancellationToken = default) {
                return Task.Run (() => new XMongoAsyncCursor<TEntity> (Items) as IAsyncCursor<TEntity>);
            }

            IEnumerator IEnumerable.GetEnumerator () {
                return Items.GetEnumerator ();
            }
        }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xDataService\Mongo\XMongoReadPreferenceResolver.cs

using MongoDB.Driver;

namespace xDataService.Mongo {
    public static class XMongoReadPreferenceResolver {
        public static ReadPreference GetEffectiveReadPreference (
            IClientSessionHandle session,
            ReadPreference explicitReadPreference,
            ReadPreference defaultReadPreference) {
            if (explicitReadPreference != null) {
                return explicitReadPreference;
            }

            if (session.IsInTransaction) {
                var transactionReadPreference = session.WrappedCoreSession.CurrentTransaction.TransactionOptions.ReadPreference;
                if (transactionReadPreference != null) {
                    return transactionReadPreference;
                }
            }

            return defaultReadPreference ?? ReadPreference.Primary;
        }
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xDataService\Providers\XBaseDbSeeder.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using xCommons.Extensions;
using xDataService.Configuration;
using xDataService.Constants;
using xDataService.Interfaces;
using xModels.Base;

namespace xDataService.Providers
{
    public abstract class XBaseDbSeeder<TEntity, TKey> : IXBaseDbSeeder<TEntity, TKey>
    where TEntity : XBaseEntity<TKey>
    {
        //
        #region Properties ...
        /// <summary>
        /// Holds Entity Name ...
        /// </summary>
        public string Entity { get; }

        /// <summary>
        /// Holds Database Name ...
        /// </summary>
        public string Database { get; }

        /// <summary>
        /// Repository Service for Data Manipulation ...
        /// </summary>
        public IXBaseRepository<TEntity, TKey> Repository { get; }

        /// <summary>
        /// DataServiceConfiguration ...
        /// </summary>
        public XDataServiceConfiguration DataServiceConfiguration { get; }
        #endregion

        //
        #region Constructor ...
        public XBaseDbSeeder(
            string entity,
            string database,
            IXBaseRepository<TEntity, TKey> repository,
            XDataServiceConfiguration dataServiceConfiguration
        )
        {
            //
            this.Entity = entity;
            this.Database = database;
            this.Repository = repository;
            this.DataServiceConfiguration = dataServiceConfiguration;
        }
        #endregion

        public async Task Seed()
        {
            //
            // Validate Seed ...
            var isValid =
                DataServiceConfiguration.SeedingMode != XDbSeedingMode.None &&
                DataServiceConfiguration
                    .Databases
                    .Any(db =>
                        db.Key == Database &&
                        db.Value.SeedItems
                            .Any(si =>
                                si.Key == Entity &&
                                si.Value.HasChild()));
            if (!isValid)
            {
                return;
            }

            //
            // Extract Seeding Items ...
            var seedItems = DataServiceConfiguration
                .Databases[Database]
                .SeedItems[Entity]
                .ToList();
            foreach (var item in seedItems)
            {
                //
                try
                {
                    //
                    var entity = item
                        .ToJSON()
                        .FromJSON<TEntity>();

                    //
                    // Check Item Exists or not ...
                    var isExist = false;
                    TEntity exists = null;
                    var asyncEnumerable = this.Repository.GetAllAsAsyncEnumerable();
                    await foreach (var e in asyncEnumerable)
                    {
                        //
                        isExist = e.IsSameContent(
                            dest: entity,
                            propertyBlackList: new List<string>
                            {
                                nameof(entity.Id),
                                nameof(entity.Deleted)
                            });
                        if (isExist)
                        {
                            exists = e;
                            break;
                        }
                    }

                    //
                    // Seed Based on Seed Mode ...
                    var seedMode = DataServiceConfiguration.SeedingMode;
                    switch (seedMode)
                    {
                        //
                        case XDbSeedingMode.AddIfNotExists:
                            //
                            if (!isExist)
                            {
                                //
                                exists = await Repository.AddAsync(
                                    item: entity,
                                    saveChanges: true
                                );
                            }
                            break;

                        //
                        case XDbSeedingMode.AddOrUpdate:
                            //
                            exists = exists.UpdateData(
                                updateWith: entity,
                                propertyBlackList: new List<string>
                                {
                                    nameof(entity.Id),
                                    nameof(entity.Deleted)
                                }
                            );

                            //
                            await Repository.AddOrUpdateAsync(exists);
                            break;
                    }
                }
                catch
                { }
            }
        }
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xDataService\Providers\XBaseEFRepository.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Runtime.CompilerServices;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.ChangeTracking;
using Microsoft.EntityFrameworkCore.Query;
using xCommons.Extensions;
using xDataService.Configuration;
using xDataService.Db;
using xDataService.Extensions;
using xDataService.Interfaces;
using xDataService.Models;
using xModels.Base;
using xModels.Dtos;

namespace xDataService.Providers
{
    /// <summary>
    /// a Base Repository Pattern Implementation Specially for EF DBs using
    /// EF Core Capabilities ...
    /// </summary>
    /// <typeparam name="T"></typeparam>
    /// <typeparam name="TKey"></typeparam>
    /// <typeparam name="TDbContext"></typeparam>
    public abstract class XBaseEFRepository<T, TKey, TDbContext> : IXBaseRepository<T, TKey>
        where T : XBaseEntity<TKey>
        where TDbContext : XDbContext
    {
        //
        #region Properties ...
        //
        public readonly DbSet<T> dbSet;
        private readonly IXKeyGenerator<T, TKey> keyGenerator;
        public readonly IXUnitOfWorks<TDbContext> unitOfWorks;
        public readonly XDataServiceConfiguration configuration;
        private readonly IXBaseRepositoryEvents<T> baseRepositoryEvents;
        #endregion

        //
        #region Constructor ...
        public XBaseEFRepository(
            IXUnitOfWorks<TDbContext> unitOfWorks,
            XDataServiceConfiguration configuration,
            IXKeyGenerator<T, TKey> keyGenerator = null,
            IXBaseRepositoryEvents<T> baseRepositoryEvents = null
        )
        {
            //
            this.unitOfWorks = unitOfWorks;
            this.keyGenerator = keyGenerator;
            this.configuration = configuration;
            this.dbSet = unitOfWorks.GetDbSet<T, TKey>();
            this.baseRepositoryEvents = baseRepositoryEvents;
        }
        #endregion

        //
        #region Actions ...
        //
        #region Add ...
        /// <summary>
        /// add a new Entity ...
        /// </summary>
        /// <param name="item"></param>
        /// <param name="saveChanges"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public async Task<T> AddAsync(
            T item,
            bool saveChanges = true,
            CancellationToken cancellationToken = default
        )
        {
            //
            // Handle Key ...
            item = await HandleKeyAsync(
                item: item,
                cancellationToken: cancellationToken
            );

            //
            var entry = await dbSet.AddAsync(
                entity: item,
                cancellationToken: cancellationToken
            );

            //
            // Check action is Succeeded or not ...
            var isSucceed = false;
            if (saveChanges)
            {
                //
                // Get Modified Count ...
                var qResult = await SaveChangesAsync(cancellationToken);

                //
                // set isSucceed Value based on Changes ...
                isSucceed = qResult > 0;
            }

            //
            // Notify Event ...
            if (
                isSucceed &&
                !baseRepositoryEvents.IsNull()
            )
            {
                //
                baseRepositoryEvents
                    .AddEvent(new XBaseEventModel<T>(entry.Entity));
            }

            //
            // Return result base on action Succeed ...
            return isSucceed ?
                entry.Entity :
                null;
        }

        /// <summary>
        /// add or update an Entity (add if not exists/update if exists) ...
        /// </summary>
        /// <param name="item"></param>
        /// <param name="saveChanges"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public async Task<T> AddOrUpdateAsync(
            T item,
            bool saveChanges = true,
            CancellationToken cancellationToken = default
        )
        {
            //
            var isExists = await IsExistsAsync(
                id: GetKey(item),
                cancellationToken: cancellationToken
            );
            if (!isExists)
            {
                //
                return await AddAsync(
                    item: item,
                    saveChanges: saveChanges,
                    cancellationToken: cancellationToken
                );
            }
            else
            {
                //
                return await UpdateAsync(
                    item: item,
                    id: GetKey(item),
                    saveChanges: saveChanges,
                    cancellationToken: cancellationToken
                );
            }
        }

        /// <summary>
        /// add a range of new Entities ...
        /// </summary>
        /// <param name="items"></param>
        /// <param name="saveChanges"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public async Task AddRangeAsync(
            IEnumerable<T> items,
            bool saveChanges = true,
            CancellationToken cancellationToken = default
        )
        {
            //
            // Preparing Ids and Keys ...
            await dbSet.AddRangeAsync(
                await Task
                .WhenAll(
                    items
                    .Select(async i => await HandleKeyAsync(i))
                ),
                cancellationToken: cancellationToken
            );

            //
            // Check action is Succeeded or not ...
            var isSucceed = false;
            if (saveChanges)
            {
                //
                // Get Modified Count ...
                var qResult = await SaveChangesAsync(cancellationToken);

                //
                // set isSucceed Value based on Changes ...
                isSucceed = qResult > 0;
            }

            //
            // Notify Event ...
            if (
                isSucceed &&
                !baseRepositoryEvents.IsNull()
            )
            {
                //
                baseRepositoryEvents
                    .AddManyEvent(new XBaseEventModel<IEnumerable<T>>(null));
            }
        }
        #endregion

        //
        #region Update ...
        /// <summary>
        /// Update an Entity values ...
        /// </summary>
        /// <param name="id"></param>
        /// <param name="item"></param>
        /// <param name="saveChanges"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public async Task<T> UpdateAsync(
            TKey id,
            T item,
            bool saveChanges = true,
            CancellationToken cancellationToken = default
        )
        {
            //
            // Get Exists Entity ...
            var existsEntity = await GetAsync(
                id: id,
                ignoreSoftDeleteds: false,
                cancellationToken: cancellationToken
            );

            //
            // Update Data ...
            existsEntity.UpdateData(item);
            var entry = dbSet.Attach(existsEntity);
            entry.State = EntityState.Modified;

            //
            // Check action is Succeeded or not ...
            var isSucceed = false;
            if (saveChanges)
            {
                //
                // Get Modified Count ...
                var qResult = await SaveChangesAsync(cancellationToken);

                //
                // set isSucceed Value based on Changes ...
                isSucceed = qResult > 0;
            }

            //
            // Notify Event ...
            if (
                isSucceed &&
                !baseRepositoryEvents.IsNull()
            )
            {
                //
                baseRepositoryEvents
                    .UpdateEvent(new XBaseEventModel<T>(entry.Entity));
            }

            //
            // Return result base on action Succeed ...
            return isSucceed ?
                entry.Entity :
                null;
        }

        /// <summary>
        /// Update a range of Entities ...
        /// </summary>
        /// <param name="items"></param>
        /// <param name="saveChanges"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public async Task<bool> UpdateRangeAsync(
            IEnumerable<T> items,
            bool saveChanges = true,
            CancellationToken cancellationToken = default
        )
        {
            //
            items
                .ToList()
                .ForEach(i =>
                {
                    var entry = dbSet.Attach(i);
                    entry.State = EntityState.Modified;
                });

            //
            // Check action is Succeeded or not ...
            var isSucceed = false;
            if (saveChanges)
            {
                //
                // Get Modified Count ...
                var qResult = await SaveChangesAsync(cancellationToken);

                //
                // set isSucceed Value based on Changes ...
                isSucceed = qResult > 0;
            }

            //
            // Notify Event ...
            if (
                isSucceed &&
                !baseRepositoryEvents.IsNull()
            )
            {
                //
                baseRepositoryEvents
                    .UpdateManyEvent(new XBaseEventModel<IEnumerable<T>>(null));
            }

            //
            // Return result base on action Succeed ...
            return isSucceed;
        }
        #endregion

        //
        #region Remove ...
        /// <summary>
        /// remove an Entity by it's Id ...
        /// </summary>
        /// <param name="id"></param>
        /// <param name="softDelete"></param>
        /// <param name="saveChanges"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public async Task<T> RemoveAsync(
            TKey id,
            bool softDelete = true,
            bool saveChanges = true,
            CancellationToken cancellationToken = default
        )
        {
            //
            // Retrieve Item ...
            var item = await GetAsync(
                id,
                ignoreSoftDeleteds: false,
                cancellationToken: cancellationToken
            );
            if (item.IsNullOrDefault())
            {
                return null;
            }

            //
            // Handle Remove ...
            EntityEntry<T> entry = null;
            if (softDelete && configuration.EnableSoftDelete)
            {
                //
                item.Deleted = true;
                entry = dbSet.Update(item);
            }
            else
            {
                entry = dbSet.Remove(item);
            }

            //
            // Check action is Succeeded or not ...
            var isSucceed = false;
            if (saveChanges)
            {
                //
                // Get Modified Count ...
                var qResult = await SaveChangesAsync(cancellationToken);

                //
                // set isSucceed Value based on Changes ...
                isSucceed = qResult > 0;
            }

            //
            // Notify Event ...
            if (
                isSucceed &&
                !baseRepositoryEvents.IsNull()
            )
            {
                //
                baseRepositoryEvents
                    .RemoveEvent(new XBaseEventModel<T>(entry.Entity));
            }

            //
            // Return result base on action Succeed ...
            return isSucceed ?
                entry.Entity :
                null;
        }

        /// <summary>
        /// remove an Entity ...
        /// </summary>
        /// <param name="item"></param>
        /// <param name="softDelete"></param>
        /// <param name="saveChanges"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public async Task<T> RemoveAsync(
            T item,
            bool softDelete = true,
            bool saveChanges = true,
            CancellationToken cancellationToken = default
        )
        {
            //
            var result = await RemoveAsync(
                id: item.Id,
                softDelete: softDelete,
                saveChanges: saveChanges,
                cancellationToken: cancellationToken
            );

            //
            return result;
        }

        /// <summary>
        /// remove a range of exists Entities ...
        /// </summary>
        /// <param name="items"></param>
        /// <param name="softDelete"></param>
        /// <param name="saveChanges"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public async Task RemoveRangeAsync(
            IEnumerable<T> items,
            bool softDelete = true,
            bool saveChanges = true,
            CancellationToken cancellationToken = default
        )
        {
            //
            // Handle Remove ...
            if (softDelete && configuration.EnableSoftDelete)
            {
                //
                foreach (var item in items)
                {
                    item.Deleted = true;
                }

                //
                dbSet.UpdateRange(items);
            }
            else
            {
                dbSet.RemoveRange(items);
            }

            //
            // Check action is Succeeded or not ...
            var isSucceed = false;
            if (saveChanges)
            {
                //
                // Get Modified Count ...
                var qResult = await SaveChangesAsync(cancellationToken);

                //
                // set isSucceed Value based on Changes ...
                isSucceed = qResult > 0;
            }

            //
            // Notify Event ...
            if (
                isSucceed &&
                !baseRepositoryEvents.IsNull()
            )
            {
                //
                baseRepositoryEvents
                    .RemoveManyEvent(new XBaseEventModel<IEnumerable<T>>(null));
            }
        }
        #endregion

        //
        #region Count ...
        /// <summary>
        /// count all exists Entities ...
        /// </summary>
        /// <param name="ignoreSoftDeleteds"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public async Task<int> CountAsync(
            bool ignoreSoftDeleteds = true,
            CancellationToken cancellationToken = default
        )
        {
            //
            var result = 0;

            //
            if (ignoreSoftDeleteds)
            {
                //
                result = await dbSet.CountAsync(
                    predicate: x => !x.Deleted,
                    cancellationToken: cancellationToken
                );
            }
            else
            {
                result = await dbSet.CountAsync(cancellationToken);
            }

            //
            return result;
        }

        /// <summary>
        /// count all exists Entities Pages by providing page size ...
        /// </summary>
        /// <param name="pageSize"></param>
        /// <param name="totalItems"></param>
        /// <param name="ignoreSoftDeleteds"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public async Task<int> PagesCountAsync(
            int pageSize,
            int? totalItems = null,
            bool ignoreSoftDeleteds = true,
            CancellationToken cancellationToken = default
        )
        {
            //
            int count = totalItems.HasValue ? totalItems.Value : await CountAsync(
                cancellationToken: cancellationToken,
                ignoreSoftDeleteds: ignoreSoftDeleteds
            );
            int pagesCount = count / pageSize;

            //
            if (count % pageSize > 0)
            {
                pagesCount++;
            }

            //
            return pagesCount;
        }
        #endregion

        //
        #region Retrieve ...
        /// <summary>
        /// retrieve whole items as queryable ...
        /// </summary>
        /// <param name="asNoTracking">a flag for Tracking behaviour</param>
        /// <param name="predicate">an Expression for Filter Items ...</param>
        /// <param name="orderBuilder">an Order Builder expression for Ordering Query ...</param>
        /// <param name="includeBuilder">an Include Builder expression for Including Navigation Properties ...</param>
        /// <returns></returns>
        public IQueryable<T> AsQueryable(
            bool asNoTracking = true,
            Expression<Func<T, bool>> predicate = null,
            Func<IQueryable<T>, IOrderedQueryable<T>> orderBuilder = null,
            Func<IQueryable<T>, IIncludableQueryable<T, object>> includeBuilder = null
        )
        {
            //
            var result = dbSet
                .AsQueryable();

            //
            // Apply Predicate ...
            if (!predicate.IsNull())
            {
                result = result
                    .Where(predicate);
            }

            //
            // Apply Includes ...
            if (!includeBuilder.IsNull())
            {
                result = includeBuilder(result);
            }

            //
            // Apply Ordering ...
            if (!orderBuilder.IsNull())
            {
                result = orderBuilder(result);
            }

            //
            return result;
        }

        /// <summary>
        /// retrieve an Entity by it's Id ...
        /// </summary>
        /// <param name="id"></param>
        /// <param name="ignoreSoftDeleteds"></param>
        /// <param name="includeBuilder"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public async Task<T> GetAsync(
            TKey id,
            bool ignoreSoftDeleteds = true,
            Func<IQueryable<T>, IIncludableQueryable<T, object>> includeBuilder = null,
            CancellationToken cancellationToken = default
        )
        {
            //
            // Prepare Ignore Soft Deleted Predicator ...
            Expression<Func<T, bool>> predicator = null;
            if (ignoreSoftDeleteds)
            {
                predicator = x => !x.Deleted;
            }
            var result = (await AsQueryable(
                asNoTracking: true,
                orderBuilder: null,
                predicate: predicator,
                includeBuilder: includeBuilder
            )
            .ToListAsync(cancellationToken))
            .FirstOrDefault(x => GetKey(x).ToString() == id.ToString());

            //
            return result;
        }

        /// <summary>
        /// retrieve all exists Entities ...
        /// </summary>
        /// <param name="ignoreSoftDeleteds"></param>
        /// <param name="orderBuilder"></param>
        /// <param name="includeBuilder"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public async Task<IEnumerable<T>> GetAllAsync(
            bool ignoreSoftDeleteds = true,
            Func<IQueryable<T>, IOrderedQueryable<T>> orderBuilder = null,
            Func<IQueryable<T>, IIncludableQueryable<T, object>> includeBuilder = null,
            CancellationToken cancellationToken = default
        )
        {
            //
            // Prepare Ignore Soft Deleted Predicator ...
            Expression<Func<T, bool>> predicator = null;
            if (ignoreSoftDeleteds)
            {
                predicator = x => !x.Deleted;
            }
            var result = await AsQueryable(
                asNoTracking: true,
                predicate: predicator,
                orderBuilder: orderBuilder,
                includeBuilder: includeBuilder
            )
            .ToListAsync(cancellationToken);

            //
            return result;
        }

        /// <summary>
        /// retrieve all exists Entities
        /// as Async Enumerable ...
        /// </summary>
        /// <param name="ignoreSoftDeleteds"></param>
        /// <param name="orderBuilder"></param>
        /// <param name="includeBuilder"></param>
        /// <returns></returns>
        public IAsyncEnumerable<T> GetAllAsAsyncEnumerable(
            bool ignoreSoftDeleteds = true,
            Func<IQueryable<T>, IOrderedQueryable<T>> orderBuilder = null,
            Func<IQueryable<T>, IIncludableQueryable<T, object>> includeBuilder = null
        )
        {
            //
            // Prepare Ignore Soft Deleted Predicator ...
            Expression<Func<T, bool>> predicator = null;
            if (ignoreSoftDeleteds)
            {
                predicator = x => !x.Deleted;
            }
            var result = AsQueryable(
                asNoTracking: true,
                predicate: predicator,
                orderBuilder: orderBuilder,
                includeBuilder: includeBuilder
            )
            .AsAsyncEnumerable();

            //
            return result;

        }

        /// <summary>
        /// find an Entity by providing a Conditional Expression ...
        /// </summary>
        /// <param name="predicate"></param>
        /// <param name="ignoreSoftDeleteds"></param>
        /// <param name="includeBuilder"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public async Task<T> FindOneAsync(
            Expression<Func<T, bool>> predicate,
            bool ignoreSoftDeleteds = true,
            Func<IQueryable<T>, IIncludableQueryable<T, object>> includeBuilder = null,
            CancellationToken cancellationToken = default
        )
        {
            //
            // Prepare Ignore Soft Deleted Predicator ...
            Expression<Func<T, bool>> predicator = null;
            if (ignoreSoftDeleteds)
            {
                predicator = x => !x.Deleted;
            }
            var result = (await AsQueryable(
                asNoTracking: true,
                orderBuilder: null,
                predicate: predicator,
                includeBuilder: includeBuilder
            )
            .ToListAsync(cancellationToken))
            .FirstOrDefault(predicate.Compile());

            //
            return result;
        }

        /// <summary>
        /// find a collection of Entities by proving a Conditional Expression ...
        /// </summary>
        /// <param name="predicate"></param>
        /// <param name="ignoreSoftDeleteds"></param>
        /// <param name="orderBuilder"></param>
        /// <param name="includeBuilder"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public async Task<IEnumerable<T>> FindManyAsync(
            Expression<Func<T, bool>> predicate,
            bool ignoreSoftDeleteds = true,
            Func<IQueryable<T>, IOrderedQueryable<T>> orderBuilder = null,
            Func<IQueryable<T>, IIncludableQueryable<T, object>> includeBuilder = null,
            CancellationToken cancellationToken = default
        )
        {
            //
            // Prepare Ignore Soft Deleted Predicator ...
            Expression<Func<T, bool>> predicator = null;
            if (ignoreSoftDeleteds)
            {
                predicator = x => !x.Deleted;
            }
            var result = (await AsQueryable(
                asNoTracking: true,
                predicate: predicator,
                orderBuilder: orderBuilder,
                includeBuilder: includeBuilder
            )
            .ToListAsync(cancellationToken))
            .Where(predicate.Compile());

            //
            return result;
        }

        /// <summary>
        /// retrieve Entities based on XQuery Pagination structure ...
        /// </summary>
        /// <param name="query"></param>
        /// <param name="ignoreSoftDeleteds"></param>
        /// <param name="predicate"></param>
        /// <param name="orderBuilder"></param>
        /// <param name="includeBuilder"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public async Task<XQueryResult<T>> QueryAsync(
            XQuery query,
            bool ignoreSoftDeleteds = true,
            Expression<Func<T, bool>> predicate = null,
            Func<IQueryable<T>, IOrderedQueryable<T>> orderBuilder = null,
            Func<IQueryable<T>, IIncludableQueryable<T, object>> includeBuilder = null,
            CancellationToken cancellationToken = default
        )
        {
            //
            // Normalize Query ...
            query = query.NormalizeQuery(configuration);

            //
            var items = await GetAllAsync();
            var totalItemsCount = items.Count();

            //
            // Apply Filter ...
            if (!query.Filter.IsNullOrEmpty())
            {
                //
                items = items
                    .ApplyFilter(query.Filter);
            }
            int filteredItemsCount = items.Count();

            //
            // Count Pages ...
            var totalPagesCount = query.CountPages(totalItemsCount);
            var filteredPagesCount = query.CountPages(filteredItemsCount);

            //
            // Apply Paging and Sorting ...
            if (totalItemsCount > 0 &&
                filteredItemsCount > 0)
            {
                //
                // Apply Sorting ...
                items = items
                    .ToList()
                    .ApplySorting(
                        query.SortBy,
                        query.IsAscending
                    );

                //
                // Apply Paging ...
                items = items
                    .ToList()
                    .ApplyPaging(
                        query.Page,
                        query.PageSize
                    );
            }

            //
            // Prepare Result ...
            var result = new XQueryResult<T>
            {
                Page = query.Page,
                Items = items.ToList(),
                PageSize = query.PageSize,
                TotalPages = totalPagesCount,
                TotalItems = totalItemsCount,
                TotalFilteredPages = filteredPagesCount,
                TotalFilteredItems = filteredItemsCount
            };

            //
            return result;
        }
        #endregion

        //
        #region Exists ...
        /// <summary>
        /// Check an Entity exists or not ...
        /// </summary>
        /// <param name="id"></param>
        /// <param name="ignoreSoftDeleteds"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public async Task<bool> IsExistsAsync(
            TKey id,
            bool ignoreSoftDeleteds = true,
            CancellationToken cancellationToken = default
        )
        {
            //
            // Prepare Ignore Soft Deleted Predicator ...
            Expression<Func<T, bool>> predicator = null;
            if (ignoreSoftDeleteds)
            {
                predicator = x => !x.Deleted;
            }
            var result = (await AsQueryable(
                asNoTracking: true,
                orderBuilder: null,
                includeBuilder: null,
                predicate: predicator
            )
            .ToListAsync(cancellationToken))
            .Any(predicate: x => GetKey(x).ToString() == id.ToString());

            //
            return result;
        }
        #endregion

        //
        #region Unit Of Work ...
        /// <summary>
        /// Save all unsaved Transactions on DbContext ...
        /// used fo Unit Of Works Design Pattern ...
        /// </summary>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public async Task<int> SaveChangesAsync(
            CancellationToken cancellationToken = default
        )
        {
            return await unitOfWorks.SaveChangesAsync(cancellationToken);
        }
        #endregion

        //
        #region Key ...
        /// <summary>
        /// Retrieve Key of Entity ...
        /// </summary>
        /// <param name="item"></param>
        /// <returns></returns>
        public TKey GetKey(T item)
        {
            //
            var props = item.GetType().GetProperties();
            var keyProp = props.FirstOrDefault(p => p.Name == "Id");

            //
            var keyString = string.Empty;
            if (keyProp.IsNull())
            {
                keyString = string.Empty;
            }
            else
            {
                keyString = keyProp.GetValue(item).ToString();
            }

            //
            if (keyString.IsNullOrEmpty())
            {
                return default(TKey);
            }

            //
            // Prevent Deserializing issues throug JsonReader ...
            if (keyString.IsGuid() && typeof(TKey) == typeof(Guid))
            {
                return item.Id;
            }

            //
            return keyString.FromJSON<TKey>();
        }

        /// <summary>
        /// Set Key of Entity ...
        /// </summary>
        /// <param name="item"></param>
        /// <param name="id"></param>
        public void SetKey(
            ref T item,
            TKey id
        )
        {
            //
            var props = item.GetType().GetProperties();
            var keyProp = props.FirstOrDefault(p => p.Name == "Id");
            if (keyProp.IsNull())
            {
                return;
            }

            //
            Type t = Nullable.GetUnderlyingType(keyProp.PropertyType) ?? keyProp.PropertyType;
            object safeValue = (id == null) ? null : Convert.ChangeType(id, t);
            keyProp.SetValue(item, safeValue, null);
        }

        /// <summary>
        /// Handle Checking Key ...
        /// </summary>
        /// <param name="item"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public async Task<T> HandleKeyAsync(
            T item,
            CancellationToken cancellationToken = default
        )
        {
            //
            var keyType = typeof(TKey);

            //
            // Handle Guid Key Type ...
            // Since EFCore has AutoIncrement on int Ids, there is no need to handle int Key types ...
            if (
                (
                    keyType == typeof(Guid) ||
                    keyType == typeof(string)
                ) &&
                keyGenerator.IsEmpty(item.Id)
            )
            {
                //
                var newKey = await keyGenerator.GenerateKey(this);

                //
                SetKey(ref item, newKey);
            }

            //
            return item;
        }
        #endregion

        //
        #region Detach ...
        /// <summary>
        /// Detach an Entity ...
        /// </summary>
        /// <param name="item"></param>
        public void Detach(T item)
        {
            //
            if (item.IsNull())
            {
                return;
            }

            //
            Entry(item).State = EntityState.Detached;
        }

        /// <summary>
        /// Detach an Enumerable of Entities ...
        /// </summary>
        /// <param name="items"></param>
        public void Detach(IEnumerable<T> items)
        {
            //
            if (items.IsNull() || !items.HasChild())
            {
                return;
            }

            //
            items
                .ToList()
                .ForEach(item =>
                {
                    Detach(item);
                });
        }

        /// <summary>
        /// Detach a Query Result of Entity ...
        /// </summary>
        /// <param name="query"></param>
        public void Detach(XQueryResult<T> query)
        {
            //
            if (query.IsNull() || query.Items.HasChild())
            {
                return;
            }

            //
            Detach(query.Items);
        }
        #endregion
        #endregion

        //
        #region Others ...
        public void Dispose()
        {
            unitOfWorks.Dispose();
        }

        public string GetPropValues(T item)
        {
            //
            var props = item.GetType().GetProperties();
            var vals = props.Select(p => p.GetValue(p.Name));

            //
            return vals.ToJSON();
        }

        public EntityEntry<T> Entry(T item)
        {
            return unitOfWorks.DbContext.Entry(item);
        }
        #endregion

        //
        #region Private ...
        #endregion
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xDataService\Providers\XBaseEntityRegisterar.cs

using System;
using System.Collections.Generic;
using Microsoft.EntityFrameworkCore;
using xDataService.Interfaces;
using xModels.Base;

namespace xDataService.Providers
{
    /// <summary>
    /// Base Entity Registerar ...
    /// </summary>
    public abstract class XBaseEntityRegisterar : IXEntityRegisterar
    {
        /// <summary>
        /// Private Entity Types Collection ...
        /// </summary>
        private readonly List<Type> entityTypes = [];

        /// <summary>
        /// Name ...
        /// </summary>
        public string Name { get; }

        protected XBaseEntityRegisterar(string name)
        {
            Name = name;
        }

        /// <summary>
        /// Add Specified Entity to Collection ...
        /// </summary>
        /// <typeparam name="TEntity"></typeparam>
        /// <typeparam name="TKey"></typeparam>
        public void AddEntity<TEntity, TKey>()
        where TEntity : XBaseEntity<TKey>
        {
            entityTypes.Add(typeof(TEntity));
        }

        /// <summary>
        /// Retrieve Registered Entity Types ...
        /// </summary>
        /// <returns></returns>
        public IEnumerable<Type> GetEntityTypes()
        {
            return entityTypes;
        }

        /// <summary>
        /// Configure Dynamic Entities ...
        /// </summary>
        /// <param name="modelBuilder"></param>
        public virtual void ConfigureEntities(ModelBuilder modelBuilder)
        { }
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xDataService\Providers\XBaseEntityTypeConfiguration.cs

using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Metadata.Builders;
using xModels.Base;

namespace xDataService.Providers
{
    /// <summary>
    /// Configure an Entity Specifications ...
    /// </summary>
    /// <typeparam name="TEntity"></typeparam>
    /// <typeparam name="TKey"></typeparam>
    public abstract class XBaseEntityTypeConfiguration<TEntity, TKey> : IEntityTypeConfiguration<TEntity>
    where TEntity : XBaseEntity<TKey>
    {
        public abstract void Configure(EntityTypeBuilder<TEntity> builder);
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xDataService\Providers\XBaseInMemoryRepository.cs

using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Query;
using xCommons.Extensions;
using xDataService.Configuration;
using xDataService.Extensions;
using xDataService.Interfaces;
using xDataService.Models;
using xModels.Base;
using xModels.Dtos;

namespace xDataService.Providers
{
    /// <summary>
    /// a Base Repository Pattern Implementation Specially for InMemory Stores using
    /// EF Core Capabilities ...
    /// </summary>
    /// <typeparam name="TEntity"></typeparam>
    /// <typeparam name="TKey"></typeparam>
    public abstract class XBaseInMemoryRepository<TEntity, TKey> : IXBaseRepository<TEntity, TKey>
    where TEntity : XBaseEntity<TKey>
    {
        //
        #region Props ...
        private readonly XDataServiceConfiguration configuration;
        private readonly IXKeyGenerator<TEntity, TKey> keyGenerator;
        private readonly IXBaseRepositoryEvents<TEntity> baseRepositoryEvents;
        private static readonly ConcurrentDictionary<TKey, TEntity> store = new ConcurrentDictionary<TKey, TEntity>();
        #endregion

        //
        #region Constructor ...
        public XBaseInMemoryRepository(
            XDataServiceConfiguration configuration,
            IXKeyGenerator<TEntity, TKey> keyGenerator = null,
            IXBaseRepositoryEvents<TEntity> baseRepositoryEvents = null
        )
        {
            this.keyGenerator = keyGenerator;
            this.configuration = configuration;
            this.baseRepositoryEvents = baseRepositoryEvents;
        }
        #endregion

        //
        #region Actions ...
        //
        #region Add ...
        /// <summary>
        /// add a new Entity ...
        /// </summary>
        /// <param name="item"></param>
        /// <param name="saveChanges"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public async Task<TEntity> AddAsync(
            TEntity item,
            bool saveChanges = true,
            CancellationToken cancellationToken = default
        )
        {
            //
            // Handle Key ...
            item = await HandleKeyAsync(
                item: item,
                cancellationToken: cancellationToken
            );

            //
            var isSucceed = false;

            //
            // Add Item to Dictionary ...
            try
            {
                //
                store[item.Id] = item;
                isSucceed = true;
            }
            catch
            {
                isSucceed = false;
            }

            //
            // Notify Event ...
            if (
                isSucceed &&
                !baseRepositoryEvents.IsNull()
            )
            {
                //
                baseRepositoryEvents
                    .AddEvent(new XBaseEventModel<TEntity>(item));
            }

            //
            // Return Item ...
            return item;
        }

        /// <summary>
        /// add or update an Entity (add if not exists/update if exists) ...
        /// </summary>
        /// <param name="item"></param>
        /// <param name="saveChanges"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public async Task<TEntity> AddOrUpdateAsync(
            TEntity item,
            bool saveChanges = true,
            CancellationToken cancellationToken = default
        )
        {
            //
            var isExists = await IsExistsAsync(
                id: item.Id,
                ignoreSoftDeleteds: true,
                cancellationToken: cancellationToken
            );

            //
            var isSucceed = false;
            if (isExists)
            {
                //
                try
                {
                    //
                    item = await UpdateAsync(
                        item: item,
                        id: item.Id,
                        saveChanges: saveChanges,
                        cancellationToken: cancellationToken
                    );
                    isSucceed = true;
                }
                catch
                {
                    isSucceed = false;
                }
            }
            else
            {
                //
                try
                {
                    //
                    item = await AddAsync(
                        item: item,
                        saveChanges: saveChanges,
                        cancellationToken: cancellationToken
                    );

                    //
                    isSucceed = true;
                }
                catch
                {
                    isSucceed = false;
                }
            }

            //
            // Notify Event ...
            if (
                isSucceed &&
                !baseRepositoryEvents.IsNull()
            )
            {
                //
                if (isExists)
                {
                    //
                    baseRepositoryEvents
                        .UpdateEvent(new XBaseEventModel<TEntity>(item));
                }
                else
                {
                    //
                    baseRepositoryEvents
                        .AddEvent(new XBaseEventModel<TEntity>(item));
                }
            }

            //
            return item;
        }

        /// <summary>
        /// add a range of new Entities ...
        /// </summary>
        /// <param name="items"></param>
        /// <param name="saveChanges"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public async Task AddRangeAsync(
            IEnumerable<TEntity> items,
            bool saveChanges = true,
            CancellationToken cancellationToken = default
        )
        {
            //
            var isValid = !items.IsNull() && items.HasChild();
            if (!isValid)
            {
                return;
            }

            //
            foreach (var item in items)
            {
                //
                await AddAsync(
                    item: item,
                    saveChanges: saveChanges,
                    cancellationToken: cancellationToken
                );
            }

            //
            // Notify Event ...
            if (
                isValid &&
                !baseRepositoryEvents.IsNull()
            )
            {
                //
                baseRepositoryEvents
                    .AddManyEvent(new XBaseEventModel<IEnumerable<TEntity>>(null));
            }
        }
        #endregion

        //
        #region Update ...
        /// <summary>
        /// Update an Entity values ...
        /// </summary>
        /// <param name="id"></param>
        /// <param name="item"></param>
        /// <param name="saveChanges"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public async Task<TEntity> UpdateAsync(
            TKey id,
            TEntity item,
            bool saveChanges = true,
            CancellationToken cancellationToken = default
        )
        {
            //
            var isExists = await IsExistsAsync(
                id: id,
                ignoreSoftDeleteds: true,
                cancellationToken: cancellationToken
            );
            if (!isExists)
            {
                return null;
            }

            //
            var isSucceed = false;
            var exists = store[id];

            //
            try
            {
                //
                exists = exists.UpdateData(
                    exists,
                    propertyBlackList: new List<string> { nameof(exists.Id) }
                );
                store[id] = exists;

                //
                isSucceed = true;
            }
            catch
            {
                isSucceed = false;
            }

            //
            // Notify Event ...
            if (
                isSucceed &&
                !baseRepositoryEvents.IsNull()
            )
            {
                //
                baseRepositoryEvents
                    .UpdateEvent(new XBaseEventModel<TEntity>(item));
            }

            //
            return exists;
        }

        /// <summary>
        /// Update a range of Entities ...
        /// </summary>
        /// <param name="items"></param>
        /// <param name="saveChanges"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public async Task<bool> UpdateRangeAsync(
            IEnumerable<TEntity> items,
            bool saveChanges = true,
            CancellationToken cancellationToken = default
        )
        {
            //
            var result = false;
            var isValid = !items.IsNull() && items.HasChild();
            if (!isValid)
            {
                return result;
            }

            //
            foreach (var item in items)
            {
                //
                var updated = await UpdateAsync(
                    item: item,
                    id: item.Id,
                    saveChanges: saveChanges,
                    cancellationToken: cancellationToken
                );
                if (!updated.IsNullOrDefault() && !result)
                {
                    result = true;
                }
            }

            //
            return result;
        }
        #endregion

        //
        #region Remove ...
        /// <summary>
        /// remove an Entity by it's Id ...
        /// </summary>
        /// <param name="id"></param>
        /// <param name="softDelete"></param>
        /// <param name="saveChanges"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public async Task<TEntity> RemoveAsync(
            TKey id,
            bool softDelete = true,
            bool saveChanges = true,
            CancellationToken cancellationToken = default
        )
        {
            //
            var isExists = await IsExistsAsync(
                id: id,
                cancellationToken: cancellationToken
            );
            if (!isExists)
            {
                return null;
            }

            //
            TEntity result = null;
            if (softDelete && configuration.EnableSoftDelete)
            {
                //
                store[id].Deleted = true;
                result = store[id];
            }
            else
            {
                //
                result = store[id];
                store.TryRemove(id, out _);
            }

            //
            return result;
        }

        /// <summary>
        /// remove an Entity ...
        /// </summary>
        /// <param name="item"></param>
        /// <param name="softDelete"></param>
        /// <param name="saveChanges"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public async Task<TEntity> RemoveAsync(
            TEntity item,
            bool softDelete = true,
            bool saveChanges = true,
            CancellationToken cancellationToken = default
        )
        {
            //
            var result = await RemoveAsync(
                id: item.Id,
                softDelete: softDelete,
                saveChanges: saveChanges,
                cancellationToken: cancellationToken
            );

            //
            return result;
        }

        /// <summary>
        /// remove a range of exists Entities ...
        /// </summary>
        /// <param name="items"></param>
        /// <param name="softDelete"></param>
        /// <param name="saveChanges"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public async Task RemoveRangeAsync(
            IEnumerable<TEntity> items,
            bool softDelete = true,
            bool saveChanges = true,
            CancellationToken cancellationToken = default
        )
        {
            //
            var isValid = !items.IsNull() && items.HasChild();
            if (!isValid)
            {
                return;
            }

            //
            foreach (var item in items)
            {
                //
                await RemoveAsync(
                    item: item,
                    softDelete: softDelete,
                    saveChanges: saveChanges,
                    cancellationToken: cancellationToken
                );
            }
        }
        #endregion

        //
        #region Count ...
        /// <summary>
        /// count all exists Entities ...
        /// </summary>
        /// <param name="ignoreSoftDeleteds"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public async Task<int> CountAsync(
            bool ignoreSoftDeleteds = true,
            CancellationToken cancellationToken = default
        )
        {
            //
            // Prepare Ignore Soft Deleted Predicator ...
            Expression<Func<TEntity, bool>> predicator = null;
            if (ignoreSoftDeleteds)
            {
                predicator = x => !x.Deleted;
            }
            var result = await AsQueryable(
                asNoTracking: true,
                orderBuilder: null,
                includeBuilder: null,
                predicate: predicator
            )
            .CountAsync(cancellationToken);

            //
            return result;
        }

        /// <summary>
        /// count all exists Entities Pages by providing page size ...
        /// </summary>
        /// <param name="pageSize"></param>
        /// <param name="totalItems"></param>
        /// <param name="ignoreSoftDeleteds"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public async Task<int> PagesCountAsync(
            int pageSize,
            int? totalItems = null,
            bool ignoreSoftDeleteds = true,
            CancellationToken cancellationToken = default
        )
        {
            //
            int count = totalItems.HasValue ? totalItems.Value : await CountAsync(
                cancellationToken: cancellationToken,
                ignoreSoftDeleteds: ignoreSoftDeleteds
            );
            int pagesCount = count / pageSize;

            //
            if (count % pageSize > 0)
            {
                pagesCount++;
            }

            //
            return pagesCount;
        }
        #endregion

        //
        #region Exists ...
        /// <summary>
        /// Check an Entity exists or not ...
        /// </summary>
        /// <param name="id"></param>
        /// <param name="ignoreSoftDeleteds"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public async Task<bool> IsExistsAsync(
            TKey id,
            bool ignoreSoftDeleteds = true,
            CancellationToken cancellationToken = default
        )
        {
            //
            // Prepare Ignore Soft Deleted Predicator ...
            Expression<Func<TEntity, bool>> predicator = null;
            if (ignoreSoftDeleteds)
            {
                predicator = x => !x.Deleted;
            }
            var result = await AsQueryable(
                asNoTracking: true,
                orderBuilder: null,
                includeBuilder: null,
                predicate: predicator
            )
            .AnyAsync(
                cancellationToken: cancellationToken,
                predicate: x => GetKey(x).ToString() == id.ToString());

            //
            return result;
        }
        #endregion

        //
        #region Retrieve ...
        /// <summary>
        /// retrieve whole items as queryable ...
        /// </summary>
        /// <param name="asNoTracking">a flag for Tracking behaviour</param>
        /// <param name="predicate">an Expression for Filter Items ...</param>
        /// <param name="orderBuilder">an Order Builder expression for Ordering Query ...</param>
        /// <param name="includeBuilder">an Include Builder expression for Including Navigation Properties ...</param>
        /// <returns></returns>
        public IQueryable<TEntity> AsQueryable(
            bool asNoTracking = true,
            Expression<Func<TEntity, bool>> predicate = null,
            Func<IQueryable<TEntity>, IOrderedQueryable<TEntity>> orderBuilder = null,
            Func<IQueryable<TEntity>, IIncludableQueryable<TEntity, object>> includeBuilder = null
        )
        {
            //
            var result = store.Values.AsQueryable();

            //
            // Predicate ...
            if (!predicate.IsNull())
            {
                result = result.Where(predicate);
            }

            //
            // Apply Orders ...
            if (!orderBuilder.IsNull())
            {
                result = orderBuilder(result);
            }

            //
            // Apply Includes ...
            if (!includeBuilder.IsNull())
            {
                result = includeBuilder(result);
            }

            //
            if (asNoTracking)
            {
                result = result.AsNoTracking();
            }

            //
            return result;
        }

        /// <summary>
        /// retrieve an Entity by it's Id ...
        /// </summary>
        /// <param name="id"></param>
        /// <param name="ignoreSoftDeleteds"></param>
        /// <param name="includeBuilder"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public async Task<TEntity> GetAsync(
            TKey id,
            bool ignoreSoftDeleteds = true,
            Func<IQueryable<TEntity>, IIncludableQueryable<TEntity, object>> includeBuilder = null,
            CancellationToken cancellationToken = default
        )
        {
            //
            // Prepare Ignore Soft Deleted Predicator ...
            Expression<Func<TEntity, bool>> predicator = null;
            if (ignoreSoftDeleteds)
            {
                predicator = x => !x.Deleted;
            }
            var result = await AsQueryable(
                asNoTracking: true,
                orderBuilder: null,
                predicate: predicator,
                includeBuilder: includeBuilder
            )
            .Where(x => GetKey(x).ToString() == id.ToString())
            .FirstOrDefaultAsync(cancellationToken);

            //
            return result;
        }

        /// <summary>
        /// retrieve all exists Entities ...
        /// </summary>
        /// <param name="ignoreSoftDeleteds"></param>
        /// <param name="orderBuilder"></param>
        /// <param name="includeBuilder"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public async Task<IEnumerable<TEntity>> GetAllAsync(
            bool ignoreSoftDeleteds = true,
            Func<IQueryable<TEntity>, IOrderedQueryable<TEntity>> orderBuilder = null,
            Func<IQueryable<TEntity>, IIncludableQueryable<TEntity, object>> includeBuilder = null,
            CancellationToken cancellationToken = default
        )
        {
            //
            // Prepare Ignore Soft Deleted Predicator ...
            Expression<Func<TEntity, bool>> predicator = null;
            if (ignoreSoftDeleteds)
            {
                predicator = x => !x.Deleted;
            }
            var result = await AsQueryable(
                asNoTracking: true,
                orderBuilder: null,
                predicate: predicator,
                includeBuilder: includeBuilder
            )
            .ToListAsync(cancellationToken);

            //
            return result;
        }

        /// <summary>
        /// retrieve all exists Entities
        /// as Async Enumerable ...
        /// </summary>
        /// <param name="ignoreSoftDeleteds"></param>
        /// <param name="orderBuilder"></param>
        /// <param name="includeBuilder"></param>
        /// <returns></returns>
        public IAsyncEnumerable<TEntity> GetAllAsAsyncEnumerable(
            bool ignoreSoftDeleteds = true,
            Func<IQueryable<TEntity>, IOrderedQueryable<TEntity>> orderBuilder = null,
            Func<IQueryable<TEntity>, IIncludableQueryable<TEntity, object>> includeBuilder = null
        )
        {
            //
            Expression<Func<TEntity, bool>> predicator = null;
            if (ignoreSoftDeleteds)
            {
                predicator = x => !x.Deleted;
            }
            var result = AsQueryable(
                asNoTracking: true,
                predicate: predicator,
                orderBuilder: orderBuilder,
                includeBuilder: includeBuilder
            )
            .AsAsyncEnumerable();

            //
            return result;
        }

        /// <summary>
        /// find an Entity by providing a Conditional Expression ...
        /// </summary>
        /// <param name="predicate"></param>
        /// <param name="ignoreSoftDeleteds"></param>
        /// <param name="includeBuilder"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public async Task<TEntity> FindOneAsync(
            Expression<Func<TEntity, bool>> predicate,
            bool ignoreSoftDeleteds = true,
            Func<IQueryable<TEntity>, IIncludableQueryable<TEntity, object>> includeBuilder = null,
            CancellationToken cancellationToken = default
        )
        {
            //
            // Prepare Ignore Soft Deleted Predicator ...
            Expression<Func<TEntity, bool>> predicator = null;
            if (ignoreSoftDeleteds)
            {
                predicator = x => !x.Deleted;
            }
            var result = await AsQueryable(
                asNoTracking: true,
                orderBuilder: null,
                predicate: predicator,
                includeBuilder: includeBuilder
            )
            .Where(predicate)
            .FirstOrDefaultAsync(cancellationToken);

            //
            return result;
        }

        /// <summary>
        /// find a collection of Entities by proving a Conditional Expression ...
        /// </summary>
        /// <param name="predicate"></param>
        /// <param name="ignoreSoftDeleteds"></param>
        /// <param name="orderBuilder"></param>
        /// <param name="includeBuilder"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public async Task<IEnumerable<TEntity>> FindManyAsync(
            Expression<Func<TEntity, bool>> predicate,
            bool ignoreSoftDeleteds = true,
            Func<IQueryable<TEntity>, IOrderedQueryable<TEntity>> orderBuilder = null,
            Func<IQueryable<TEntity>, IIncludableQueryable<TEntity, object>> includeBuilder = null,
            CancellationToken cancellationToken = default
        )
        {
            //
            // Prepare Ignore Soft Deleted Predicator ...
            Expression<Func<TEntity, bool>> predicator = null;
            if (ignoreSoftDeleteds)
            {
                predicator = x => !x.Deleted;
            }
            var result = await AsQueryable(
                asNoTracking: true,
                orderBuilder: null,
                predicate: predicator,
                includeBuilder: includeBuilder
            )
            .Where(predicate)
            .ToListAsync(cancellationToken);

            //
            return result;
        }

        /// <summary>
        /// retrieve Entities based on XQuery Pagination structure ...
        /// </summary>
        /// <param name="query"></param>
        /// <param name="ignoreSoftDeleteds"></param>
        /// <param name="predicate"></param>
        /// <param name="orderBuilder"></param>
        /// <param name="includeBuilder"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public async Task<XQueryResult<TEntity>> QueryAsync(
            XQuery query,
            bool ignoreSoftDeleteds = true,
            Expression<Func<TEntity, bool>> predicate = null,
            Func<IQueryable<TEntity>, IOrderedQueryable<TEntity>> orderBuilder = null,
            Func<IQueryable<TEntity>, IIncludableQueryable<TEntity, object>> includeBuilder = null,
            CancellationToken cancellationToken = default
        )
        {
            //
            // Normalize Query ...
            query = query.NormalizeQuery(configuration);

            //
            var items = await GetAllAsync();
            var totalItemsCount = items.Count();

            //
            // Apply Filter ...
            if (!query.Filter.IsNullOrEmpty())
            {
                //
                items = items
                    .ApplyFilter(query.Filter);
            }
            int filteredItemsCount = items.Count();

            //
            // Count Pages ...
            var totalPagesCount = query.CountPages(totalItemsCount);
            var filteredPagesCount = query.CountPages(filteredItemsCount);

            //
            // Apply Paging and Sorting ...
            if (totalItemsCount > 0 &&
                filteredItemsCount > 0)
            {
                //
                // Apply Sorting ...
                items = items
                    .ToList()
                    .ApplySorting(
                        query.SortBy,
                        query.IsAscending
                    );

                //
                // Apply Paging ...
                items = items
                    .ToList()
                    .ApplyPaging(
                        query.Page,
                        query.PageSize
                    );
            }

            //
            // Prepare Result ...
            var result = new XQueryResult<TEntity>
            {
                Page = query.Page,
                Items = items.ToList(),
                PageSize = query.PageSize,
                TotalPages = totalPagesCount,
                TotalItems = totalItemsCount,
                TotalFilteredPages = filteredPagesCount,
                TotalFilteredItems = filteredItemsCount
            };

            //
            return result;
        }
        #endregion

        //
        #region Unit Of Work ...
        /// <summary>
        /// Save all unsaved Transactions on DbContext ...
        /// used fo Unit Of Works Design Pattern ...
        /// </summary>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public async Task<int> SaveChangesAsync(
            CancellationToken cancellationToken = default
        )
        {
            //
            return await Task.Run(
                () => 0,
                cancellationToken
            );
        }
        #endregion

        //
        #region Key ...
        /// <summary>
        /// Retrieve Key of Entity ...
        /// </summary>
        /// <param name="item"></param>
        /// <returns></returns>
        public TKey GetKey(TEntity item)
        {
            //
            var props = item.GetType().GetProperties();
            var keyProp = props.FirstOrDefault(p => p.Name == "Id");

            //
            var keyString = string.Empty;
            if (keyProp.IsNull())
            {
                keyString = string.Empty;
            }
            else
            {
                keyString = keyProp.GetValue(item).ToString();
            }

            //
            if (keyString.IsNullOrEmpty())
            {
                return default(TKey);
            }

            //
            // Prevent Deserializing issues throug JsonReader ...
            if (keyString.IsGuid() && typeof(TKey) == typeof(Guid))
            {
                return item.Id;
            }

            //
            return keyString.FromJSON<TKey>();
        }

        /// <summary>
        /// Set Key of Entity ...
        /// </summary>
        /// <param name="item"></param>
        /// <param name="id"></param>
        public void SetKey(
            ref TEntity item,
            TKey id
        )
        {
            //
            var props = item.GetType().GetProperties();
            var keyProp = props.FirstOrDefault(p => p.Name == "Id");
            if (keyProp.IsNull())
            {
                return;
            }

            //
            Type t = Nullable.GetUnderlyingType(keyProp.PropertyType) ?? keyProp.PropertyType;
            object safeValue = (id == null) ? null : Convert.ChangeType(id, t);
            keyProp.SetValue(item, safeValue, null);
        }

        /// <summary>
        /// Handle Checking Key ...
        /// </summary>
        /// <param name="item"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public async Task<TEntity> HandleKeyAsync(
            TEntity item,
            CancellationToken cancellationToken = default
        )
        {
            //
            var keyType = typeof(TKey);

            //
            // Handle Guid Key Type ...
            // Since EFCore has AutoIncrement on int Ids, there is no need to handle int Key types ...
            if (
                (
                    keyType == typeof(Guid) ||
                    keyType == typeof(string)
                ) &&
                keyGenerator.IsEmpty(item.Id)
            )
            {
                //
                var newKey = await keyGenerator.GenerateKey(this);

                //
                SetKey(ref item, newKey);
            }

            //
            return item;
        }
        #endregion

        //
        #region Detach ...
        /// <summary>
        /// Detach an Entity ...
        /// </summary>
        /// <param name="item"></param>
        public void Detach(TEntity item) { }

        /// <summary>
        /// Detach an Enumerable of Entities ...
        /// </summary>
        /// <param name="items"></param>
        public void Detach(IEnumerable<TEntity> items) { }

        /// <summary>
        /// Detach a Query Result of Entity ...
        /// </summary>
        /// <param name="query"></param>
        public void Detach(XQueryResult<TEntity> query) { }
        #endregion
        #endregion

        //
        #region Others ...
        public void Dispose()
        { }
        #endregion

        //
        #region Private ...
        #endregion
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xDataService\Providers\XBaseMongoRepository.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Query;
using MongoDB.Driver;
using MongoDB.Driver.Linq;
using xCommons.Extensions;
using xDataService.Configuration;
using xDataService.Extensions;
using xDataService.Interfaces;
using xDataService.Models;
using xModels.Base;
using xModels.Dtos;

namespace xDataService.Providers
{
    /// <summary>
    /// a Base Repository Pattern Implementation Specially for Mongo DBs using
    /// EF Core Capabilities ...
    /// </summary>
    /// <typeparam name="T"></typeparam>
    /// <typeparam name="TKey"></typeparam>
    public abstract class XBaseMongoRepository<T, TKey> : IXBaseRepository<T, TKey>
        where T : XBaseEntity<TKey>
    {
        //
        #region Properties ...
        private readonly string collectionName;
        public List<WriteModel<T>> bulkCollection;
        public readonly IMongoCollection<T> collection;
        private readonly IXKeyGenerator<T, TKey> keyGenerator;
        public readonly XDataBaseConfiguration dbConfiguration;
        public readonly XDataServiceConfiguration configuration;
        private readonly IXBaseRepositoryEvents<T> baseRepositoryEvents;
        #endregion

        //
        #region Constructor ...
        protected XBaseMongoRepository(
            XDataBaseConfiguration dbConfiguration,
            XDataServiceConfiguration configuration,
            string collectionName = null,
            IXKeyGenerator<T, TKey> keyGenerator = null,
            IXBaseRepositoryEvents<T> baseRepositoryEvents = null
        )
        {
            //
            this.keyGenerator = keyGenerator;
            this.configuration = configuration;
            this.collectionName = collectionName
                .IsNullOrEmpty() ?
                typeof(T).Name :
                collectionName;
            this.dbConfiguration = dbConfiguration;
            this.baseRepositoryEvents = baseRepositoryEvents;

            //
            var client = new MongoClient(dbConfiguration.GetMongoDbURI());
            var database = client.GetDatabase(dbConfiguration.GetMongoDbDatabase());

            //
            bulkCollection = new List<WriteModel<T>>();
            collection = database.GetCollection<T>(
                this.collectionName
            );
        }
        #endregion

        //
        #region Actions ...
        //
        #region Add ...
        /// <summary>
        /// add a new Entity ...
        /// </summary>
        /// <param name="item"></param>
        /// <param name="saveChanges"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public async Task<T> AddAsync(
            T item,
            bool saveChanges = true,
            CancellationToken cancellationToken = default
        )
        {
            //
            // Handle Key ...
            item = await HandleKeyAsync(
                item: item,
                cancellationToken: cancellationToken
            );

            //
            // Add Action model to Bulk Collection ...
            bulkCollection.Add(new InsertOneModel<T>(item));

            //
            // Check action is Succeeded or not ...
            var isSucceed = false;
            if (saveChanges)
            {
                //
                // Get Modified Count ...
                var qResult = await SaveChangesAsync(cancellationToken);

                //
                // set isSucceed Value based on Changes ...
                isSucceed = qResult > 0;
            }

            //
            // Notify Event ...
            if (
                isSucceed &&
                !baseRepositoryEvents.IsNull()
            )
            {
                //
                baseRepositoryEvents
                    .AddEvent(new XBaseEventModel<T>(item));
            }

            //
            // Return result base on action Succeed ...
            return isSucceed ?
                item :
                null;
        }

        /// <summary>
        /// add or update an Entity (add if not exists/update if exists) ...
        /// </summary>
        /// <param name="item"></param>
        /// <param name="saveChanges"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public async Task<T> AddOrUpdateAsync(
            T item,
            bool saveChanges = true,
            CancellationToken cancellationToken = default
        )
        {
            //
            var isExists = await IsExistsAsync(
                id: GetKey(item),
                ignoreSoftDeleteds: true,
                cancellationToken: cancellationToken
            );
            if (!isExists)
            {
                //
                // Handle Key ...
                item = await HandleKeyAsync(
                    item: item,
                    cancellationToken: cancellationToken
                );

                //
                // Add Action model to Bulk Collection ...
                bulkCollection
                    .Add(new InsertOneModel<T>(item));
            }
            else
            {
                //
                // Filter ...
                var filter = Builders<T>.Filter.Eq(i => i.Id, item.Id);

                //
                // Add Action model to Bulk Collection ...
                bulkCollection
                    .Add(new ReplaceOneModel<T>(filter, item) { IsUpsert = true });
            }

            //
            // Check action is Succeeded or not ...
            var isSucceed = false;
            if (saveChanges)
            {
                //
                // Get Modified Count ...
                var qResult = await SaveChangesAsync(cancellationToken);

                //
                // set isSucceed Value based on Changes ...
                isSucceed = qResult > 0;
            }

            //
            // Notify Event ...
            if (
                isSucceed &&
                !baseRepositoryEvents.IsNull()
            )
            {
                //
                if (isExists)
                {
                    //
                    baseRepositoryEvents
                        .UpdateEvent(new XBaseEventModel<T>(item));
                }
                else
                {
                    //
                    baseRepositoryEvents
                        .AddEvent(new XBaseEventModel<T>(item));
                }
            }

            //
            // Return result base on action Succeed ...
            return isSucceed ?
                item :
                null;
        }

        /// <summary>
        /// add a range of new Entities ...
        /// </summary>
        /// <param name="items"></param>
        /// <param name="saveChanges"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public async Task AddRangeAsync(
            IEnumerable<T> items,
            bool saveChanges = true,
            CancellationToken cancellationToken = default
        )
        {
            //
            var isValid = !items.IsNull() && items.HasChild();
            if (!isValid)
            {
                return;
            }

            //
            foreach (var item in items)
            {
                //
                await AddAsync(
                    item: item,
                    saveChanges: saveChanges,
                    cancellationToken: cancellationToken
                );
            }

            //
            // Notify Event ...
            if (
                isValid &&
                !baseRepositoryEvents.IsNull()
            )
            {
                //
                baseRepositoryEvents
                    .AddManyEvent(new XBaseEventModel<IEnumerable<T>>(null));
            }
        }
        #endregion

        //
        #region Update ...
        /// <summary>
        /// Update an Entity values ...
        /// </summary>
        /// <param name="id"></param>
        /// <param name="item"></param>
        /// <param name="saveChanges"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public async Task<T> UpdateAsync(
            TKey id,
            T item,
            bool saveChanges = true,
            CancellationToken cancellationToken = default
        )
        {
            //
            // Filter ...
            var filter = Builders<T>.Filter.Eq(i => i.Id, id);

            //
            // Add Action model to Bulk Collection ...
            bulkCollection.Add(new ReplaceOneModel<T>(filter, item) { IsUpsert = false });

            //
            // Check action is Succeeded or not ...
            var isSucceed = false;
            if (saveChanges)
            {
                //
                // Get Modified Count ...
                var qResult = await SaveChangesAsync(cancellationToken);

                //
                // set isSucceed Value based on Changes ...
                isSucceed = qResult > 0;
            }

            //
            // Notify Event ...
            if (
                isSucceed &&
                !baseRepositoryEvents.IsNull()
            )
            {
                //
                baseRepositoryEvents
                    .UpdateEvent(new XBaseEventModel<T>(item));
            }

            //
            // Return result base on action Succeed ...
            return isSucceed ?
                item :
                null;
        }

        /// <summary>
        /// Update a range of Entities ...
        /// </summary>
        /// <param name="items"></param>
        /// <param name="saveChanges"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public async Task<bool> UpdateRangeAsync(
            IEnumerable<T> items,
            bool saveChanges = true,
            CancellationToken cancellationToken = default
        )
        {
            //
            var result = false;
            var isValid = !items.IsNull() && items.HasChild();
            if (!isValid)
            {
                return result;
            }

            //
            foreach (var item in items)
            {
                //
                var updated = await UpdateAsync(
                    item: item,
                    id: item.Id,
                    saveChanges: saveChanges,
                    cancellationToken: cancellationToken
                );
                if (!updated.IsNullOrDefault() && !result)
                {
                    result = true;
                }
            }

            //
            return result;
        }
        #endregion

        //
        #region Remove ...
        /// <summary>
        /// remove an Entity by it's Id ...
        /// </summary>
        /// <param name="id"></param>
        /// <param name="softDelete"></param>
        /// <param name="saveChanges"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public async Task<T> RemoveAsync(
            TKey id,
            bool softDelete = true,
            bool saveChanges = true,
            CancellationToken cancellationToken = default
        )
        {
            //
            // Retrieve Item ...
            var item = await GetAsync(
                id: id,
                ignoreSoftDeleteds: true,
                cancellationToken: cancellationToken
            );
            if (item.IsNull())
            {
                return null;
            }

            //
            // Filter ...
            var filter = Builders<T>.Filter.Eq(i => i.Id, id);

            //
            // Check SoftDelete ...
            if (softDelete && configuration.EnableSoftDelete)
            {
                //
                // Set Soft Delete ...
                item.Deleted = true;

                //
                // Update ...
                // Add Action model to Bulk Collection ...
                bulkCollection.Add(new ReplaceOneModel<T>(filter, item) { IsUpsert = true });
            }
            else
            {
                //
                // Delete ...
                // Add Action model to Bulk Collection ...
                bulkCollection.Add(new DeleteOneModel<T>(filter));
            }

            //
            // Check action is Succeeded or not ...
            var isSucceed = false;
            if (saveChanges)
            {
                //
                // Get Modified Count ...
                var qResult = await SaveChangesAsync(cancellationToken);

                //
                // set isSucceed Value based on Changes ...
                isSucceed = qResult > 0;
            }

            //
            // Notify Event ...
            if (
                isSucceed &&
                !baseRepositoryEvents.IsNull()
            )
            {
                //
                baseRepositoryEvents
                    .RemoveEvent(new XBaseEventModel<T>(item));
            }

            //
            // Return result base on action Succeed ...
            return isSucceed ?
                item :
                null;
        }

        /// <summary>
        /// remove an Entity ...
        /// </summary>
        /// <param name="item"></param>
        /// <param name="softDelete"></param>
        /// <param name="saveChanges"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public async Task<T> RemoveAsync(
            T item,
            bool softDelete = true,
            bool saveChanges = true,
            CancellationToken cancellationToken = default
        )
        {
            //
            var result = await RemoveAsync(
                id: item.Id,
                softDelete: softDelete,
                saveChanges: saveChanges,
                cancellationToken: cancellationToken
            );

            //
            return result;
        }

        /// <summary>
        /// remove a range of exists Entities ...
        /// </summary>
        /// <param name="items"></param>
        /// <param name="softDelete"></param>
        /// <param name="saveChanges"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public async Task RemoveRangeAsync(
            IEnumerable<T> items,
            bool softDelete = true,
            bool saveChanges = true,
            CancellationToken cancellationToken = default
        )
        {
            //
            // loop through items ...
            foreach (var item in items)
            {
                //
                // Filter ...
                var filter = Builders<T>.Filter.Eq(i => i.Id, item.Id);

                //
                // Check Soft Delete ...
                if (softDelete && configuration.EnableSoftDelete)
                {
                    //
                    // Set Soft Delete ...
                    item.Deleted = true;

                    //
                    // Update ...
                    // Add Action model to Bulk Collection ...
                    bulkCollection.Add(new ReplaceOneModel<T>(filter, item) { IsUpsert = true });
                }
                else
                {
                    //
                    // Delete ...
                    // Add Action model to Bulk Collection ...
                    bulkCollection.Add(new DeleteOneModel<T>(filter));
                }
            }

            //
            // Check action is Succeeded or not ...
            var isSucceed = false;
            if (saveChanges)
            {
                //
                // Get Modified Count ...
                var qResult = await SaveChangesAsync(cancellationToken);

                //
                // set isSucceed Value based on Changes ...
                isSucceed = qResult > 0;
            }

            //
            // Notify Event ...
            if (
                isSucceed &&
                !baseRepositoryEvents.IsNull()
            )
            {
                //
                baseRepositoryEvents
                    .RemoveManyEvent(new XBaseEventModel<IEnumerable<T>>(null));
            }
        }
        #endregion

        //
        #region Count ...
        /// <summary>
        /// count all exists Entities ...
        /// </summary>
        /// <param name="ignoreSoftDeleteds"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public async Task<int> CountAsync(
            bool ignoreSoftDeleteds = true,
            CancellationToken cancellationToken = default
        )
        {
            //
            // Prepare Ignore Soft Deleted Predicator ...
            Expression<Func<T, bool>> predicator = null;
            if (ignoreSoftDeleteds)
            {
                predicator = x => !x.Deleted;
            }
            var result = await AsQueryable(
                asNoTracking: true,
                orderBuilder: null,
                includeBuilder: null,
                predicate: predicator
            )
            .CountAsync(cancellationToken);

            //
            return result;
        }

        /// <summary>
        /// count all exists Entities Pages by providing page size ...
        /// </summary>
        /// <param name="pageSize"></param>
        /// <param name="totalItems"></param>
        /// <param name="ignoreSoftDeleteds"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public async Task<int> PagesCountAsync(
            int pageSize,
            int? totalItems = null,
            bool ignoreSoftDeleteds = true,
            CancellationToken cancellationToken = default
        )
        {
            //
            int count = totalItems.HasValue ? totalItems.Value : await CountAsync(
                cancellationToken: cancellationToken,
                ignoreSoftDeleteds: ignoreSoftDeleteds
            );
            int pagesCount = count / pageSize;

            //
            if (count % pageSize > 0)
            {
                pagesCount++;
            }

            //
            return pagesCount;
        }
        #endregion

        //
        #region Retrieve ...
        /// <summary>
        /// retrieve whole items as queryable ...
        /// </summary>
        /// <param name="asNoTracking">a flag for Tracking behaviour</param>
        /// <param name="predicate">an Expression for Filter Items ...</param>
        /// <param name="orderBuilder">an Order Builder expression for Ordering Query ...</param>
        /// <param name="includeBuilder">an Include Builder expression for Including Navigation Properties ...</param>
        /// <returns></returns>
        public IQueryable<T> AsQueryable(
            bool asNoTracking = true,
            Expression<Func<T, bool>> predicate = null,
            Func<IQueryable<T>, IOrderedQueryable<T>> orderBuilder = null,
            Func<IQueryable<T>, IIncludableQueryable<T, object>> includeBuilder = null
        )
        {
            //
            var result = collection
                .AsQueryable();

            //
            // Apply Predicate ...
            if (!predicate.IsNull())
            {
                result = result
                    .Where(predicate);
            }

            //
            // Apply Includes ...
            if (!includeBuilder.IsNull())
            {
                //
                // Since Mongo Queryable doesnt Support Includes ...
                // we ignore this ...
                result = (IMongoQueryable<T>)includeBuilder(result);
            }

            //
            // Apply Ordering ...
            if (!orderBuilder.IsNull())
            {
                result = (IMongoQueryable<T>)orderBuilder(result);
            }

            //
            return result;
        }

        /// <summary>
        /// retrieve an Entity by it's Id ...
        /// </summary>
        /// <param name="id"></param>
        /// <param name="ignoreSoftDeleteds"></param>
        /// <param name="includeBuilder"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public async Task<T> GetAsync(
            TKey id,
            bool ignoreSoftDeleteds = true,
            Func<IQueryable<T>, IIncludableQueryable<T, object>> includeBuilder = null,
            CancellationToken cancellationToken = default
        )
        {
            //
            // Prepare Ignore Soft Deleted Predicator ...
            Expression<Func<T, bool>> predicator = null;
            if (ignoreSoftDeleteds)
            {
                predicator = x => !x.Deleted;
            }
            var result = await AsQueryable(
                asNoTracking: true,
                orderBuilder: null,
                predicate: predicator,
                includeBuilder: includeBuilder
            )
            .Where(x => GetKey(x).ToString() == id.ToString())
            .FirstOrDefaultAsync(cancellationToken);

            //
            return result;
        }

        /// <summary>
        /// retrieve all exists Entities ...
        /// </summary>
        /// <param name="ignoreSoftDeleteds"></param>
        /// <param name="orderBuilder"></param>
        /// <param name="includeBuilder"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public async Task<IEnumerable<T>> GetAllAsync(
            bool ignoreSoftDeleteds = true,
            Func<IQueryable<T>, IOrderedQueryable<T>> orderBuilder = null,
            Func<IQueryable<T>, IIncludableQueryable<T, object>> includeBuilder = null,
            CancellationToken cancellationToken = default
        )
        {
            //
            // Prepare Ignore Soft Deleted Predicator ...
            Expression<Func<T, bool>> predicator = null;
            if (ignoreSoftDeleteds)
            {
                predicator = x => !x.Deleted;
            }
            var result = await AsQueryable(
                asNoTracking: true,
                predicate: predicator,
                orderBuilder: orderBuilder,
                includeBuilder: includeBuilder
            )
            .ToListAsync(cancellationToken);

            //
            return result;
        }

        /// <summary>
        /// retrieve all exists Entities
        /// as Async Enumerable ...
        /// </summary>
        /// <param name="ignoreSoftDeleteds"></param>
        /// <param name="orderBuilder"></param>
        /// <param name="includeBuilder"></param>
        /// <returns></returns>
        public IAsyncEnumerable<T> GetAllAsAsyncEnumerable(
            bool ignoreSoftDeleteds = true,
            Func<IQueryable<T>, IOrderedQueryable<T>> orderBuilder = null,
            Func<IQueryable<T>, IIncludableQueryable<T, object>> includeBuilder = null
        )
        {
            //
            // Prepare Ignore Soft Deleted Predicator ...
            Expression<Func<T, bool>> predicator = null;
            if (ignoreSoftDeleteds)
            {
                predicator = x => !x.Deleted;
            }
            var result = AsQueryable(
                asNoTracking: true,
                predicate: predicator,
                orderBuilder: orderBuilder,
                includeBuilder: includeBuilder
            )
            .AsAsyncEnumerable();

            //
            return result;

        }

        /// <summary>
        /// find an Entity by providing a Conditional Expression ...
        /// </summary>
        /// <param name="predicate"></param>
        /// <param name="ignoreSoftDeleteds"></param>
        /// <param name="includeBuilder"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public async Task<T> FindOneAsync(
            Expression<Func<T, bool>> predicate,
            bool ignoreSoftDeleteds = true,
            Func<IQueryable<T>, IIncludableQueryable<T, object>> includeBuilder = null,
            CancellationToken cancellationToken = default
        )
        {
            //
            // Prepare Ignore Soft Deleted Predicator ...
            Expression<Func<T, bool>> predicator = null;
            if (ignoreSoftDeleteds)
            {
                predicator = x => !x.Deleted;
            }
            var result = await AsQueryable(
                asNoTracking: true,
                orderBuilder: null,
                predicate: predicator,
                includeBuilder: includeBuilder
            )
            .Where(predicate)
            .FirstOrDefaultAsync(cancellationToken);

            //
            return result;
        }

        /// <summary>
        /// find a collection of Entities by proving a Conditional Expression ...
        /// </summary>
        /// <param name="predicate"></param>
        /// <param name="ignoreSoftDeleteds"></param>
        /// <param name="orderBuilder"></param>
        /// <param name="includeBuilder"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public async Task<IEnumerable<T>> FindManyAsync(
            Expression<Func<T, bool>> predicate,
            bool ignoreSoftDeleteds = true,
            Func<IQueryable<T>, IOrderedQueryable<T>> orderBuilder = null,
            Func<IQueryable<T>, IIncludableQueryable<T, object>> includeBuilder = null,
            CancellationToken cancellationToken = default
        )
        {
            //
            // Prepare Ignore Soft Deleted Predicator ...
            Expression<Func<T, bool>> predicator = null;
            if (ignoreSoftDeleteds)
            {
                predicator = x => !x.Deleted;
            }
            var result = await AsQueryable(
                asNoTracking: true,
                predicate: predicator,
                orderBuilder: orderBuilder,
                includeBuilder: includeBuilder
            )
            .Where(predicate)
            .ToListAsync(cancellationToken);

            //
            return result;
        }

        /// <summary>
        /// retrieve Entities based on XQuery Pagination structure ...
        /// </summary>
        /// <param name="query"></param>
        /// <param name="ignoreSoftDeleteds"></param>
        /// <param name="predicate"></param>
        /// <param name="orderBuilder"></param>
        /// <param name="includeBuilder"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public async Task<XQueryResult<T>> QueryAsync(
            XQuery query,
            bool ignoreSoftDeleteds = true,
            Expression<Func<T, bool>> predicate = null,
            Func<IQueryable<T>, IOrderedQueryable<T>> orderBuilder = null,
            Func<IQueryable<T>, IIncludableQueryable<T, object>> includeBuilder = null,
            CancellationToken cancellationToken = default
        )
        {
            //
            // Normalize Query ...
            query = query.NormalizeQuery(configuration);

            //
            var items = await GetAllAsync();
            var totalItemsCount = items.Count();

            //
            // Apply Filter ...
            if (!query.Filter.IsNullOrEmpty())
            {
                //
                items = items
                    .ApplyFilter(query.Filter);
            }
            int filteredItemsCount = items.Count();

            //
            // Count Pages ...
            var totalPagesCount = query.CountPages(totalItemsCount);
            var filteredPagesCount = query.CountPages(filteredItemsCount);

            //
            // Apply Paging and Sorting ...
            if (totalItemsCount > 0 &&
                filteredItemsCount > 0)
            {
                //
                // Apply Sorting ...
                items = items
                    .ToList()
                    .ApplySorting(
                        query.SortBy,
                        query.IsAscending
                    );

                //
                // Apply Paging ...
                items = items
                    .ToList()
                    .ApplyPaging(
                        query.Page,
                        query.PageSize
                    );
            }

            //
            // Prepare Result ...
            var result = new XQueryResult<T>
            {
                Page = query.Page,
                Items = items.ToList(),
                PageSize = query.PageSize,
                TotalPages = totalPagesCount,
                TotalItems = totalItemsCount,
                TotalFilteredPages = filteredPagesCount,
                TotalFilteredItems = filteredItemsCount
            };

            //
            return result;
        }
        #endregion

        //
        #region Exists ...
        /// <summary>
        /// Check an Entity exists or not ...
        /// </summary>
        /// <param name="id"></param>
        /// <param name="ignoreSoftDeleteds"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public async Task<bool> IsExistsAsync(
            TKey id,
            bool ignoreSoftDeleteds = true,
            CancellationToken cancellationToken = default
        )
        {
            //
            // Prepare Ignore Soft Deleted Predicator ...
            Expression<Func<T, bool>> predicator = null;
            if (ignoreSoftDeleteds)
            {
                predicator = x => !x.Deleted;
            }
            var result = await AsQueryable(
                asNoTracking: true,
                orderBuilder: null,
                includeBuilder: null,
                predicate: predicator
            )
            .AnyAsync(
                cancellationToken: cancellationToken,
                predicate: x => GetKey(x).ToString() == id.ToString());

            //
            return result;
        }
        #endregion

        //
        #region Unit Of Work ...
        /// <summary>
        /// Save all unsaved Transactions on DbContext ...
        /// used fo Unit Of Works Design Pattern ...
        /// </summary>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public async Task<int> SaveChangesAsync(
            CancellationToken cancellationToken = default
        )
        {
            //
            try
            {
                //  
                // Write all Bulk Models which stored inside bulkCollection ...               
                var result = await collection
                    .BulkWriteAsync(
                        options: null,
                        requests: bulkCollection,
                        cancellationToken: cancellationToken
                );

                //
                // Clear Bulk Collection ...
                bulkCollection.Clear();

                //
                // Return number of Modified Documents ...
                var resultCount = (int)result.ModifiedCount +
                    (int)result.InsertedCount +
                    (int)result.DeletedCount;

                //
                return resultCount;
            }
            catch (Exception ex)
            {
                //
                // Log Thrown Exception ...
                Console.WriteLine($"XMongo Repository Exception: {ex.Message} ...");

                //
                // Return less than zero value ...
                return -1;
            }
        }
        #endregion

        //
        #region Key ...
        /// <summary>
        /// Retrieve Key of Entity ...
        /// </summary>
        /// <param name="item"></param>
        /// <returns></returns>
        public TKey GetKey(T item)
        {
            //
            var props = item.GetType().GetProperties();
            var keyProp = props.FirstOrDefault(p => p.Name == "Id");

            //
            var keyString = string.Empty;
            if (keyProp.IsNull())
            {
                keyString = string.Empty;
            }
            else
            {
                keyString = keyProp.GetValue(item).ToString();
            }

            //
            if (keyString.IsNullOrEmpty())
            {
                return default(TKey);
            }

            //
            // Prevent Deserializing issues throug JsonReader ...
            if (keyString.IsGuid() && typeof(TKey) == typeof(Guid))
            {
                return item.Id;
            }

            //
            return keyString.FromJSON<TKey>();
        }

        /// <summary>
        /// Set Key of Entity ...
        /// </summary>
        /// <param name="item"></param>
        /// <param name="id"></param>
        public void SetKey(
            ref T item,
            TKey id
        )
        {
            //
            var props = item.GetType().GetProperties();
            var keyProp = props.FirstOrDefault(p => p.Name == "Id");
            if (keyProp.IsNull())
            {
                return;
            }

            //
            Type t = Nullable.GetUnderlyingType(keyProp.PropertyType) ?? keyProp.PropertyType;
            object safeValue = (id == null) ? null : Convert.ChangeType(id, t);
            keyProp.SetValue(item, safeValue, null);
        }

        /// <summary>
        /// Handle Checking Key ...
        /// </summary>
        /// <param name="item"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public async Task<T> HandleKeyAsync(
            T item,
            CancellationToken cancellationToken = default
        )
        {
            //
            var keyType = typeof(TKey);

            //
            // Handle Guid Key Type ...
            // Since EFCore has AutoIncrement on int Ids, there is no need to handle int Key types ...
            if (
                (
                    keyType == typeof(Guid) ||
                    keyType == typeof(string)
                ) &&
                keyGenerator.IsEmpty(item.Id)
            )
            {
                //
                var newKey = await keyGenerator.GenerateKey(this);

                //
                SetKey(ref item, newKey);
            }

            //
            return item;
        }
        #endregion

        //
        #region Detach ...
        /// <summary>
        /// Detach an Entity ...
        /// </summary>
        /// <param name="item"></param>
        public void Detach(T item) { }

        /// <summary>
        /// Detach an Enumerable of Entities ...
        /// </summary>
        /// <param name="items"></param>
        public void Detach(IEnumerable<T> items) { }

        /// <summary>
        /// Detach a Query Result of Entity ...
        /// </summary>
        /// <param name="query"></param>
        public void Detach(XQueryResult<T> query) { }
        #endregion
        #endregion

        //
        #region Others ...
        public void Dispose() { }

        public string GetPropValues(T item)
        {
            //
            var props = item.GetType().GetProperties();
            var vals = props.Select(p => p.GetValue(p.Name));

            //
            return vals.ToJSON();
        }
        #endregion

        //
        #region Private ...
        #endregion
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xDataService\Providers\XBaseRepositoryEvents.cs

using System;
using System.Collections.Generic;
using System.Reactive.Linq;
using System.Reactive.Subjects;
using xDataService.Interfaces;
using xDataService.Models;

namespace xDataService.Providers {
    /// <summary>
    /// Some Events can be Raised on Some Actions Happens on Repositories ...
    /// this is the Base Events Class ...
    /// </summary>
    /// <typeparam name="T"></typeparam>
    public abstract class XBaseRepositoryEvents<T> : IXBaseRepositoryEvents<T> {
        //
        private readonly ISubject<XBaseEventModel<T>> onAddSubject;
        private readonly ISubject<XBaseEventModel<T>> onUpdateSubject;
        private readonly ISubject<XBaseEventModel<T>> onRemoveSubject;

        //
        private readonly ISubject<XBaseEventModel<IEnumerable<T>>> onAddManySubject;
        private readonly ISubject<XBaseEventModel<IEnumerable<T>>> onUpdateManySubject;
        private readonly ISubject<XBaseEventModel<IEnumerable<T>>> onRemoveManySubject;

        //
        protected XBaseRepositoryEvents () {
            //
            onAddSubject = new ReplaySubject<XBaseEventModel<T>> (1);
            onUpdateSubject = new ReplaySubject<XBaseEventModel<T>> (1);
            onRemoveSubject = new ReplaySubject<XBaseEventModel<T>> (1);

            //
            onAddManySubject = new ReplaySubject<XBaseEventModel<IEnumerable<T>>> (1);
            onUpdateManySubject = new ReplaySubject<XBaseEventModel<IEnumerable<T>>> (1);
            onRemoveManySubject = new ReplaySubject<XBaseEventModel<IEnumerable<T>>> (1);
        }

        //
        public void AddEvent (XBaseEventModel<T> model) => onAddSubject.OnNext (model);

        public void UpdateEvent (XBaseEventModel<T> model) => onUpdateSubject.OnNext (model);

        public void RemoveEvent (XBaseEventModel<T> model) => onRemoveSubject.OnNext (model);

        //
        public void AddManyEvent (XBaseEventModel<IEnumerable<T>> model) => onAddManySubject.OnNext (model);
        public void UpdateManyEvent (XBaseEventModel<IEnumerable<T>> model) => onUpdateManySubject.OnNext (model);
        public void RemoveManyEvent (XBaseEventModel<IEnumerable<T>> model) => onRemoveManySubject.OnNext (model);

        //
        public IObservable<XBaseEventModel<T>> OnAddObservable => onAddSubject.AsObservable ();

        public IObservable<XBaseEventModel<T>> OnUpdateObservable => onUpdateSubject.AsObservable ();

        public IObservable<XBaseEventModel<T>> OnRemoveObservable => onRemoveSubject.AsObservable ();

        //
        public IObservable<XBaseEventModel<IEnumerable<T>>> OnAddManyObservable => onAddManySubject.AsObservable ();
        public IObservable<XBaseEventModel<IEnumerable<T>>> OnUpdateManyObservable => onUpdateManySubject.AsObservable ();
        public IObservable<XBaseEventModel<IEnumerable<T>>> OnRemoveManyObservable => onRemoveManySubject.AsObservable ();

    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xDataService\Providers\XBaseRepositoryService.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Runtime.CompilerServices;
using System.Threading;
using System.Threading.Tasks;
using AutoMapper;
using Microsoft.EntityFrameworkCore.Query;
using xCommons.Extensions;
using xDataService.Interfaces;
using xModels.Base;
using xModels.Dtos;

namespace xDataService.Providers
{
    /// <summary>
    /// a Base Repository Service Implementation which Use a Repository Patterns Implementatin 
    /// and provides Data Manipulation Methods using Dtos instead of Entities ...
    /// 
    /// it can be use of following Repository Patterns Implementation:
    /// <see cref="XBaseEFRepository"/>>
    /// <see cref="XBaseMongoRepository"/>>
    /// <see cref="XBaseInMemoryRepository"/>>
    /// </summary>
    /// <typeparam name="TEntity"></typeparam>
    /// <typeparam name="TDto"></typeparam>
    /// <typeparam name="TKey"></typeparam>
    public abstract class XBaseRepositoryService<TEntity, TDto, TKey> : IXBaseRepositoryService<TEntity, TDto, TKey>
    where TEntity : XBaseEntity<TKey>
    where TDto : XBaseEntityDto<TKey>
    {
        //
        #region Properties ...
        /// <summary>
        /// Mapper Instance ...
        /// </summary>
        public IMapper Mapper { get; }

        /// <summary>
        /// Repository Implementation for Data Manipulations ...
        /// </summary>
        public IXBaseRepository<TEntity, TKey> Repository { get; }

        /// <summary>
        /// Mapping Profile Configuration ...
        /// 
        /// this Configuration used for Mapping TEntity to Dto and reverse ...
        /// default mapping prepared on Constructing time, other custom maps
        /// must handled manually if required ...
        /// </summary>
        public MapperConfiguration MapperConfiguration { get; }
        #endregion

        //
        #region Constructor ...
        public XBaseRepositoryService(
            IXBaseRepository<TEntity, TKey> repository,
            IEnumerable<Profile> mapperProfiles = null
        )
        {
            //
            Repository = repository;

            //
            // Preparing Mapping Configurations ...
            MapperConfiguration = new MapperConfiguration(cfg =>
            {
                //
                // Add Default Profiles ...

                //
                // Entity To Dto ...
                cfg.CreateMap<TEntity, TDto>()
                    .ForMember(dest => dest.Deleted, opt => opt.Ignore());
                cfg.CreateMap<XQueryResult<TEntity>, XQueryResult<TDto>>();

                //
                // Dto to Entity ...
                cfg.CreateMap<TDto, TEntity>()
                    .ForMember(dest => dest.Deleted, opt => opt.Ignore());
                cfg.CreateMap<XQueryResult<TDto>, XQueryResult<TEntity>>();

                //
                // Add Provided Profiles if Provided ...
                // if Same Profiles Provided, here resolved ...
                if (!mapperProfiles.IsNull() &&
                    mapperProfiles.HasChild())
                {
                    cfg.AddProfiles(mapperProfiles);
                }
            });

            //
            // Make Mapper Instance using prepared Configuration ...
            Mapper = MapperConfiguration.CreateMapper();
        }
        #endregion

        //
        #region Actions ...
        //
        #region Add ...
        /// <summary>
        /// add a new Dto ...
        /// </summary>
        /// <param name="item"></param>
        /// <param name="saveChanges"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public async Task<TDto> AddAsync(
            TDto item,
            bool saveChanges = true,
            CancellationToken cancellationToken = default
        )
        {
            //
            TDto result = null;

            //
            // Validate ...
            bool isValid = !item.IsNull();
            if (!isValid)
            {
                return result;
            }

            //
            try
            {
                //
                var entity = Mapper.Map<TEntity>(item);

                //
                entity = await Repository.AddAsync(
                    item: entity,
                    saveChanges: saveChanges,
                    cancellationToken: cancellationToken
                );

                //
                result = Mapper.Map<TDto>(entity);
            }
            catch
            { }

            //
            return result;
        }

        /// <summary>
        /// add or update a Dto (add if not exists/update if exists) ...
        /// </summary>
        /// <param name="item"></param>
        /// <param name="saveChanges"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public async Task<TDto> AddOrUpdateAsync(
            TDto item,
            bool saveChanges = true,
            CancellationToken cancellationToken = default
        )
        {
            //
            TDto result = null;

            //
            // Validate ...
            bool isValid = !item.IsNull();
            if (!isValid)
            {
                return result;
            }

            //
            try
            {
                //
                var entity = Mapper.Map<TEntity>(item);

                //
                entity = await Repository.AddOrUpdateAsync(
                    item: entity,
                    saveChanges: saveChanges,
                    cancellationToken: cancellationToken
                );

                //
                result = Mapper.Map<TDto>(entity);
            }
            catch
            { }

            //
            return result;
        }

        /// <summary>
        /// add a range of new Dtos ...
        /// </summary>
        /// <param name="items"></param>
        /// <param name="saveChanges"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public async Task AddRangeAsync(
            IEnumerable<TDto> items,
            bool saveChanges = true,
            CancellationToken cancellationToken = default
        )
        {
            //
            TDto result = null;

            //
            // Validate ...
            bool isValid =
                !items.IsNull() &&
                items.HasChild();
            if (!isValid)
            {
                return;
            }

            //
            try
            {
                //
                var entities = Mapper.Map<IEnumerable<TEntity>>(items);

                //
                await Repository.AddRangeAsync(
                    items: entities,
                    saveChanges: saveChanges,
                    cancellationToken: cancellationToken
                );
            }
            catch
            { }
        }
        #endregion

        //
        #region Update ...
        /// <summary>
        /// Update an Dto values ...
        /// </summary>
        /// <param name="id"></param>
        /// <param name="item"></param>
        /// <param name="saveChanges"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public async Task<TDto> UpdateAsync(
            TKey id,
            TDto item,
            bool saveChanges = true,
            CancellationToken cancellationToken = default
        )
        {
            //
            TDto result = null;

            //
            try
            {
                //
                var entity = Mapper.Map<TEntity>(item);

                //
                entity = await Repository.UpdateAsync(
                    id: item.Id,
                    item: entity,
                    saveChanges: saveChanges,
                    cancellationToken: cancellationToken
                );

                //
                result = Mapper.Map<TDto>(entity);
            }
            catch
            { }

            //
            return result;
        }

        /// <summary>
        /// Update a range of Dtos ...
        /// </summary>
        /// <param name="items"></param>
        /// <param name="saveChanges"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public async Task<bool> UpdateRangeAsync(
            IEnumerable<TDto> items,
            bool saveChanges = true,
            CancellationToken cancellationToken = default
        )
        {
            //
            // Validate ...
            var result =
                !items.IsNull() &&
                items.HasChild();
            if (!result)
            {
                return result;
            }

            //
            try
            {
                //
                var entitis = Mapper.Map<IEnumerable<TEntity>>(items);

                //
                result = await Repository.UpdateRangeAsync(
                    items: entitis,
                    saveChanges: saveChanges,
                    cancellationToken: cancellationToken
                );
            }
            catch
            {
                result = false;
            }

            //
            return result;
        }
        #endregion

        //
        #region Remove ...
        /// <summary>
        /// remove an Dto by it's Id ...
        /// </summary>
        /// <param name="id"></param>
        /// <param name="softDelete"></param>
        /// <param name="saveChanges"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public async Task<TDto> RemoveAsync(
            TKey id,
            bool softDelete = true,
            bool saveChanges = true,
            CancellationToken cancellationToken = default
        )
        {
            //
            TDto result = null;

            //
            try
            {
                //
                var entity = await Repository.RemoveAsync(
                    id: id,
                    softDelete: softDelete,
                    saveChanges: saveChanges,
                    cancellationToken: cancellationToken
                );

                //
                result = Mapper.Map<TDto>(entity);
            }
            catch
            { }

            //
            return result;
        }

        /// <summary>
        /// remove an Dto ...
        /// </summary>
        /// <param name="item"></param>
        /// <param name="softDelete"></param>
        /// <param name="saveChanges"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public async Task<TDto> RemoveAsync(
            TDto item,
            bool softDelete = true,
            bool saveChanges = true,
            CancellationToken cancellationToken = default
        )
        {
            //
            TDto result = null;

            //
            try
            {
                //
                var entity = Mapper.Map<TEntity>(item);

                //
                entity = await Repository.RemoveAsync(
                    item: entity,
                    softDelete: softDelete,
                    saveChanges: saveChanges,
                    cancellationToken: cancellationToken
                );

                //
                result = Mapper.Map<TDto>(entity);
            }
            catch
            { }

            //
            return result;
        }

        /// <summary>
        /// remove a range of exists Dtos ...
        /// </summary>
        /// <param name="items"></param>
        /// <param name="softDelete"></param>
        /// <param name="saveChanges"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public async Task RemoveRangeAsync(
            IEnumerable<TDto> items,
            bool softDelete = true,
            bool saveChanges = true,
            CancellationToken cancellationToken = default
        )
        {
            //
            // Validate ...
            var isValid =
                !items.IsNull() &&
                items.HasChild();
            if (!isValid)
            {
                return;
            }

            //
            var entities = Mapper.Map<IEnumerable<TEntity>>(items);

            //
            try
            {
                //
                await Repository.RemoveRangeAsync(
                    items: entities,
                    softDelete: softDelete,
                    saveChanges: saveChanges,
                    cancellationToken: cancellationToken
                );
            }
            catch
            { }
        }
        #endregion

        //
        #region Count ...
        /// <summary>
        /// count all exists Dtos ...
        /// </summary>
        /// <param name="ignoreSoftDeleteds"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public async Task<int> CountAsync(
            bool ignoreSoftDeleteds = true,
            CancellationToken cancellationToken = default
        )
        {
            //
            var result = await Repository.CountAsync(
                cancellationToken: cancellationToken,
                ignoreSoftDeleteds: ignoreSoftDeleteds
            );

            //
            return result;
        }

        /// <summary>
        /// count all exists Entities Pages by providing page size ...
        /// </summary>
        /// <param name="pageSize"></param>
        /// <param name="totalItems"></param>
        /// <param name="ignoreSoftDeleteds"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public async Task<int> PagesCountAsync(
            int pageSize,
            int? totalItems = null,
            bool ignoreSoftDeleteds = true,
            CancellationToken cancellationToken = default
        )
        {
            //
            var result = await Repository.PagesCountAsync(
                pageSize: pageSize,
                totalItems: totalItems,
                cancellationToken: cancellationToken,
                ignoreSoftDeleteds: ignoreSoftDeleteds
            );

            //
            return result;
        }
        #endregion

        //
        #region Exists ...
        /// <summary>
        /// Check a Dto exists or not ...
        /// </summary>
        /// <param name="id"></param>
        /// <param name="ignoreSoftDeleteds"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public async Task<bool> IsExistsAsync(
            TKey id,
            bool ignoreSoftDeleteds = true,
            CancellationToken cancellationToken = default
        )
        {
            //
            var result = await Repository.IsExistsAsync(
                id: id,
                cancellationToken: cancellationToken,
                ignoreSoftDeleteds: ignoreSoftDeleteds
            );

            //
            return result;
        }
        #endregion

        //
        #region Retrieve ...
        /// <summary>
        /// retrieve an Dto by it's Id ...
        /// </summary>
        /// <param name="id"></param>
        /// <param name="ignoreSoftDeleteds"></param>
        /// <param name="includeBuilder"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public async Task<TDto> GetAsync(
            TKey id,
            bool ignoreSoftDeleteds = true,
            Func<IQueryable<TEntity>, IIncludableQueryable<TEntity, object>> includeBuilder = null,
            CancellationToken cancellationToken = default
        )
        {
            //
            TDto result = null;

            //
            try
            {
                //
                var entity = await Repository.GetAsync(
                    id: id,
                    includeBuilder: includeBuilder,
                    cancellationToken: cancellationToken,
                    ignoreSoftDeleteds: ignoreSoftDeleteds
                );

                //
                result = Mapper.Map<TDto>(entity);
            }
            catch
            { }

            //
            return result;
        }

        /// <summary>
        /// retrieve all exists Dtos ...
        /// </summary>
        /// <param name="ignoreSoftDeleteds"></param>
        /// <param name="orderBuilder"></param>
        /// <param name="includeBuilder"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public async Task<IEnumerable<TDto>> GetAllAsync(
            bool ignoreSoftDeleteds = true,
            Func<IQueryable<TEntity>, IOrderedQueryable<TEntity>> orderBuilder = null,
            Func<IQueryable<TEntity>, IIncludableQueryable<TEntity, object>> includeBuilder = null,
            CancellationToken cancellationToken = default
        )
        {
            //
            IEnumerable<TDto> result = Enumerable.Empty<TDto>();

            //
            try
            {
                //
                var entities = await Repository.GetAllAsync(
                    orderBuilder: orderBuilder,
                    includeBuilder: includeBuilder,
                    cancellationToken: cancellationToken,
                    ignoreSoftDeleteds: ignoreSoftDeleteds
                );

                //
                result = Mapper.Map<IEnumerable<TDto>>(entities);
            }
            catch
            { }

            //
            return result;
        }

        /// <summary>
        /// retrieve all exists Dtos
        /// as Async Enumerable ...
        /// </summary>
        /// <param name="ignoreSoftDeleteds"></param>
        /// <param name="orderBuilder"></param>
        /// <param name="includeBuilder"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public async IAsyncEnumerable<TDto> GetAllAsAsyncEnumerable(
            bool ignoreSoftDeleteds = true,
            Func<IQueryable<TEntity>, IOrderedQueryable<TEntity>> orderBuilder = null,
            Func<IQueryable<TEntity>, IIncludableQueryable<TEntity, object>> includeBuilder = null,
            [EnumeratorCancellation] CancellationToken cancellationToken = default
        )
        {
            //
            var entityEnumerable = Repository.GetAllAsAsyncEnumerable(
                orderBuilder: orderBuilder,
                includeBuilder: includeBuilder,
                ignoreSoftDeleteds: ignoreSoftDeleteds
            );
            await foreach (var entity in entityEnumerable)
            {
                //
                if (cancellationToken.IsCancellationRequested)
                {
                    yield break;
                }

                //
                var dto = Mapper.Map<TDto>(entity);
                yield return dto;
            }
        }

        /// <summary>
        /// find an Dto by providing a Conditional Expression ...
        /// </summary>
        /// <param name="predicate"></param>
        /// <param name="ignoreSoftDeleteds"></param>
        /// <param name="includeBuilder"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public async Task<TDto> FindOneAsync(
            Expression<Func<TEntity, bool>> predicate,
            bool ignoreSoftDeleteds = true,
            Func<IQueryable<TEntity>, IIncludableQueryable<TEntity, object>> includeBuilder = null,
            CancellationToken cancellationToken = default
        )
        {
            //
            TDto result = null;

            //
            try
            {
                //
                var entity = await Repository.FindOneAsync(
                    predicate: predicate,
                    includeBuilder: includeBuilder,
                    cancellationToken: cancellationToken,
                    ignoreSoftDeleteds: ignoreSoftDeleteds
                );

                //
                result = Mapper.Map<TDto>(entity);
            }
            catch
            { }

            //
            return result;
        }

        /// <summary>
        /// find a collection of Dtos by proving a Conditional Expression ...
        /// </summary>
        /// <param name="predicate"></param>
        /// <param name="ignoreSoftDeleteds"></param>
        /// <param name="orderBuilder"></param>
        /// <param name="includeBuilder"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public async Task<IEnumerable<TDto>> FindManyAsync(
            Expression<Func<TEntity, bool>> predicate,
            bool ignoreSoftDeleteds = true,
            Func<IQueryable<TEntity>, IOrderedQueryable<TEntity>> orderBuilder = null,
            Func<IQueryable<TEntity>, IIncludableQueryable<TEntity, object>> includeBuilder = null,
            CancellationToken cancellationToken = default
        )
        {
            //
            IEnumerable<TDto> result = Enumerable.Empty<TDto>();

            //
            try
            {
                //
                var entities = await Repository.FindManyAsync(
                    predicate: predicate,
                    orderBuilder: orderBuilder,
                    includeBuilder: includeBuilder,
                    cancellationToken: cancellationToken,
                    ignoreSoftDeleteds: ignoreSoftDeleteds
                );

                //
                result = Mapper.Map<IEnumerable<TDto>>(entities);
            }
            catch
            { }

            //
            return result;
        }

        /// <summary>
        /// retrieve Dtos based on XQuery Pagination structure ...
        /// </summary>
        /// <param name="query"></param>
        /// <param name="ignoreSoftDeleteds"></param>
        /// <param name="predicate"></param>
        /// <param name="orderBuilder"></param>
        /// <param name="includeBuilder"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public async Task<XQueryResult<TDto>> QueryAsync(
            XQuery query,
            bool ignoreSoftDeleteds = true,
            Expression<Func<TEntity, bool>> predicate = null,
            Func<IQueryable<TEntity>, IOrderedQueryable<TEntity>> orderBuilder = null,
            Func<IQueryable<TEntity>, IIncludableQueryable<TEntity, object>> includeBuilder = null,
            CancellationToken cancellationToken = default
        )
        {
            //
            XQueryResult<TDto> result = null;

            //
            try
            {
                //
                var entityResult = await Repository.QueryAsync(
                    query: query,
                    predicate: predicate,
                    orderBuilder: orderBuilder,
                    includeBuilder: includeBuilder,
                    cancellationToken: cancellationToken,
                    ignoreSoftDeleteds: ignoreSoftDeleteds
                );

                //
                result = Mapper.Map<XQueryResult<TDto>>(entityResult);
            }
            catch
            { }

            //
            return result;
        }
        #endregion

        public virtual void Dispose()
        { }
        #endregion
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xDataService\Providers\XEntityRegisterarHandlerService.cs

using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Reflection;
using Microsoft.EntityFrameworkCore;
using xCommons.Extensions;
using xDataService.Interfaces;

namespace xDataService.Providers
{
    public class XEntityRegisterarHandlerService
    {
        /// <summary>
        /// a Collection for Extract Registerars Services ...
        /// </summary>
        private readonly List<IXEntityRegisterar> registerars = [];

        /// <summary>
        /// a Collection for Holding all Entity Types ...
        /// </summary>
        public IReadOnlyList<Type> AllEntityTypes { get; private set; }

        /// <summary>
        /// Retrieve Specified Registerars Entity Types ...
        /// </summary>
        /// <param name="names"></param>
        /// <returns></returns>
        public IReadOnlyList<Type> GetEntityTypes(string[] names = null)
        {
            //
            var items = new List<Type>();

            //
            if (!names.IsNull() && names.HasChild())
            {
                //
                items = [.. registerars
                    .Where(r => names.Contains(r.Name))
                    .SelectMany(r => r.GetEntityTypes())];
            }

            //
            return items.AsReadOnly();
        }

        /// <summary>
        /// Load all Dynamically Registered Entities ...
        /// </summary>
        public void HandleRegisteredEntities()
        {
            //
            var entityTypes = new List<Type>();
            // path = Path.Combine (Directory.GetCurrentDirectory ());
            var path = Path.Combine (AppContext.BaseDirectory);
            var files = Directory.GetFiles(path, "*.dll");
            foreach (var dll in files)
            {
                //
                // Retrieve DLL Assembly ...
                var assembly = Assembly.LoadFrom(dll);

                //
                // Extract Registerar Types ...
                var registerarTypes = assembly
                    .GetExportedTypes()
                    .Where(t =>
                        !t.IsAbstract &&
                        typeof(IXEntityRegisterar).IsAssignableFrom(t));
                foreach (var registerarType in registerarTypes)
                {
                    //
                    // Create Instance of Registerar Type ...
                    var registerar = (IXEntityRegisterar)Activator.CreateInstance(registerarType);
                    if (!registerar.IsNull())
                    {
                        //
                        // Add Registerar Instance to Collection ...
                        registerars.Add(registerar);

                        //
                        // Add Registerar Provided Entities to Collection ...
                        entityTypes.AddRange(registerar.GetEntityTypes());
                    }
                }

                //
                // Converts to Readonly List ...
                AllEntityTypes = entityTypes.AsReadOnly();
            }
        }

        /// <summary>
        /// Configure all Dynamically Registered Entities ...
        /// </summary>
        /// <param name="modelBuilder"></param>
        /// <param name="names"></param>
        public void HandleApplyRegisteredEntitiesConfigurations(
            ModelBuilder modelBuilder,
            string[] names = null
        )
        {
            //
            var selectedRegisterars = 
                !names.IsNull() &&
                names.HasChild()
                ? registerars
                    .Where(r => names.Contains(r.Name))
                : registerars;

            //
            // Loop Through Extracted Registerars ... 
            foreach(var registerar in selectedRegisterars)
            {
                //
                // Configure Specified Registerars Entities ...
                registerar.ConfigureEntities(modelBuilder);
            }
        }
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xDataService\Providers\XGuidKeyGenerator.cs

using System;
using System.Threading;
using System.Threading.Tasks;
using xCommons.Extensions;
using xDataService.Interfaces;
using xModels.Base;

namespace xDataService.Providers
{
    /// <summary>
    /// Default Guid Key Generator ...
    /// </summary>
    /// <typeparam name="TEntity"></typeparam>
    public class XGuidKeyGenerator<TEntity> : XKeyGenerator<TEntity, Guid>, IXKeyGenerator<TEntity, Guid>
    where TEntity : XBaseEntity<Guid>
    {
        private readonly IXSequentialGuid sequentialGuid;

        public XGuidKeyGenerator(
            IXSequentialGuid sequentialGuid = null
        )
        {
            this.sequentialGuid = sequentialGuid;
        }

        public override async Task<Guid> GenerateKey(
            IXBaseRepository<TEntity, Guid> repository,
            CancellationToken cancellationToken = default
        )
        {
            //
            return await Task.Run(() =>
            {
                //
                // Check if provided SequentialGuid ...
                if (sequentialGuid.IsNull())
                {
                    return Guid.NewGuid();
                }
                else
                {
                    return sequentialGuid.Next();
                }
            }, cancellationToken: cancellationToken);
        }

        public override bool IsEmpty(Guid id)
        {
            //
            var result = id.IsNull() || id.IsDefaultGuid();

            //
            return result;
        }
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xDataService\Providers\XIntKeyGenerator.cs

using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using xCommons.Extensions;
using xDataService.Extensions;
using xDataService.Interfaces;
using xModels.Base;

namespace xDataService.Providers
{
    /// <summary>
    /// Default Int Key Generator ...
    /// </summary>
    /// <typeparam name="TEntity"></typeparam>
    public class XIntKeyGenerator<TEntity> : XKeyGenerator<TEntity, int>, IXKeyGenerator<TEntity, int>
    where TEntity : XBaseEntity<int>
    {
        public override async Task<int> GenerateKey(
            IXBaseRepository<TEntity, int> repository,
            CancellationToken cancellationToken = default
        )
        {
            //
            var items = (await repository.GetAllAsync())
                .OrderByDescending(nameof(XBaseEntity<int>.Id));
            var last = items
                .FirstOrDefault();

            //
            var result = last.IsNull() ? 1 : last.Id + 1;

            //
            return result;
        }

        public override bool IsEmpty(int id)
        {
            //
            var result = id <= 0;

            //
            return result;
        }
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xDataService\Providers\XKeyGenerator.cs

using System.Threading;
using System.Threading.Tasks;
using xDataService.Interfaces;
using xModels.Base;

namespace xDataService.Providers
{
    public abstract class XKeyGenerator<TEntity, TKey> : IXKeyGenerator<TEntity, TKey>
    where TEntity : XBaseEntity<TKey>
    {
        public abstract Task<TKey> GenerateKey(
            IXBaseRepository<TEntity, TKey> repository, 
            CancellationToken cancellationToken = default
        );

        public abstract bool IsEmpty(TKey id);
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xDataService\Providers\XLongKeyGenerator.cs

using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using xCommons.Extensions;
using xDataService.Extensions;
using xDataService.Interfaces;
using xModels.Base;

namespace xDataService.Providers
{
    /// <summary>
    /// Default Long Key Generator ...
    /// </summary>
    /// <typeparam name="TEntity"></typeparam>    
    public class XLongKeyGenerator<TEntity> : XKeyGenerator<TEntity, long>, IXKeyGenerator<TEntity, long>
    where TEntity : XBaseEntity<long>
    {
        public override async Task<long> GenerateKey(
            IXBaseRepository<TEntity, long> repository,
            CancellationToken cancellationToken = default
        )
        {
            //
            var items = (await repository.GetAllAsync())
                .OrderByDescending(nameof(XBaseEntity<long>.Id));
            var last = items
                .FirstOrDefault();

            //
            var result = last.IsNull() ? 1 : last.Id + 1;

            //
            return result;
        }

        public override bool IsEmpty(long id)
        {
            //
            var result = id <= 0;

            //
            return result;
        }
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xDataService\Providers\XSequentialGuid.cs

using System;
using xDataService.Interfaces;

namespace xDataService.Helpers
{
    /// <summary>
    /// this service provide Sequential GUID mechanism for Entity Ids ...
    /// </summary>
    public class XSequentialGuid : IXSequentialGuid
    {
        private static int[] sqlOrderMap = null;
        private static int[] SQLORDERMAP
        {
            get
            {
                if (sqlOrderMap == null)
                {
                    sqlOrderMap = new int[16] {
                    3,
                    2,
                    1,
                    0,
                    5,
                    4,
                    7,
                    6,
                    9,
                    8,
                    15,
                    14,
                    13,
                    12,
                    11,
                    10
                    };
                    // 3 - the least significant byte in Guid ByteArray [for SQL Server ORDER BY clause]
                    // 10 - the most significant byte in Guid ByteArray [for SQL Server ORDERY BY clause]
                }
                return sqlOrderMap;
            }
        }

        private Guid currentGuid;

        public XSequentialGuid()
        {
            currentGuid = Guid.NewGuid();
        }

        public Guid GetCurrentGuid()
        {
            return currentGuid;
        }

        public Guid Next()
        {
            byte[] bytes = currentGuid.ToByteArray();
            for (int mapIndex = 0; mapIndex < 16; mapIndex++)
            {
                int bytesIndex = SQLORDERMAP[mapIndex];
                bytes[bytesIndex]++;
                if (bytes[bytesIndex] != 0)
                {
                    break; // No need to increment more significant bytes
                }
            }
            currentGuid = new Guid(bytes);
            return currentGuid;
        }
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xDataService\Providers\XStringKeyGenerator.cs

using System;
using System.Threading;
using System.Threading.Tasks;
using xCommons.Extensions;
using xDataService.Interfaces;
using xModels.Base;

namespace xDataService.Providers
{
    /// <summary>
    /// Default Guid Key Generator ...
    /// </summary>
    /// <typeparam name="TEntity"></typeparam>

    public class XStringKeyGenerator<TEntity> : XKeyGenerator<TEntity, string>, IXKeyGenerator<TEntity, string>
    where TEntity : XBaseEntity<string>
    {
        private readonly IXSequentialGuid sequentialGuid;

        public XStringKeyGenerator(IXSequentialGuid sequentialGuid = null)
        {
            this.sequentialGuid = sequentialGuid;
        }

        public override async Task<string> GenerateKey(
            IXBaseRepository<TEntity, string> repository,
            CancellationToken cancellationToken = default
        )
        {
            //
            await Task.CompletedTask;

            //
            if (sequentialGuid.IsNull())
            {
                return Guid.NewGuid().ToString();
            }
            else
            {
                return sequentialGuid.Next().ToString();
            }
        }

        public override bool IsEmpty(string id)
        {
            return id.IsNullOrEmpty();
        }
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xEventService\Base\XBaseEvent.cs

using System;

namespace xEventService.Base {
    public abstract class XBaseEvent {
        public string Type { get; protected set; }
        public DateTime Timestamp { get; protected set; }

        protected XBaseEvent () {
            //
            Type = GetType ().Name;
            Timestamp = DateTime.UtcNow;
        }
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xEventService\Configuration\XEventServiceConfiguration.cs

using System.Collections.Generic;
using RabbitMQ.Client;

namespace xEventService.Configuration {
    /// <summary>
    /// a configuration class for describing how to connect rabbit mq server
    /// and how channels must be declared ...
    /// </summary>
    public class XEventServiceConfiguration {
        public string Server { get; set; }
        public int Port { get; set; }
        public string Username { get; set; }
        public string Password { get; set; }

        //
        public bool AllowDynamicQueues { get; set; } = true;
        public XQueueArgs DefaultQueueArgs { get; set; } = new XQueueArgs ();
        public IDictionary<string, XQueueArgs> Queues { get; set; }

        //
        public bool AllowDynamicExchangess { get; set; } = true;
        public XExchangeArgs DefaultExchangeArgs { get; set; } = new XExchangeArgs ();
        public IDictionary<string, XExchangeArgs> Exchanges { get; set; }

        //
        public static XEventServiceConfiguration GetDefaults () {
            return new XEventServiceConfiguration {
                Port = 5672,
                    Username = "guest",
                    Password = "guest",
                    Server = "localhost",
                    Queues = new Dictionary<string, XQueueArgs> { { "XMainQueue", new XQueueArgs { Name = "XMainQueue" } }
                    }
            };
        }
    }

    public class XQueueArgs {
        public string Name { get; set; }
        public bool Durable { get; set; } = false;
        public bool Exclusive { get; set; } = false;
        public bool AutoDelete { get; set; } = true;
    }

    public class XExchangeArgs {
        public string Name { get; set; }
        public string Type { get; set; } = ExchangeType.Fanout;
        public bool Durable { get; set; } = false;
        public bool AutoDelete { get; set; } = true;
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xEventService\Constants\ConfigurationNodeNames.cs

namespace xEventService.Constants
{
    public partial struct ConfigurationNodeNames {
        public const string EVENT_SERVICE_NODE_NAME = "EventServiceConfiguration";
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xEventService\DI\XDIHelperExtension.cs

using System;
using Microsoft.AspNetCore.Builder;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using xCommons.Extensions;
using xEventService.Configuration;
using xEventService.Constants;
using xEventService.Interfaces;
using xEventService.Models;
using xEventService.Providers;

namespace xEventService.DI {
    public static partial class XDIHelperExtension {
        /// <summary>
        /// Extract EventService Configurations ...
        /// </summary>
        /// <param name="source"></param>
        /// <returns></returns>
        public static XEventServiceConfiguration GetXEventServiceConfigurations (this IConfiguration source) {
            //
            var configSection = source
                .GetSection (ConfigurationNodeNames.EVENT_SERVICE_NODE_NAME);
            var result = configSection.Get<XEventServiceConfiguration> ();

            //
            return result;
        }

        /// <summary>
        /// Register Event Service Configurations ...
        /// </summary>
        /// <param name="services"></param>
        /// <param name="configuration"></param>
        public static void AddXEventServiceConfigurations (
            this IServiceCollection services,
            IConfiguration configuration
        ) {
            //
            var config = configuration.GetXEventServiceConfigurations ();
            services.AddXEventServiceConfigurations (config);
        }

        /// <summary>
        /// Register Event Service Configurations ...
        /// </summary>
        /// <param name="services"></param>
        /// <param name="configuration"></param>
        public static void AddXEventServiceConfigurations (
            this IServiceCollection services,
            XEventServiceConfiguration configuration
        ) {
            //
            services.AddSingleton<XEventServiceConfiguration> (configuration);
        }

        /// <summary>
        /// Register Event Service ...
        /// </summary>
        /// <param name="services"></param>
        /// <param name="configuration"></param>
        public static void AddXEventService (
            this IServiceCollection services,
            IConfiguration configuration
        ) {
            //
            // Check Configuration Registered ...
            var config = services.GetRegisteredService<XEventServiceConfiguration> ();
            if (config.IsNull ()) {
                //
                Console.WriteLine ($"XEventService: there is no provided XEventServiceConfiguration, using default ...");

                //
                // Register Default Configuration ...
                services.AddXEventServiceConfigurations (configuration);
            }

            //
            // Register IXEventBus ...
            var serviceBas = services.GetRegisteredService<IXEventBus> ();
            if (serviceBas.IsNull ()) {
                services.AddSingleton<IXEventBus, XEventBus> ();
            }
        }

        /// <summary>
        /// Register an Event Handler ...
        /// </summary>
        /// <param name="services"></param>
        /// <param name="lifetime"></param>
        /// <typeparam name="TEvent"></typeparam>
        /// <typeparam name="THandler"></typeparam>
        /// <returns></returns>
        public static void AddXEventHandler<TEvent, THandler> (
            this IServiceCollection services,
            ServiceLifetime lifetime = ServiceLifetime.Transient
        )
        where TEvent : XEvent
        where THandler : IXEventHandler<TEvent> {
            //
            services.Add (new ServiceDescriptor (
                serviceType: typeof (THandler),
                implementationType: typeof (THandler),
                lifetime: lifetime
            ));

            //
            services.Add (new ServiceDescriptor (
                serviceType: typeof (IXEventHandler<TEvent>),
                implementationType: typeof (THandler),
                lifetime: lifetime
            ));
        }

        /// <summary>
        /// Subscribe to specific Event ...
        /// </summary>
        /// <param name="app"></param>
        /// <typeparam name="TEvent"></typeparam>
        /// <typeparam name="THandler"></typeparam>
        /// <returns></returns>
        public static void XEventSubscribe<TEvent, THandler> (
            this IApplicationBuilder app,
            bool toExchange = true
        )
        where TEvent : XEvent
        where THandler : IXEventHandler<TEvent> {
            //
            var eventName = typeof (TEvent).Name;

            //
            // Retrieve EventBus from IOC ...
            var eventBus = app.ApplicationServices.GetRequiredService<IXEventBus> ();

            //
            // Subscribe to Event Handler ...
            var isSubscribed = eventBus.Subscribe<TEvent, THandler> ();
            Console.WriteLine ($"XEventService: Event Handler subscription result: {eventName} => {isSubscribed} ...");
        }
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xEventService\Extensions\ConfigurationExtensions.cs

using System;
using RabbitMQ.Client;
using xCommons.Extensions;
using xEventService.Configuration;
using xEventService.Models;
using xExceptions.Constants;

namespace xEventService.Extensions {
    public static class ConfigurationExtensions {
        /// <summary>
        /// Create Connection Factory Based on
        /// provided Configuration ...
        /// </summary>
        /// <param name="source"></param>
        /// <returns></returns>
        public static ConnectionFactory GetConnectionFactory (this XEventServiceConfiguration source) {
            //
            // Validate Args ...
            if (source.IsNull ()) {
                XException.InvalidConfiguration.Throw ();
            }

            //
            // Create Connection Factory ...
            var result = new ConnectionFactory {
                Port = source.Port,
                HostName = source.Server,
                UserName = source.Username,
                Password = source.Password
            };

            //
            // Return Result ...
            return result;
        }

        /// <summary>
        /// Create a Connection to Server ...
        /// </summary>
        /// <param name="source"></param>
        /// <returns></returns>
        public static IConnection Connect (this XEventServiceConfiguration source) {
            //
            // Open Connection ...
            IConnection result = null;
            try {
                //
                // Retrieve Connection Factory ...
                var connectionFactory = source.GetConnectionFactory ();

                //
                // Create Connection ...
                result = connectionFactory.CreateConnection ();
            } catch (Exception ex) {
                //
                Console.WriteLine ($"XEventService Exception: Connection Failed, {ex.Message} ...");

                //
                XException.ActionFailed.Throw ();
            }

            //
            return result;
        }

        /// <summary>
        /// Validate a Queue Name based on Configurations ...
        /// </summary>
        /// <param name="source"></param>
        /// <param name="queueName"></param>
        public static void ValidateQueue (
            this XEventServiceConfiguration source,
            string queueName
        ) {
            //
            // Validate Args ...
            if (source.IsNull ()) {
                XException.InvalidArgs.Throw ();
            }

            //
            // Validate Queues ...
            if ((source.Queues.IsNull () &&
                    !source.AllowDynamicQueues) ||
                (!source.Queues.IsNull () &&
                    !source.Queues.Keys.HasChild () &&
                    !source.AllowDynamicQueues)) {
                //
                Console.WriteLine ($"XEventService Exception: there isn't any configured Queue ...");

                //
                XException.InvalidArgs.Throw ();
            }

            //
            // Check queueName not empty ...
            if (queueName.IsNullOrEmpty ()) {
                //
                Console.WriteLine ($"XEventService Exception: Invalid QueueName ...");

                //
                XException.InvalidArgs.Throw ();
            }

            //
            // Check queueName Exists ...
            if (!source.Queues.IsNull () &&
                !source.Queues.ContainsKey (queueName) &&
                !source.AllowDynamicQueues) {
                //
                Console.WriteLine ($"XEventService Exception: QueueName {queueName} not found ...");

                //
                XException.InvalidArgs.Throw ();
            }
        }

        /// <summary>
        /// Validate a Exchange Name based on Configurations ...
        /// </summary>
        /// <param name="source"></param>
        /// <param name="exchangeName"></param>
        public static void ValidateExchange (
            this XEventServiceConfiguration source,
            string exchangeName
        ) {
            //
            // Validate Args ...
            if (source.IsNull ()) {
                XException.InvalidArgs.Throw ();
            }

            //
            // Validate Exchanges ...
            if ((source.Exchanges.IsNull () &&
                    !source.AllowDynamicExchangess) ||
                (!source.Exchanges.IsNull () &&
                    !source.Exchanges.Keys.HasChild () &&
                    !source.AllowDynamicExchangess)) {
                //
                Console.WriteLine ($"XEventService Exception: there isn't any configured Exchanges ...");

                //
                XException.InvalidArgs.Throw ();
            }

            //
            // Check exchangeName not empty ...
            if (exchangeName.IsNullOrEmpty ()) {
                //
                Console.WriteLine ($"XEventService Exception: Invalid ExchangeName ...");

                //
                XException.InvalidArgs.Throw ();
            }

            //
            // Check exchangeName Exists ...
            if (!source.Exchanges.IsNull () &&
                !source.Exchanges.ContainsKey (exchangeName) &&
                !source.AllowDynamicExchangess) {
                //
                Console.WriteLine ($"XEventService Exception: ExchangeName {exchangeName} not found ...");

                //
                XException.InvalidArgs.Throw ();
            }
        }

        /// <summary>
        /// Retrieve specific QueueArgs ...
        /// </summary>
        /// <param name="source"></param>
        /// <param name="queueName"></param>
        /// <returns></returns>
        public static XQueueArgs GetQueueArgs (
            this XEventServiceConfiguration source,
            string queueName
        ) {
            //
            // Validate Queue Name ...
            source.ValidateQueue (queueName);

            //
            var result = source.Queues
                .IsNull () ? null : source
                .Queues[queueName];
            if (result.IsNull ()) {
                //
                // Prepare Default Queue ...
                result = source.DefaultQueueArgs;
                if (result.IsNull ()) {
                    result = new XQueueArgs () {
                        Name = queueName
                    };
                } else {
                    result.Name = queueName;
                }
            }

            //
            return result;
        }

        /// <summary>
        /// Retrieve specific ExchangeArgs ...
        /// </summary>
        /// <param name="source"></param>
        /// <param name="exchangeName"></param>
        /// <returns></returns>
        public static XExchangeArgs GetExchangeArgs (
            this XEventServiceConfiguration source,
            string exchangeName
        ) {
            //
            // Validate Exchange Name ...
            source.ValidateExchange (exchangeName);

            //
            var result = source.Exchanges
                .IsNull () ? null : source
                .Exchanges[exchangeName];
            if (result.IsNull ()) {
                //
                // Prepare Default Queue ...
                result = source.DefaultExchangeArgs;
                if (result.IsNull ()) {
                    result = new XExchangeArgs () {
                        Name = exchangeName,
                        Type = ExchangeType.Fanout
                    };
                } else {
                    result.Name = exchangeName;
                }
            }

            //
            return result;
        }

        /// <summary>
        /// Create a Channel ...
        /// </summary>
        /// <param name="source"></param>
        /// <param name="exchangeName"></param>
        /// <returns></returns>
        public static XChannel CreateChannel (
            this XEventServiceConfiguration source,
            string exchangeName = null
        ) {
            //
            // Validate ExchangeName and Retrieve ExchangeArgs if provided ...
            var exchangeArgs = exchangeName
                .IsNullOrEmpty () ?
                null :
                source.GetExchangeArgs (exchangeName);

            //
            // Create Connection ...
            var connection = source.Connect ();
            var channel = connection.CreateModel ();

            //
            // Create XChannel Model ...
            var result = new XChannel (
                exchangeName: exchangeName,
                connection: connection
            );

            //
            // Declaring Queue if Provided ...
            if (!exchangeArgs.IsNull () &&
                !exchangeName.IsNullOrEmpty ()) {
                //
                // Declaring Queue ...
                result.Channel.ExchangeDeclare (
                    exchange: exchangeName,
                    type: exchangeArgs.Type,
                    durable: exchangeArgs.Durable,
                    autoDelete: exchangeArgs.AutoDelete
                );
            }

            //
            return result;
        }
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xEventService\Extensions\XEventModelExtensions.cs

using System;
using System.Text;
using xCommons.Extensions;

namespace xEventService.Extensions {
    public static class XEventModelExtensions {
        /// <summary>
        /// Convert an Object to bytes array for publishing
        /// </summary>
        /// <param name="source"></param>
        /// <typeparam name="T"></typeparam>
        /// <returns></returns>
        public static byte[] ToBody<T> (this T source) {
            //
            var json = source
                .ToJSON ();

            //
            var result = json
                .ToBytes ();

            //
            return result;
        }

        /// <summary>
        /// Convert Recieved Bytes to Specific Type ...
        /// </summary>
        /// <param name="source"></param>
        /// <typeparam name="T"></typeparam>
        /// <returns></returns>
        public static T FromBody<T> (this ReadOnlyMemory<byte> source) {
            //
            var jsonString = Encoding.UTF8
                .GetString (
                    source.ToArray ()
                );
            var result = jsonString.FromJSON<T> ();

            //
            return result;
        }
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xEventService\Interfaces\IXEventBus.cs

using xEventService.Models;

namespace xEventService.Interfaces {
    public interface IXEventBus {
        bool Publish<T> (T @event) where T : XEvent;

        bool Subscribe<TEvent, THandler> ()
        where TEvent : XEvent
        where THandler : IXEventHandler<TEvent>;
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xEventService\Interfaces\IXEventHandler.cs

using System.Threading.Tasks;
using xEventService.Models;

namespace xEventService.Interfaces {
    public interface IXEventHandler<in TEvent> : IXEventHandler
    where TEvent : XEvent {
        Task HandleAsync (TEvent @event);
    }

    public interface IXEventHandler { }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xEventService\Models\XChannel.cs

using System;
using RabbitMQ.Client;
using RabbitMQ.Client.Events;
using xCommons.Extensions;
using xEventService.Configuration;
using xEventService.Extensions;
using xExceptions.Constants;

namespace xEventService.Models {
    public class XChannel {
        //
        public IModel Channel { get; protected set; }
        public string QueueName { get; protected set; }
        public string ExchangeName { get; protected set; }
        public IConnection Connection { get; protected set; }

        //
        #region Constructors ...
        public XChannel (
            string exchangeName = null,
            IConnection connection = null,
            IModel channel = null,
            EventingBasicConsumer consumer = null
        ) {
            //
            // Validate Connection ...
            if (connection.IsNull ()) {
                XException.InvalidArgs.Throw ();
            }
            Connection = connection;

            //
            // Validate Channel ...
            if (channel.IsNull ()) {
                channel = connection.CreateModel ();
            }
            Channel = channel;

            //
            // Check Queue Name and it's Declaration ...
            if (!exchangeName.IsNullOrEmpty ()) {
                //
                ExchangeName = exchangeName;
            }
        }

        public XChannel (
            XEventServiceConfiguration configuration,
            bool dispatchConsumersAsync = true,
            string exchangeName = null
        ) {
            //
            // Generate Factory ...
            var factory = configuration.GetConnectionFactory ();
            if (dispatchConsumersAsync) {
                factory.DispatchConsumersAsync = true;
            }

            //
            // Create Cahnnel ...
            Connection = factory.CreateConnection ();
            Channel = Connection.CreateModel ();

            //
            // Check Exchange Declaration if provided ...
            if (!exchangeName.IsNullOrEmpty ()) {
                //
                ExchangeName = exchangeName;
                var exchangeArgs = configuration.GetExchangeArgs (ExchangeName);

                //
                // Declaring Exchange ...
                Channel.ExchangeDeclare (
                    exchange: exchangeName,
                    type: exchangeArgs.Type,
                    durable: exchangeArgs.Durable,
                    autoDelete: exchangeArgs.AutoDelete
                );

                //
                // Create a Queue ...
                var queueName = $"{exchangeName}[{Guid.NewGuid().ToString().GetDigits()}]";
                var queueArgs = configuration.GetQueueArgs (queueName);
                QueueName = queueName;
                Channel.QueueDeclare (
                    queue: queueName,
                    durable: queueArgs.Durable,
                    exclusive: queueArgs.Exclusive,
                    autoDelete: queueArgs.AutoDelete
                );

                //
                // Bind Queue to Exchange ...
                Channel.QueueBind (
                    queue: queueName,
                    exchange: exchangeName,
                    routingKey: ""
                );
            }
        }
        #endregion

        //
        #region Actions ...
        /// <summary>
        /// Close Channel ...
        /// </summary>
        public void CloseChannel () {
            //
            // Check Channel Exists ...
            if (!this.Channel.IsNull ()) {
                //
                // Close Channel if it's Open ...
                if (this.Channel.IsOpen) {
                    this.Channel.Close ();
                }

                //
                this.Channel.Dispose ();
                this.Channel = null;
            }
        }

        /// <summary>
        /// Close Connection ...
        /// </summary>
        public void CloseConnection () {
            //
            // Check Connection Exists ...
            if (!this.Connection.IsNull ()) {
                //
                // Close Connection if it's Open ...
                if (this.Connection.IsOpen) {
                    this.Connection.Close ();
                }

                //
                this.Connection.Dispose ();
                this.Connection = null;
            }
        }

        /// <summary>
        /// Publish a Message through Channel on Declare Queue ...
        /// </summary>
        /// <param name="message"></param>
        /// <typeparam name="T"></typeparam>
        /// <returns></returns>
        public bool Publish<T> (T message) {
            //
            // Validate Args ...
            if (this.Connection.IsNull () ||
                !this.Connection.IsOpen ||
                this.Channel.IsNull () ||
                !this.Channel.IsOpen) {
                //
                Console.WriteLine ($"XEventService Exception: Publish Failed ...");

                //
                XException.InvalidArgs.Throw ();
            }

            //
            // Check Publish Method ...
            //
            // Check Exchange Name ...
            if (this.ExchangeName.IsNullOrEmpty ()) {
                //
                Console.WriteLine ($"XEventService Exception: Publish Failed, Invalid Exchange Name {ExchangeName} ...");

                //
                XException.InvalidArgs.Throw ();
            }

            //
            try {
                //
                // Publish Message through Channel to Declared Queue ...
                var body = message.ToBody ();
                this.Channel.BasicPublish (
                    exchange: ExchangeName,
                    routingKey: "",
                    basicProperties : null,
                    body : body
                );

                //
                return true;
            } catch (Exception ex) {
                //
                Console.WriteLine ($"XEventService Exception: Publish Failed, {ex.Message} ...");

                //
                return false;
            }
        }

        public void Consume (EventingBasicConsumer consumer) {
            Channel.BasicConsume (
                queue: QueueName,
                autoAck: true,
                consumer: consumer
            );
        }

        public void ConsumeAsync (AsyncEventingBasicConsumer consumer) {
            Channel.BasicConsume (
                queue: QueueName,
                autoAck: true,
                consumer: consumer
            );
        }

        /// <summary>
        /// Dispose XChannel ...
        /// </summary>
        public void Dispose () {
            //
            this.CloseChannel ();
            this.CloseConnection ();
        }
        #endregion        
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xEventService\Models\XEvent.cs

using xEventService.Base;

namespace xEventService.Models {
    public class XEvent : XBaseEvent { }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xEventService\Providers\XEventBus.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using RabbitMQ.Client.Events;
using xCommons.Extensions;
using xEventService.Configuration;
using xEventService.Extensions;
using xEventService.Interfaces;
using xEventService.Models;
using xExceptions.Constants;

namespace xEventService.Providers {
    public sealed class XEventBus : IXEventBus {
        //
        #region Properties ...
        private readonly List<Type> events;
        private readonly ILogger<XEventBus> logger;
        private readonly IServiceScopeFactory serviceScopeFactory;
        private readonly XEventServiceConfiguration configuration;
        private readonly IDictionary<string, List<Type>> handlers;
        #endregion

        //
        #region Constructors ...
        public XEventBus (
            ILoggerFactory loggerFactory,
            IServiceScopeFactory serviceScopeFactory,
            XEventServiceConfiguration configuration
        ) {
            //
            this.configuration = configuration;
            this.serviceScopeFactory = serviceScopeFactory;

            //
            events = new List<Type> ();
            handlers = new Dictionary<string, List<Type>> ();
            logger = loggerFactory.CreateLogger<XEventBus> ();
        }
        #endregion

        //
        #region Abstracts ...
        public bool Publish<T> (T @event) where T : XEvent {
            //
            // Validate Args ...
            if (@event.IsNull ()) {
                return false;
            }

            //
            // Prepare Channel ...
            XChannel channel = null;

            //
            // Extract event name ...
            var exchangeName = @event.GetType ().Name;

            //
            // Do Action ...
            try {
                //
                // Get XChannel Model ...
                channel = configuration.CreateChannel (exchangeName);

                //
                // Publish Command ...
                channel.Publish (message: @event);

                //
                // Return Result ...
                return true;
            } catch (Exception ex) {
                //
                logger.LogError ($"XEventService Exception: Publishing Failed {exchangeName}/{ex.Message} ...");

                //
                return false;
            } finally {
                //
                if (!channel.IsNull ()) {
                    channel.Dispose ();
                }
            }
        }

        public bool Subscribe<TEvent, THandler> ()
        where TEvent : XEvent
        where THandler : IXEventHandler<TEvent> {
            //
            // Extract required data ...
            var eventType = typeof (TEvent);
            var eventName = eventType.Name;
            var handlerType = typeof (THandler);

            //
            // Check event exists in list or not ...
            if (!events.Contains (eventType)) {
                //
                // Add it if not exists ...
                events.Add (eventType);
            }

            //
            // Check handlers Dictionary contains list or not ...
            if (!handlers.ContainsKey (eventName)) {
                handlers.Add (eventName, new List<Type> ());
            }

            //
            // Check handlers Subscribed before or not ...
            var isHandlerSubscribed = handlers[eventName]
                .Any (h => h.GetType () == handlerType);
            if (isHandlerSubscribed) {
                //
                logger.LogError ($"XEventService Exception: Duplicate Event Handler Subscription {eventName}/{handlerType.Name} ...");

                //
                return false;
            }

            //
            // Register Handler ...
            handlers[eventName].Add (handlerType);

            //
            // Do Consuming Handler ...
            ConsumeEvent<TEvent> ();

            //
            return true;
        }
        #endregion

        //
        #region Private ...
        /// <summary>
        /// Consume Specific Event ...
        /// </summary>
        /// <typeparam name="TEvent"></typeparam>
        private void ConsumeEvent<TEvent> ()
        where TEvent : XEvent {
            //
            // Extract required data ...
            var eventType = typeof (TEvent);
            var eventName = eventType.Name;

            //
            // Create ChannelObject ...
            var channel = new XChannel (
                exchangeName: eventName,
                configuration: configuration,
                dispatchConsumersAsync: true
            );

            //
            // Create Consumer ...
            var consumer = new AsyncEventingBasicConsumer (channel.Channel);

            //
            // Set Consumer Delegate ...
            consumer.Received += XConsumerReceivedDelegate;

            //
            // Consume Async Consumer ...
            channel.ConsumeAsync (consumer);
        }

        /// <summary>
        /// this Delegate method calls when a message recieved ...
        /// </summary>
        private async Task XConsumerReceivedDelegate (
            object sender,
            BasicDeliverEventArgs ea
        ) {
            //
            // Generate Required Data ...
            var eventName = ea.Exchange;
            var json = Encoding.UTF8
                .GetString (
                    ea.Body
                    .ToArray ()
                );

            //
            // Do Processing Event ...
            try {
                //
                // Process Event in non Blocking Tasks ...
                await ProcessEvent (eventName, json)
                    .ConfigureAwait (false);
            } catch (Exception ex) {
                //
                logger.LogError ($"XEventService Exception: Processing Event failed {eventName}/{ex.Message} ...");

                //
                XException.ActionFailed.Throw ();
            } finally {
                //
                var channel = ((EventingBasicConsumer) sender).Model;
                channel.BasicAck (
                    deliveryTag: ea.DeliveryTag,
                    multiple: false
                );
            }
        }

        /// <summary>
        /// Here we must call registered Event Handlers to Handle the Event ...
        /// </summary>
        private async Task ProcessEvent (
            string eventName,
            string json
        ) {
            //
            // Check Handler Exists for current Event ...
            var isExistsHandler = handlers.ContainsKey (eventName);
            if (!isExistsHandler) {
                return;
            }

            //
            // Using Service Scope Factory ...
            using (var scope = serviceScopeFactory.CreateScope ()) {
                //
                // Get Handler Subscriptions ...
                var subscriptions = handlers[eventName];
                foreach (var subscription in subscriptions) {
                    //
                    // Inject Handler from Dependency Injections ...
                    var handler = scope.ServiceProvider.GetService (subscription);
                    if (handler.IsNull ()) {
                        //
                        logger.LogInformation ($"XEventService: there is no handler Registered in DependencyInjection for {eventName}/{subscription.Name}");

                        //
                        continue;
                    }

                    //
                    // Retrieve Event Type ...
                    var eventType = events.SingleOrDefault (t => t.Name == eventName);
                    var @event = json.FromJSON (eventType);
                    var conreteType = typeof (IXEventHandler<>).MakeGenericType (eventType);

                    //
                    // Call EventHandler 'HandleAsync' method ...
                    await ((Task) conreteType
                        .GetMethod (nameof (IXEventHandler<XEvent>.HandleAsync))
                        .Invoke (handler, new object[] { @event }))
                    .ConfigureAwait (true);
                }
            }
        }
        #endregion
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xExceptions\Attributes\StringValueAttribute.cs

using System;

namespace xExceptions.Attributes
{
    /// <summary>
    /// an attribute which attached to enums to carry propper string
    /// </summary>
    public partial class StringValueAttribute : System.Attribute {
        public string StringValue { get; set; }

        public StringValueAttribute (string value) {
            this.StringValue = value;
        }
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xExceptions\Constants\XException.cs

using xExceptions.Attributes;

namespace xExceptions.Constants
{
    public enum XException {
        //
        #region Invalid Exceptions 1xx ...
        [StringValue ("Invalid Data ...")]
        InvalidData = 100,

        //
        [StringValue ("Invalid Date ...")]
        InvalidDate = 101,

        //
        [StringValue ("Bad Request ...")]
        BadRequest = 102,

        //
        [StringValue ("Invalid Args ...")]
        InvalidArgs = 103,

        //
        [StringValue ("Invalid Message ...")]
        InvalidMessage = 104,

        //
        [StringValue ("Invalid Token ...")]
        InvalidToken = 105,

        //
        [StringValue ("Invalid Verification Code ...")]
        InvalidVerificationCode = 106,

        //
        [StringValue ("Invalid Email Address ...")]
        InvalidEmailAddress = 107,

        //
        [StringValue ("Invalid Mobile Number ...")]
        InvalidMobileNumber = 108,

        //
        [StringValue ("Invalid Password ...")]
        InvalidPassword = 109,

        //
        [StringValue ("Inavlid Url ...")]
        InavlidUrl = 110,

        //
        [StringValue ("Invalid Device ...")]
        InvalidDevice = 111,

        //
        [StringValue ("Invalid Profile Image ...")]
        InvalidProfileImage = 112,

        //
        [StringValue ("Invalid File ...")]
        InavlidFile = 113,

        //
        [StringValue ("Invalid Username ...")]
        InvalidUserName = 114,
        #endregion

        //
        #region Not (...) Exceptions 2xx ...
        //
        [StringValue ("Not Found ...")]
        NotFound = 200,

        //
        [StringValue ("Not Allowed ...")]
        NotAllowed = 201,

        //
        [StringValue ("Not Authorized ...")]
        NotAuthorized = 202,

        //
        [StringValue ("Not Visible ...")]
        NotVisible = 203,
        #endregion

        //
        #region User/Registration/Account/Bann Exceptions 3xx ...
        //
        [StringValue ("Account Locked out Until:{0}")]
        AccountLockedOut = 300,

        //
        [StringValue ("Login Failed ...")]
        LoginFailed = 301,

        //
        [StringValue ("User Registered Before ...")]
        UserRegisteredBefore = 302,

        //
        [StringValue ("User Disabled ...")]
        UserDisabled = 303,
        //
        [StringValue ("Device Banned Until:{0}")]
        DeviceBanned = 304,

        //
        [StringValue ("You can't Request Verification code Until:{0}")]
        VerificationCodeResendNotAllowed = 305,

        //
        [StringValue ("Passwords Same ...")]
        PasswordsSame = 306,

        // 
        [StringValue ("Mobiles Same ...")]
        MobilesSame = 307,

        // 
        [StringValue ("Emails Same ...")]
        EmailsSame = 308,

        //
        [StringValue ("Mobile In Used ...")]
        MobileInUsed = 309,

        //
        [StringValue ("Email In Used ...")]
        EmailInUsed = 310,

        //
        [StringValue ("Mobile Not Confirmed ...")]
        MobileNotConfirmed = 311,

        //
        [StringValue ("Email Not Confirmed ...")]
        EmailNotConfirmed = 312,

        //
        [StringValue ("Post Banned ...")]
        PostBanned = 313,

        //
        [StringValue ("User Banned ...")]
        UserBanned = 314,
        #endregion

        //
        #region General Exceptions 4xx ...
        //
        [StringValue ("Unknown Error ...")]
        Unknown = 400,

        //
        [StringValue ("Duplicate ...")]
        Duplicate = 401,

        //
        [StringValue ("Action Failed ...")]
        ActionFailed = 402,

        //
        [StringValue ("Expired Date ...")]
        ExpiredDate = 403,

        //
        [StringValue ("Unavailable ...")]
        Unavailable = 404,

        //
        [StringValue ("Max Allowed Tag Exceeded ...")]
        MaxAllowedTagExceeded = 405,

        //
        [StringValue ("Timed out ...")]
        Timeout = 406,
        #endregion

        //
        #region File Exceptions 5xx ...
        //
        [StringValue ("Empty File ...")]
        EmptyFile = 500,

        //
        [StringValue ("max File size exceeded ...")]
        MaxFileSizeExceeded = 501,

        //
        [StringValue ("Unsupported File Type ...")]
        UnsupportedFileType = 502,

        //
        [StringValue ("Max Allowed Media Exceeded ...")]
        MaxAllowedMediaExceeded = 503,
        #endregion

        //
        #region Configuration Exceptions 6xx ...
        //
        [StringValue ("Invalid Configuration ...")]
        InvalidConfiguration = 600,

        //
        [StringValue ("Storage Service Initiallization Failed ...")]
        StorageServiceInitialFailed = 601,

        //
        [StringValue ("Message Service Initialization Failed ...")]
        MessageServiceInitialFailed = 602,
        #endregion
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xExceptions\Models\XError.cs

namespace xExceptions.Models {
    public partial class XError {
        /// <summary>
        /// th ID of Error
        /// </summary>
        /// <value></value>
        public int Id { get; set; }

        /// <summary>
        /// the String Value of Error
        /// </summary>
        /// <value></value>
        public string Message { get; set; }
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xFileService\Configurations\Entities\XFileEntityConfiguration.cs

using System;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Metadata.Builders;
using xDataService.Providers;
using xFileService.Constants;
using xFileService.Models.Entities;

namespace xFileService.Configurations.Entities
{
    public class XFileEntityConfiguration : XBaseEntityTypeConfiguration<XFile, Guid>
    {
        public override void Configure(EntityTypeBuilder<XFile> builder)
        {
            builder.ToTable(XFileServiceConstants.XFileTable);
        }
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xFileService\Constants\XFileServiceConstants.cs

using xFileService.Models.Entities;

namespace xFileService.Constants
{
    public struct XFileServiceConstants
    {
        //
        // Service Extensions Log Tag ...
        public const string XFileServiceDILogTag = "XFileService";

        //
        // Table Mapping Identifiers ...
        public const string XFileTable = "Files";

        //
        // GraphQL Collection Mappings ...
        public const string XFileSingleName = "file";
        public const string XFileCollectionName = "files";

        //
        // Hubs ...
        public const string XFileDtoHub = "fileDto";
        public const string XFileEntityHub = "fileEntity";

        //
        // Custome Constants ...
        public const string XFileTagProvided = nameof(XFile);

        //
        // EF Repositories Helper Extensions ...
        public const string GetXFileEFRepositoryDescriptor = "GetXFileEFRepositoryDescriptor";
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xFileService\Controllers\XFileProviderControllerBase.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore.Query;
using Microsoft.Extensions.Logging;
using xCommons.Configurations;
using xCommons.Extensions;
using xCommons.Providers;
using xDataService.Models;
using xExceptions.Constants;
using xFileService.Interfaces;
using xFileService.Models.Dtos;
using xFileService.Models.Entities;
using xFileService.Providers.Dtos;
using xIdentityService.Interfaces;
using xTagService.Controllers;

namespace xFileService.Controllers
{
    public abstract class XFileProviderControllerBase : XBaseProvidedHasTagControllerBase<XFile, XFileDto, Guid, XFileDtoHub>, IXFileProviderController
    {
        private readonly IXFileProvider provider;

        protected XFileProviderControllerBase(
            ILogger<XFileProviderControllerBase> logger,
            XAppConfiguration appConfiguration,
            IXIdentityProvider identityProvider,
            XValidationProvider validationProvider,
            IXFileProvider provider,
            IXFileTagProvided tagProvided,
            Func<IQueryable<XFile>, IOrderedQueryable<XFile>> defaultOrderBuilder = null,
            Func<IQueryable<XFile>, IIncludableQueryable<XFile, object>> defaultIncludeBuilder = null
        ) : base(
            logger,
            appConfiguration,
            identityProvider,
            validationProvider,
            provider,
            tagProvided,
            defaultOrderBuilder,
            defaultIncludeBuilder
        )
        {
            this.provider = provider;
        }

        //
        #region Tools ...
        /// <summary>
        /// Stream Specified File ...
        /// </summary>
        /// <param name="id"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        [HttpGet("{id}/Stream/ById")]
        public virtual async Task<ActionResult> Stream(
            [FromRoute] Guid id,
            CancellationToken cancellationToken = default
        )
        {
            //
            try
            {
                //
                var result = await provider.Stream(
                    id: id,
                    cancellationToken: cancellationToken
                );

                //
                return result;
            }
            catch (Exception ex)
            {
                //
                var result = GetExceptionActionResult(ex);
                return result;
            }
        }

        /// <summary>
        /// Stream Specified File ...
        /// </summary>
        /// <param name="name"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        [HttpGet("{name}/Stream/ByName")]
        public virtual async Task<ActionResult> Stream(
            [FromRoute] string name,
            CancellationToken cancellationToken = default
        )
        {
            //
            try
            {
                //
                var result = await provider.Stream(
                    name: name,
                    cancellationToken: cancellationToken
                );

                //
                return result;
            }
            catch (Exception ex)
            {
                //
                var result = GetExceptionActionResult(ex);
                return result;
            }
        }

        /// <summary>
        /// Download Specified File ...
        /// </summary>
        /// <param name="id"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        [HttpGet("{id}/Download/ById")]
        public virtual async Task<ActionResult> Download(
            [FromRoute] Guid id,
            CancellationToken cancellationToken = default
        )
        {
            //
            try
            {
                //
                var result = await provider.Download(
                    id: id,
                    cancellationToken: cancellationToken
                );

                //
                return result;
            }
            catch (Exception ex)
            {
                //
                var result = GetExceptionActionResult(ex);
                return result;
            }
        }

        /// <summary>
        /// Download Specified File ...
        /// </summary>
        /// <param name="name"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        [HttpGet("{name}/Download/ByName")]
        public virtual async Task<ActionResult> Download(
            string name,
            CancellationToken cancellationToken = default
        )
        {
            //
            try
            {
                //
                var result = await provider.Download(
                    name: name,
                    cancellationToken: cancellationToken
                );

                //
                return result;
            }
            catch (Exception ex)
            {
                //
                var result = GetExceptionActionResult(ex);
                return result;
            }
        }

        /// <summary>
        /// Upload Files ...
        /// </summary>
        /// <param name="files"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        [HttpPost("Upload")]
        [RequestSizeLimit(966_367_641)]
        public virtual async Task<ActionResult<IEnumerable<XFileDto>>> Upload(
            [FromForm] IFormFileCollection files,
            CancellationToken cancellationToken = default
        )
        {
            //
            try
            {
                //
                // Retrieve User Info ...
                var userInfo = await GetUserInfo();
                var connectionId = GetConnectionId();

                //
                var result = await provider.Upload(
                    files: files,
                    userInfo: userInfo,
                    connectionId: connectionId,
                    cancellationToken: cancellationToken
                );

                //
                return Ok(result.ToDynamicObject());
            }
            catch (Exception ex)
            {
                //
                var result = GetExceptionActionResult(ex);
                return result;
            }
        }

        /// <summary>
        /// Remove Specified Files ...
        /// </summary>
        /// <param name="ids"></param>
        /// <param name="userInfo"></param>
        /// <param name="connectionId"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        [HttpDelete("")]
        public virtual async Task<ActionResult<IEnumerable<Guid>>> Remove(
            [FromQuery] string ids,
            CancellationToken cancellationToken = default
        )
        {
            //
            try
            {
                //
                // Retrieve User Info ...
                var userInfo = await GetUserInfo();
                var connectionId = GetConnectionId();

                //
                var result = await provider.Remove(
                    ids: ids,
                    userInfo: userInfo,
                    connectionId: connectionId,
                    cancellationToken: cancellationToken
                );

                //
                return Ok(result.ToDynamicObject());
            }
            catch (Exception ex)
            {
                //
                var result = GetExceptionActionResult(ex);
                return result;
            }
        }
        #endregion                

        //
        #region Reference ...
        /// <summary>
        /// Check an Item Has Reference to Specified ProvideFor and Specified forProvidedId ...
        /// </summary>
        /// <param name="id"></param>
        /// <param name="providedFor"></param>
        /// <param name="forProvidedId"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        [HttpGet("{id}/Reference/IsProvidedFor")]
        public virtual async Task<ActionResult<bool>> IsProvidedFor(
            [FromRoute] Guid id,
            [FromQuery] string providedFor,
            [FromQuery] object forProvidedId,
            CancellationToken cancellationToken = default
        )
        {
            //
            try
            {
                //
                // Validate ...
                if (!ModelState.IsValid)
                {
                    XException.InvalidArgs.Throw();
                }
                await ValidationProvider
                    .GroupValidationBuilder()
                    .AddNotNull(id)
                    .AddNotEmpty(providedFor)
                    .AddNotNull(forProvidedId)
                    .ValidateGroupAsync();

                //
                var result = await provider.IsProvidedFor(
                    id: id,
                    providedFor: providedFor,
                    forProvidedId: forProvidedId,
                    cancellationToken: cancellationToken
                );

                //
                return Ok(result);
            }
            catch (Exception ex)
            {
                //
                var result = GetExceptionActionResult(ex);
                return result;
            }
        }

        /// <summary>
        /// Add a Reference to Item for Specified ProvideFor and Specified forProvidedId ...
        /// </summary>
        /// <param name="id"></param>
        /// <param name="providedFor"></param>
        /// <param name="forProvidedId"></param>
        /// <param name="forIndex"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        [HttpPost("{id}/Reference")]
        public virtual async Task<ActionResult> AddReference(
            [FromRoute] Guid id,
            [FromQuery] string providedFor,
            [FromQuery] object forProvidedId,
            [FromQuery] int forIndex = 0,
            CancellationToken cancellationToken = default
        )
        {
            //
            try
            {
                //
                // Validate ...
                if (!ModelState.IsValid)
                {
                    XException.InvalidArgs.Throw();
                }
                await ValidationProvider
                    .GroupValidationBuilder()
                    .AddNotNull(id)
                    .AddNotEmpty(providedFor)
                    .AddNotNull(forProvidedId)
                    .ValidateGroupAsync();

                //
                var userInfo = await GetUserInfo();
                var connectionId = GetConnectionId();

                //
                await provider.AddReference(
                    id: id,
                    forIndex: forIndex,
                    userInfo: userInfo,
                    providedFor: providedFor,
                    connectionId: connectionId,
                    forProvidedId: forProvidedId,
                    cancellationToken: cancellationToken
                );

                //
                return Ok();
            }
            catch (Exception ex)
            {
                //
                var result = GetExceptionActionResult(ex);
                return result;
            }
        }

        /// <summary>
        /// Remove a Reference from Item for Specified ProvideFor and Specified forProvidedId ...
        /// </summary>
        /// <param name="id"></param>
        /// <param name="providedFor"></param>
        /// <param name="forProvidedId"></param>
        /// <param name="forIndex"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        [HttpDelete("{id}/Reference")]
        public virtual async Task<ActionResult> RemoveReference(
            [FromRoute] Guid id,
            [FromQuery] string providedFor,
            [FromQuery] object forProvidedId,
            [FromQuery] int forIndex = 0,
            CancellationToken cancellationToken = default
        )
        {
            //
            try
            {
                //
                // Validate ...
                if (!ModelState.IsValid)
                {
                    XException.InvalidArgs.Throw();
                }
                await ValidationProvider
                    .GroupValidationBuilder()
                    .AddNotNull(id)
                    .AddNotEmpty(providedFor)
                    .AddNotNull(forProvidedId)
                    .ValidateGroupAsync();

                //
                var userInfo = await GetUserInfo();
                var connectionId = GetConnectionId();

                //
                await provider.RemoveReference(
                    id: id,
                    forIndex: forIndex,
                    userInfo: userInfo,
                    providedFor: providedFor,
                    connectionId: connectionId,
                    forProvidedId: forProvidedId,
                    cancellationToken: cancellationToken
                );

                //
                return Ok();
            }
            catch (Exception ex)
            {
                //
                var result = GetExceptionActionResult(ex);
                return result;
            }
        }

        /// <summary>
        /// Retrieve References of Specified Itemfor providedFor ...
        /// </summary>
        /// <param name="id"></param>
        /// <param name="providedFor"></param>
        /// <param name="cancellationToken"></param>
        /// <typeparam name="TReferenceKey"></typeparam>
        /// <returns></returns>
        [HttpGet("{id}/References")]
        public virtual async Task<ActionResult<IEnumerable<XReference<string>>>> GetReferences(
            [FromRoute] Guid id,
            [FromQuery] string providedFor,
            CancellationToken cancellationToken = default
        )
        {
            //
            try
            {
                //
                // Validate ...
                if (!ModelState.IsValid)
                {
                    XException.InvalidArgs.Throw();
                }
                await ValidationProvider
                    .GroupValidationBuilder()
                    .AddNotNull(id)
                    .AddNotEmpty(providedFor)
                    .ValidateGroupAsync();

                //
                var result = await provider.GetReferences(
                    id: id,
                    providedFor: providedFor,
                    cancellationToken: cancellationToken
                );

                //
                return Ok(result.ToDynamicObject());
            }
            catch (Exception ex)
            {
                //
                var result = GetExceptionActionResult(ex);
                return result;
            }
        }
        #endregion
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xFileService\Controllers\XFileRepositoryControllerBase.cs

using System;
using System.Linq;
using Microsoft.EntityFrameworkCore.Query;
using Microsoft.Extensions.Logging;
using xCommons.Configurations;
using xCommons.Providers;
using xDataService.Controllers;
using xDataService.Interfaces;
using xFileService.Interfaces.Entities;
using xFileService.Models.Entities;

namespace xFileService.Controllers
{
    public abstract class XFileRepositoryControllerBase : XBaseRepositoryController<XFile, Guid>, IXBaseRepositoryController<XFile, Guid>
    {
        protected XFileRepositoryControllerBase(
            ILogger<XFileRepositoryControllerBase> logger,
            XAppConfiguration appConfiguration,
            XValidationProvider validationProvider,
            IXFileRepository repository,
            Func<IQueryable<XFile>, IOrderedQueryable<XFile>> defaultOrderBuilder = null,
            Func<IQueryable<XFile>, IIncludableQueryable<XFile, object>> defaultIncludeBuilder = null
        ) : base(
            logger,
            appConfiguration,
            validationProvider,
            repository,
            defaultOrderBuilder,
            defaultIncludeBuilder
        )
        { }
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xFileService\Controllers\XFileRepositoryProviderControllerBase.cs

using System;
using System.Linq;
using Microsoft.EntityFrameworkCore.Query;
using Microsoft.Extensions.Logging;
using xCommons.Configurations;
using xCommons.Providers;
using xFileService.Interfaces.Entities;
using xFileService.Models.Entities;
using xFileService.Providers.Entities;
using xIdentityService.Interfaces;
using xPushService.Controllers;
using xPushService.Interfaces;

namespace xFileService.Controllers
{
    public abstract class XFileRepositoryProviderControllerBase : XBaseRepositoryProviderController<XFile, Guid, XFileEntityHub>, IXBaseRepositoryProviderController<XFile, Guid, XFileEntityHub>
    {
        protected XFileRepositoryProviderControllerBase(
            ILogger<XFileRepositoryProviderControllerBase> logger,
            XAppConfiguration appConfiguration,
            IXIdentityProvider identityProvider,
            XValidationProvider validationProvider,
            IXFileRepositoryProvider provider,
            Func<IQueryable<XFile>, IOrderedQueryable<XFile>> defaultOrderBuilder = null,
            Func<IQueryable<XFile>, IIncludableQueryable<XFile, object>> defaultIncludeBuilder = null
        ) : base(
            logger,
            appConfiguration,
            identityProvider,
            validationProvider,
            provider,
            defaultOrderBuilder,
            defaultIncludeBuilder
        )
        { }
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xFileService\Controllers\XFileServiceControllerBase.cs

using System;
using System.Linq;
using Microsoft.EntityFrameworkCore.Query;
using Microsoft.Extensions.Logging;
using xCommons.Configurations;
using xCommons.Providers;
using xDataService.Controllers;
using xDataService.Interfaces;
using xFileService.Interfaces.Dtos;
using xFileService.Models.Dtos;
using xFileService.Models.Entities;

namespace xFileService.Controllers
{
    public abstract class XFileServiceControllerBase : XBaseServiceController<XFile, XFileDto, Guid>, IXBaseServiceController<XFile, XFileDto, Guid>
    {
        protected XFileServiceControllerBase(
            ILogger<XFileServiceControllerBase> logger,
            XAppConfiguration appConfiguration,
            XValidationProvider validationProvider,
            IXFileRepositoryService repositoryService,
            Func<IQueryable<XFile>, IOrderedQueryable<XFile>> defaultOrderBuilder = null,
            Func<IQueryable<XFile>, IIncludableQueryable<XFile, object>> defaultIncludeBuilder = null
        ) : base(
            logger,
            appConfiguration,
            validationProvider,
            repositoryService,
            defaultOrderBuilder,
            defaultIncludeBuilder
        )
        { }
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xFileService\Controllers\XFileServiceProviderControllerBase.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.EntityFrameworkCore.Query;
using Microsoft.Extensions.Logging;
using xCommons.Configurations;
using xCommons.Providers;
using xFileService.Interfaces.Dtos;
using xFileService.Models.Dtos;
using xFileService.Models.Entities;
using xFileService.Providers.Dtos;
using xIdentityService.Interfaces;
using xPushService.Controllers;
using xPushService.Interfaces;

namespace xFileService.Controllers
{
    public abstract class XFileServiceProviderControllerBase : XBaseServiceProviderController<XFile, XFileDto, Guid, XFileDtoHub>, IXBaseServiceProviderController<XFile, XFileDto, Guid, XFileDtoHub>
    {
        protected XFileServiceProviderControllerBase(
            ILogger<XFileServiceProviderControllerBase> logger,
            XAppConfiguration appConfiguration,
            IXIdentityProvider identityProvider,
            XValidationProvider validationProvider,
            IXFileServiceProvider provider,
            Func<IQueryable<XFile>, IOrderedQueryable<XFile>> defaultOrderBuilder = null,
            Func<IQueryable<XFile>, IIncludableQueryable<XFile, object>> defaultIncludeBuilder = null
        ) : base(
            logger,
            appConfiguration,
            identityProvider,
            validationProvider,
            provider,
            defaultOrderBuilder,
            defaultIncludeBuilder
        )
        { }
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xFileService\DI\XDIHelperExtension.cs

using System;
using Microsoft.AspNetCore.Builder;
using Microsoft.Extensions.DependencyInjection;
using xCommons.Extensions;
using xCommons.Helpers;
using xDataService.Constants;
using xDataService.Db;
using xDataService.DI;
using xDataService.Models;
using xExceptions.Constants;
using xPushService.DI;
using xPushService.Helpers;
using xFileService.Helpers;
using xFileService.Interfaces.Dtos;
using xFileService.Interfaces.Entities;
using xFileService.Providers.Dtos;
using xFileService.Providers.Entities;
using xFileService.Interfaces;
using xFileService.Providers;
using xFileService.Constants;

namespace xFileService.DI
{
    public static class XDIHelperExtension
    {
        /// <summary>
        /// Register Service ...
        /// </summary>
        /// <param name="services"></param>
        /// <param name="repositoryType"></param>
        /// <param name="lifeTime"></param>
        public static void AddXFileService(
            this IServiceCollection services,
            XRepositoryType repositoryType,
            ServiceLifetime lifeTime = ServiceLifetime.Scoped
        )
        {
            AddFileService(
                contextType: null,
                services: services,
                lifeTime: lifeTime,
                repositoryType: repositoryType
            );
        }

        /// <summary>
        /// Register Service ...
        /// </summary>
        /// <typeparam name="TContext"></typeparam>
        /// <param name="services"></param>
        /// <param name="repositoryType"></param>
        /// <param name="lifeTime"></param>
        public static void AddXFileService<TContext>(
            this IServiceCollection services,
            XRepositoryType repositoryType,
            ServiceLifetime lifeTime = ServiceLifetime.Scoped
        )
        where TContext : XDbContext
        {
            AddFileService(
                services: services,
                lifeTime: lifeTime,
                contextType: typeof(TContext),
                repositoryType: repositoryType
            );
        }

        /// <summary>
        /// Use XFileService Middleware ... 
        /// </summary>
        /// <param name="app"></param>
        /// <param name="isDevelopmentEnvironment"></param>
        public static void UseXFileService(
            this IApplicationBuilder app,
            bool isDevelopmentEnvironment = false
        )
        {
            //
            #region  Using XFile Hubs ...
            //
            var pushHelper = new XPushServiceHelper();

            //
            pushHelper.AddHub<XFileDtoHub>(XFileServiceConstants.XFileDtoHub);
            pushHelper.AddHub<XFileEntityHub>(XFileServiceConstants.XFileEntityHub);

            //
            app.UseXPushService(pushHelper);
            #endregion

            //
            // Using XFile Repository Descriptor ...
            if (!descriptor.IsNull())
            {
                //
                app.UseXRepository(
                    descriptor: descriptor,
                    isDevelopmentEnvironment: isDevelopmentEnvironment
                );
            }
        }

        //
        #region Private ...
        private static XRepositoryDescriptor descriptor = null;

        /// <summary>
        /// a LogTag for Service ...
        /// </summary>
        private static string XLogTag = XFileServiceConstants.XFileServiceDILogTag;

        /// <summary>
        /// print a log in Console ...
        /// </summary>
        /// <param name="message"></param>
        private static void Log(string message)
        {
            Console.WriteLine($"{XLogTag} => {message}");
        }

        /// <summary>
        /// Register Service ...
        /// </summary>
        /// <param name="services"></param>
        /// <param name="repositoryType"></param>
        /// <param name="contextType"></param>
        /// <param name="lifeTime"></param>
        private static void AddFileService(
            IServiceCollection services,
            XRepositoryType repositoryType,
            Type contextType = null,
            ServiceLifetime lifeTime = ServiceLifetime.Scoped
        )
        {
            //
            var exception = XException.InvalidArgs.ToException(); ;

            //
            // Services ...
            var isServicesExists = !services.IsNull();
            if (!isServicesExists)
            {
                //
                Log("Service Registration failed, services not provided ...");
                throw exception;
            }

            //
            // Lifetime ...
            var isLifetimeExists = !lifeTime.IsNull();
            if (!isLifetimeExists)
            {
                //
                Log("Service Registration failed, lifetime not provided ...");
                throw exception;
            }

            //
            // Validate Repository Type ...
            var isRepositoryTypeValid =
                (repositoryType == XRepositoryType.EF &&
                !contextType.IsNull()) ||
                ((repositoryType == XRepositoryType.Mongo ||
                    repositoryType == XRepositoryType.InMemory) &&
                contextType.IsNull());
            if (!isRepositoryTypeValid)
            {
                //
                Log("Service Registration failed, Invalid Repository Type and Context Type ...");
                throw exception;
            }

            //
            // Maske Instance of Repository Descriptor 
            // Based on Provided Type ...
            switch (repositoryType)
            {
                //
                case XRepositoryType.EF:
                    //
                    descriptor = typeof(XFileServiceHelper)
                        .InvokeGenericMethod<XRepositoryDescriptor>(
                            args: null,
                            runtimeType: contextType,
                            methodName: XFileServiceConstants.GetXFileEFRepositoryDescriptor
                    );
                    break;

                //
                case XRepositoryType.Mongo:
                    descriptor = XFileServiceHelper.GetXFileMongoRepositoryDescriptor();
                    break;

                //
                case XRepositoryType.InMemory:
                    descriptor = XFileServiceHelper.GetXFileInMemoryRepositoryDescriptor();
                    break;
            }

            //
            // Register XFile Repository Descriptor ...
            services.AddXRepository(
                lifeTime: lifeTime,
                descriptor: descriptor
            );

            //
            // Register Dto Services ...
            services.Add(
                new ServiceDescriptor(typeof(IXFileServiceProvider), typeof(XFileServiceProvider), lifeTime)
            );
            services.Add(
                new ServiceDescriptor(typeof(IXFileRepositoryService), typeof(XFileRepositoryService), lifeTime)
            );
            services.Add(
                new ServiceDescriptor(typeof(IXFileRepositoryProvider), typeof(XFileRepositoryProvider), lifeTime)
            );

            //
            // Register Additional Service ...
            services.Add(
                new ServiceDescriptor(typeof(IXFileTagProvider), typeof(XFileTagProvider), lifeTime)
            );
            services.Add(
                new ServiceDescriptor(typeof(IXFileTagProvided), typeof(XFileTagProvided), lifeTime)
            );
            services.Add(
                new ServiceDescriptor(typeof(IXFileProvider), typeof(XFileProvider), lifeTime)
            );

            //
            Log("Service Regitration Succeed ...");
        }
        #endregion        
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xFileService\Extensions\XModelExtensions.cs

using System.Collections.Generic;
using System.Linq;
using xCommons.Extensions;
using xDataService.Extensions;
using xDataService.Models;
using xFileService.Models.Dtos;
using xFileService.Models.Entities;

namespace xFileService.Extensions
{
    public static class XModelExtensions
    {
        /// <summary>
        /// Extract References of a Model ...
        /// </summary>
        /// <param name="source"></param>
        /// <returns></returns>
        public static IList<XReference<string>> GetReferences(
            this XFile source
        )
        {
            //
            var result = new List<XReference<string>>();

            //
            if (
                !source.IsNullOrDefault() &&
                !source.References.IsNullOrEmpty()
            )
            {
                //  
                result = source.References
                    .ParseXReferenceList<string>()
                    .ToList();
            }

            //
            return result;
        }

        /// <summary>
        /// Extract References of a Model ...
        /// </summary>
        /// <param name="source"></param>
        /// <returns></returns>
        public static IList<XReference<string>> GetReferences(
            this XFileDto source
        )
        {
            //
            var result = new List<XReference<string>>();

            //
            if (
                !source.IsNullOrDefault() &&
                !source.References.IsNullOrEmpty()
            )
            {
                //  
                result = source.References
                    .ParseXReferenceList<string>()
                    .ToList();
            }

            //
            return result;
        }

        /// <summary>
        /// Update a Model's References by Providing References List ...
        /// </summary>
        /// <param name="source"></param>
        /// <param name="references"></param>
        /// <param name="forceClean"></param>
        /// <returns></returns>
        public static XFile UpdateReferences(
            this XFile source,
            IList<XReference<string>> references,
            bool forceClean = true
        )
        {
            //
            XFile result = source;

            //
            if (!source.IsNullOrDefault())
            {
                //
                result = source;
                
                //
                if (forceClean)
                {
                    result.References = string.Empty;
                }

                //
                if (!references.IsNull() && 
                    references.HasChild())
                {
                    result.References = references.ToXReferenceString();
                }
            }

            //
            return result;
        }

        /// <summary>
        /// Update a Model's References by Providing References List ...
        /// </summary>
        /// <param name="source"></param>
        /// <param name="references"></param>
        /// <param name="forceClean"></param>
        /// <returns></returns>
        public static XFileDto UpdateReferences(
            this XFileDto source,
            IList<XReference<string>> references,
            bool forceClean = true
        )
        {
            //
            XFileDto result = source;

            //
            if (!source.IsNullOrDefault())
            {
                //
                result = source;
                
                //
                if (forceClean)
                {
                    result.References = string.Empty;
                }

                //
                if (!references.IsNull() && 
                    references.HasChild())
                {
                    result.References = references.ToXReferenceString();
                }
            }

            //
            return result;
        }
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xFileService\Helpers\XFileServiceHelper.cs

using System;
using GraphQL.Types;
using xDataService.Db;
using xDataService.Models;
using xDataService.Providers;
using xFileService.Interfaces;
using xFileService.Interfaces.Entities;
using xFileService.Models.Entities;
using xFileService.Providers.Entities;
using xFileService.Providers.GraphQL;

namespace xFileService.Helpers
{
    public static class XFileServiceHelper
    {
        //
        #region EF Repository Descriptor Provider(s) ...
        public static XEFRepositoryDescriptor<
            XFile,
            Guid,
            IXFileKeyGenerator,
            XFileKeyGenerator,
            IXFileRepositoryEvents,
            XFileRepositoryEvents,
            XFileGraphType,
            GuidGraphType,
            XFileGraphQuery,
            IXFileGraphQLTypeHelper,
            XFileGraphQLTypeHelper,
            XFileGraphSchema,
            IXFileRepository,
            XFileEFRepository<TContext>,
            TContext
        > GetXFileEFRepositoryDescriptor<TContext>()
        where TContext : XDbContext
        {
            //
            var result = new XEFRepositoryDescriptor<
                XFile,
                Guid,
                IXFileKeyGenerator,
                XFileKeyGenerator,
                IXFileRepositoryEvents,
                XFileRepositoryEvents,
                XFileGraphType,
                GuidGraphType,
                XFileGraphQuery,
                IXFileGraphQLTypeHelper,
                XFileGraphQLTypeHelper,
                XFileGraphSchema,
                IXFileRepository,
                XFileEFRepository<TContext>,
                TContext
            >();

            //
            return result;
        }

        public static XEFRepositoryDescriptor<
            XFile,
            Guid,
            IXFileKeyGenerator,
            XFileKeyGenerator,
            IXFileRepositoryEvents,
            XFileRepositoryEvents,
            XFileGraphType,
            GuidGraphType,
            XFileGraphQuery,
            IXFileGraphQLTypeHelper,
            XFileGraphQLTypeHelper,
            XFileGraphSchema,
            IXFileRepository,
            XFileEFRepository<TContext>,
            TContext,
            IXFileSeeder,
            TSeederImplementation
        > GetXFileEFRepositoryDescriptor<TContext, TSeederImplementation>()
        where TContext : XDbContext
        where TSeederImplementation : XBaseDbSeeder<XFile, Guid>
        {
            //
            var result = new XEFRepositoryDescriptor<
                XFile,
                Guid,
                IXFileKeyGenerator,
                XFileKeyGenerator,
                IXFileRepositoryEvents,
                XFileRepositoryEvents,
                XFileGraphType,
                GuidGraphType,
                XFileGraphQuery,
                IXFileGraphQLTypeHelper,
                XFileGraphQLTypeHelper,
                XFileGraphSchema,
                IXFileRepository,
                XFileEFRepository<TContext>,
                TContext,
                IXFileSeeder,
                TSeederImplementation
            >();

            //
            return result;
        }
        #endregion

        //
        #region Mongo Repository Descriptor Provider(s) ...
        public static XMongoRepositoryDescriptor<
            XFile,
            Guid,
            IXFileKeyGenerator,
            XFileKeyGenerator,
            IXFileRepositoryEvents,
            XFileRepositoryEvents,
            XFileGraphType,
            GuidGraphType,
            XFileGraphQuery,
            IXFileGraphQLTypeHelper,
            XFileGraphQLTypeHelper,
            XFileGraphSchema,
            IXFileRepository,
            XFileMongoRepository
        > GetXFileMongoRepositoryDescriptor()
        {
            //
            var result = new XMongoRepositoryDescriptor<
                XFile,
                Guid,
                IXFileKeyGenerator,
                XFileKeyGenerator,
                IXFileRepositoryEvents,
                XFileRepositoryEvents,
                XFileGraphType,
                GuidGraphType,
                XFileGraphQuery,
                IXFileGraphQLTypeHelper,
                XFileGraphQLTypeHelper,
                XFileGraphSchema,
                IXFileRepository,
                XFileMongoRepository
            >();

            //
            return result;
        }

        public static XMongoRepositoryDescriptor<
            XFile,
            Guid,
            IXFileKeyGenerator,
            XFileKeyGenerator,
            IXFileRepositoryEvents,
            XFileRepositoryEvents,
            XFileGraphType,
            GuidGraphType,
            XFileGraphQuery,
            IXFileGraphQLTypeHelper,
            XFileGraphQLTypeHelper,
            XFileGraphSchema,
            IXFileRepository,
            XFileMongoRepository,
            IXFileSeeder,
            TSeederImplementation
        > GetXFileMongoRepositoryDescriptor<TSeederImplementation>()
        where TSeederImplementation : XBaseDbSeeder<XFile, Guid>
        {
            //
            var result = new XMongoRepositoryDescriptor<
                XFile,
                Guid,
                IXFileKeyGenerator,
                XFileKeyGenerator,
                IXFileRepositoryEvents,
                XFileRepositoryEvents,
                XFileGraphType,
                GuidGraphType,
                XFileGraphQuery,
                IXFileGraphQLTypeHelper,
                XFileGraphQLTypeHelper,
                XFileGraphSchema,
                IXFileRepository,
                XFileMongoRepository,
                IXFileSeeder,
                TSeederImplementation
            >();

            //
            return result;
        }
        #endregion

        //
        #region InMemory Repository Descriptor Provider(s) ...
        public static XInMemoryRepositoryDescriptor<
            XFile,
            Guid,
            IXFileKeyGenerator,
            XFileKeyGenerator,
            IXFileRepositoryEvents,
            XFileRepositoryEvents,
            XFileGraphType,
            GuidGraphType,
            XFileGraphQuery,
            IXFileGraphQLTypeHelper,
            XFileGraphQLTypeHelper,
            XFileGraphSchema,
            IXFileRepository,
            XFileInMemoryRepository
        > GetXFileInMemoryRepositoryDescriptor()
        {
            //
            var result = new XInMemoryRepositoryDescriptor<
                XFile,
                Guid,
                IXFileKeyGenerator,
                XFileKeyGenerator,
                IXFileRepositoryEvents,
                XFileRepositoryEvents,
                XFileGraphType,
                GuidGraphType,
                XFileGraphQuery,
                IXFileGraphQLTypeHelper,
                XFileGraphQLTypeHelper,
                XFileGraphSchema,
                IXFileRepository,
                XFileInMemoryRepository
            >();

            //
            return result;
        }

        public static XInMemoryRepositoryDescriptor<
            XFile,
            Guid,
            IXFileKeyGenerator,
            XFileKeyGenerator,
            IXFileRepositoryEvents,
            XFileRepositoryEvents,
            XFileGraphType,
            GuidGraphType,
            XFileGraphQuery,
            IXFileGraphQLTypeHelper,
            XFileGraphQLTypeHelper,
            XFileGraphSchema,
            IXFileRepository,
            XFileInMemoryRepository,
            IXFileSeeder,
            TSeederImplementation
        > GetXFileInMemoryRepositoryDescriptor<TSeederImplementation>()
        where TSeederImplementation : XBaseDbSeeder<XFile, Guid>
        {
            //
            var result = new XInMemoryRepositoryDescriptor<
                XFile,
                Guid,
                IXFileKeyGenerator,
                XFileKeyGenerator,
                IXFileRepositoryEvents,
                XFileRepositoryEvents,
                XFileGraphType,
                GuidGraphType,
                XFileGraphQuery,
                IXFileGraphQLTypeHelper,
                XFileGraphQLTypeHelper,
                XFileGraphSchema,
                IXFileRepository,
                XFileInMemoryRepository,
                IXFileSeeder,
                TSeederImplementation
            >();

            //
            return result;
        }
        #endregion
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xFileService\Interfaces\Dtos\IXFileDtoHub.cs

using System;
using xFileService.Models.Dtos;
using xFileService.Models.Entities;
using xPushService.Interfaces;

namespace xFileService.Interfaces.Dtos
{
    public interface IXFileDtoHub : IXBaseDtoHub<XFile, XFileDto, Guid>
    { }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xFileService\Interfaces\Dtos\IXFileRepositoryService.cs

using System;
using xDataService.Interfaces;
using xFileService.Models.Dtos;
using xFileService.Models.Entities;

namespace xFileService.Interfaces.Dtos
{
    public interface IXFileRepositoryService : IXBaseRepositoryService<XFile, XFileDto, Guid>
    { }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xFileService\Interfaces\Dtos\IXFileServiceProvider.cs

using System;
using xFileService.Models.Dtos;
using xFileService.Models.Entities;
using xFileService.Providers.Dtos;
using xPushService.Interfaces;

namespace xFileService.Interfaces.Dtos
{
    public interface IXFileServiceProvider : IXBaseDtoProvider<XFile, XFileDto, Guid, XFileDtoHub>
    { }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xFileService\Interfaces\Entities\IXFileEntityHub.cs

using System;
using xFileService.Models.Entities;
using xPushService.Interfaces;

namespace xFileService.Interfaces.Entities
{
    public interface IXFileEntityHub : IXBaseEntityHub<XFile, Guid>
    { }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xFileService\Interfaces\Entities\IXFileGraphQLTypeHelper.cs

using System;
using xDataService.Interfaces;
using xFileService.Models.Entities;

namespace xFileService.Interfaces.Entities
{
    public interface IXFileGraphQLTypeHelper : IXBaseGraphQLTypeHelper<XFile, Guid>
    { }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xFileService\Interfaces\Entities\IXFileKeyGenerator.cs

using System;
using xDataService.Interfaces;
using xFileService.Models.Entities;

namespace xFileService.Interfaces.Entities
{
    public interface IXFileKeyGenerator : IXKeyGenerator<XFile, Guid>
    { }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xFileService\Interfaces\Entities\IXFileRepository.cs

using System;
using xDataService.Interfaces;
using xFileService.Models.Entities;

namespace xFileService.Interfaces.Entities
{
    public interface IXFileRepository : IXBaseRepository<XFile, Guid>
    { }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xFileService\Interfaces\Entities\IXFileRepositoryEvents.cs

using xDataService.Interfaces;
using xFileService.Models.Entities;

namespace xFileService.Interfaces.Entities
{
    public interface IXFileRepositoryEvents : IXBaseRepositoryEvents<XFile>
    { }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xFileService\Interfaces\Entities\IXFileRepositoryProvider.cs

using System;
using xFileService.Models.Entities;
using xFileService.Providers.Entities;
using xPushService.Interfaces;

namespace xFileService.Interfaces.Entities
{
    public interface IXFileRepositoryProvider : IXBaseEntityProvider<XFile, Guid, XFileEntityHub>
    { }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xFileService\Interfaces\Entities\IXFileSeeder.cs

using System;
using xDataService.Interfaces;
using xFileService.Models.Entities;

namespace xFileService.Interfaces.Entities
{
    public interface IXFileSeeder : IXBaseDbSeeder<XFile, Guid>
    { }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xFileService\Interfaces\IXFileProvider.cs

using System;
using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using xFileService.Models.Dtos;
using xFileService.Models.Entities;
using xFileService.Providers.Dtos;
using xIdentityModels.Models;
using xIdentityService.Interfaces;
using xTagService.Interfaces;

namespace xFileService.Interfaces
{
    public interface IXFileProvider : IXBaseProvidedHasTag<XFile, XFileDto, Guid, XFileDtoHub>, IXBaseReferenced<XFile, Guid>
    {
        //
        #region Tools ...
        /// <summary>
        /// Stream Specified File ...
        /// </summary>
        /// <param name="id"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        Task<FileStreamResult> Stream(
            Guid id,
            CancellationToken cancellationToken = default
        );

        /// <summary>
        /// Stream Specified File ...
        /// </summary>
        /// <param name="name"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        Task<FileStreamResult> Stream(
            string name,
            CancellationToken cancellationToken = default
        );

        /// <summary>
        /// Download Specified File ...
        /// </summary>
        /// <param name="id"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        Task<PhysicalFileResult> Download(
            Guid id,
            CancellationToken cancellationToken = default
        );

        /// <summary>
        /// Download Specified File ...
        /// </summary>
        /// <param name="name"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        Task<PhysicalFileResult> Download(
            string name,
            CancellationToken cancellationToken = default
        );

        /// <summary>
        /// Upload Files ...
        /// </summary>
        /// <param name="files"></param>
        /// <param name="userInfo"></param>
        /// <param name="connectionId"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        Task<IEnumerable<XFileDto>> Upload(
            IFormFileCollection files,
            XUserClaimsInfoDto userInfo = null,
            string connectionId = null,
            CancellationToken cancellationToken = default
        );

        /// <summary>
        /// Remove Specified Files ...
        /// </summary>
        /// <param name="ids"></param>
        /// <param name="userInfo"></param>
        /// <param name="connectionId"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        Task<IEnumerable<Guid>> Remove(
            string ids,
            XUserClaimsInfoDto userInfo = null,
            string connectionId = null,
            CancellationToken cancellationToken = default
        );

        /// <summary>
        /// Retrieve Specified File Streaming Info ...
        /// </summary>
        /// <param name="id"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        Task<XFileStreamDescriptorDto> GetFileDescriptor(
            Guid id,
            CancellationToken cancellationToken = default
        );

        /// <summary>
        /// Retrieve Specified File Streaming Info ...
        /// </summary>
        /// <param name="fileName"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        Task<XFileStreamDescriptorDto> GetFileDescriptor(
            string fileName,
            CancellationToken cancellationToken = default
        );
        #endregion        
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xFileService\Interfaces\IXFileProviderController.cs

using System;
using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using xFileService.Models.Dtos;
using xFileService.Models.Entities;
using xFileService.Providers.Dtos;
using xIdentityService.Interfaces;
using xTagService.Interfaces;

namespace xFileService.Interfaces
{
    public interface IXFileProviderController : IXBaseProvidedHasTagController<XFile, XFileDto, Guid, XFileDtoHub>, IXBaseReferencedController<XFile, Guid>
    {
        //
        #region Tools ...
        /// <summary>
        /// Stream Specified File ...
        /// </summary>
        /// <param name="id"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        [HttpGet("{id}/Stream/ById")]
        Task<ActionResult> Stream(
            [FromRoute] Guid id,
            CancellationToken cancellationToken = default
        );

        /// <summary>
        /// Stream Specified File ...
        /// </summary>
        /// <param name="name"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        [HttpGet("{name}/Stream/ByName")]
        Task<ActionResult> Stream(
            [FromRoute] string name,
            CancellationToken cancellationToken = default
        );

        /// <summary>
        /// Download Specified File ...
        /// </summary>
        /// <param name="id"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        [HttpGet("{id}/Download/ById")]
        Task<ActionResult> Download(
            [FromRoute] Guid id,
            CancellationToken cancellationToken = default
        );

        /// <summary>
        /// Download Specified File ...
        /// </summary>
        /// <param name="name"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        [HttpGet("{name}/Download/ByName")]
        Task<ActionResult> Download(
            string name,
            CancellationToken cancellationToken = default
        );

        /// <summary>
        /// Upload Files ...
        /// </summary>
        /// <param name="files"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        [HttpPost("Upload")]
        [RequestSizeLimit(966_367_641)]        
        Task<ActionResult<IEnumerable<XFileDto>>> Upload(
            [FromForm] IFormFileCollection files,
            CancellationToken cancellationToken = default
        );

        /// <summary>
        /// Remove Specified Files ...
        /// </summary>
        /// <param name="ids"></param>
        /// <param name="userInfo"></param>
        /// <param name="connectionId"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        [HttpDelete("")]
        Task<ActionResult<IEnumerable<Guid>>> Remove(
            [FromQuery] string ids,
            CancellationToken cancellationToken = default
        );
        #endregion                
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xFileService\Interfaces\IXFileTagProvided.cs

using System;
using xFileService.Models.Dtos;
using xFileService.Models.Entities;
using xFileService.Providers.Dtos;
using xTagService.Interfaces;

namespace xFileService.Interfaces
{
    public interface IXFileTagProvided : IXTagProvided<XFile, XFileDto, Guid, XFileDtoHub>
    { }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xFileService\Interfaces\IXFileTagProvider.cs

using System;
using xTagService.Interfaces;

namespace xFileService.Interfaces
{
    public interface IXFileTagProvider : IXBaseTagProvider<Guid>
    { }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xFileService\Models\Dtos\XFileDto.cs

using System;
using xCommons.Constants;
using xModels.Base;
using xModels.Dtos;

namespace xFileService.Models.Dtos
{
    public class XFileDto : XBaseGuidIDEntityDto
    {
        public XFileType Type { get; set; }
        public string Name { get; set; }
        public string Thumb { get; set; }
        public string Path { get; set; }
        public string ThumbPath { get; set; }
        public DateTime UploadedOn { get; set; }
        public string FileName { get; set; }

        public string OwnerId { get; set; }
        public XPersonDto Owner { get; set; }

        public string References { get; set; }
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xFileService\Models\Dtos\XFileStreamDescriptorDto.cs

using System.IO;
using xModels.Base;

namespace xFileService.Models.Dtos
{
    public class XFileStreamDescriptorDto : XBaseDto
    {
        public Stream Stream { get; set; }
        public string MIMEType { get; set; }
        public string Name { get; set; }
        public string Path { get; set; }
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xFileService\Models\Entities\XFile.cs

using System;
using System.ComponentModel.DataAnnotations;
using xCommons.Constants;
using xModels.Base;

namespace xFileService.Models.Entities
{
    /// <summary>
    /// Specified File in Server ...
    /// </summary>
    public class XFile : XBaseGuidIDEntity
    {
        /// <summary>
        /// Specified File Type ...
        /// </summary>
        /// <value></value>
        public XFileType Type { get; set; }

        /// <summary>
        /// User Identifier ...
        /// </summary>
        /// <value></value>
        [Required]
        [StringLength(255)]
        public string OwnerId { get; set; }

        /// <summary>
        /// File Name on Server ...
        /// </summary>
        /// <value></value>
        [Required]
        [StringLength(255)]
        public string Name { get; set; }

        /// <summary>
        /// File Path On Server ...
        /// </summary>
        /// <value></value>
        [Required]
        public string Path { get; set; }

        /// <summary>
        /// Thumbnail FIle Name ...
        /// if File Type Supported Thumbnail ...
        /// </summary>
        /// <value></value>
        public string Thumb { get; set; }

        /// <summary>
        /// Thumbnail File Path ...
        /// if File Type Supported Thumbnail ...
        /// </summary>
        /// <value></value>
        public string ThumbPath { get; set; }

        /// <summary>
        /// File Uploading Time ...
        /// </summary>
        /// <value></value>
        public DateTime UploadedOn { get; set; }

        /// <summary>
        /// Request For Upload File Name on Client ...
        /// </summary>
        /// <value></value>
        public string FileName { get; set; }

        /// <summary>
        /// Comma Separated List Which Provides Pointer to Specified 
        /// Model for Describe ...
        /// </summary>
        /// <value></value>
        public string References { get; set; }        
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xFileService\Providers\Dtos\XFileDtoHub.cs

using System;
using Microsoft.Extensions.Logging;
using xFileService.Interfaces.Dtos;
using xFileService.Models.Dtos;
using xFileService.Models.Entities;
using xPushService.Base;

namespace xFileService.Providers.Dtos
{
    public class XFileDtoHub : XBaseDtoHub<XFile, XFileDto, Guid>, IXFileDtoHub
    {
        public XFileDtoHub(
            ILogger<XFileDtoHub> logger
        ) : base(logger)
        { }
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xFileService\Providers\Dtos\XFileRepositoryService.cs

using System;
using System.Collections.Generic;
using AutoMapper;
using xDataService.Providers;
using xFileService.Interfaces.Dtos;
using xFileService.Interfaces.Entities;
using xFileService.Models.Dtos;
using xFileService.Models.Entities;

namespace xFileService.Providers.Dtos
{
    public class XFileRepositoryService : XBaseRepositoryService<XFile, XFileDto, Guid>, IXFileRepositoryService
    {
        public XFileRepositoryService(
            IXFileRepository repository, 
            IEnumerable<Profile> mapperProfiles = null
        ) : base(
            repository, 
            mapperProfiles
        )
        { }
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xFileService\Providers\Dtos\XFileServiceProvider.cs

using System;
using Microsoft.AspNetCore.SignalR;
using xDataService.Configuration;
using xFileService.Interfaces.Dtos;
using xFileService.Models.Dtos;
using xFileService.Models.Entities;
using xIdentityService.Interfaces;
using xPushService.Base;

namespace xFileService.Providers.Dtos
{
    public class XFileServiceProvider : XBaseDtoProvider<XFile, XFileDto, Guid, XFileDtoHub>, IXFileServiceProvider
    {
        public XFileServiceProvider(
            IHubContext<XFileDtoHub> hub,
            XDataServiceConfiguration dataConfiguration,
            IXFileRepositoryService service,
            IXIdentityProvider identityProvider = null
        ) : base(
            hub,
            dataConfiguration,
            service,
            identityProvider
        )
        { }
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xFileService\Providers\Entities\XFileEFRepository.cs

using System;
using xDataService.Configuration;
using xDataService.Db;
using xDataService.Interfaces;
using xDataService.Providers;
using xFileService.Interfaces.Entities;
using xFileService.Models.Entities;

namespace xFileService.Providers.Entities
{
    public class XFileEFRepository<TContext> : XBaseEFRepository<XFile, Guid, TContext>, IXFileRepository
    where TContext : XDbContext
    {
        public XFileEFRepository(
            IXUnitOfWorks<TContext> unitOfWorks,
            XDataServiceConfiguration configuration,
            IXFileKeyGenerator keyGenerator = null,
            IXFileRepositoryEvents baseRepositoryEvents = null
        ) : base(
            unitOfWorks,
            configuration,
            keyGenerator,
            baseRepositoryEvents
        )
        { }
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xFileService\Providers\Entities\XFileEntityHub.cs

using System;
using Microsoft.Extensions.Logging;
using xFileService.Interfaces.Entities;
using xFileService.Models.Entities;
using xPushService.Base;

namespace xFileService.Providers.Entities
{
    public class XFileEntityHub : XBaseEntityHub<XFile, Guid>, IXFileEntityHub
    {
        public XFileEntityHub(
            ILogger<XFileEntityHub> logger
        ) : base(logger)
        { }
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xFileService\Providers\Entities\XFileInMemoryRepository.cs

using System;
using xDataService.Configuration;
using xDataService.Providers;
using xFileService.Interfaces.Entities;
using xFileService.Models.Entities;

namespace xFileService.Providers.Entities
{
    public class XFileInMemoryRepository : XBaseInMemoryRepository<XFile, Guid>, IXFileRepository
    {
        public XFileInMemoryRepository(
            XDataServiceConfiguration configuration,
            IXFileKeyGenerator keyGenerator = null,
            IXFileRepositoryEvents baseRepositoryEvents = null
        ) : base(
            configuration,
            keyGenerator,
            baseRepositoryEvents
        )
        { }
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xFileService\Providers\Entities\XFileKeyGenerator.cs

using xDataService.Providers;
using xFileService.Interfaces.Entities;
using xFileService.Models.Entities;

namespace xFileService.Providers.Entities
{
    public class XFileKeyGenerator : XGuidKeyGenerator<XFile>, IXFileKeyGenerator
    { }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xFileService\Providers\Entities\XFileMongoRepository.cs

using System;
using xDataService.Configuration;
using xDataService.Providers;
using xFileService.Interfaces.Entities;
using xFileService.Models.Entities;

namespace xFileService.Providers.Entities
{
    public class XFileMongoRepository : XBaseMongoRepository<XFile, Guid>, IXFileRepository
    {
        public XFileMongoRepository(
            XDataBaseConfiguration dbConfiguration,
            XDataServiceConfiguration configuration,
            string collectionName = null,
            IXFileKeyGenerator keyGenerator = null,
            IXFileRepositoryEvents baseRepositoryEvents = null
        ) : base(
            dbConfiguration,
            configuration,
            collectionName,
            keyGenerator,
            baseRepositoryEvents
        )
        { }
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xFileService\Providers\Entities\XFileRepositoryEvents.cs

using xDataService.Providers;
using xFileService.Interfaces.Entities;
using xFileService.Models.Entities;

namespace xFileService.Providers.Entities
{
    public class XFileRepositoryEvents : XBaseRepositoryEvents<XFile>, IXFileRepositoryEvents
    { }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xFileService\Providers\Entities\XFileRepositoryProvider.cs

using System;
using Microsoft.AspNetCore.SignalR;
using xDataService.Configuration;
using xFileService.Interfaces.Entities;
using xFileService.Models.Entities;
using xIdentityService.Interfaces;
using xPushService.Base;

namespace xFileService.Providers.Entities
{
    public class XFileRepositoryProvider : XBaseEntityProvider<XFile, Guid, XFileEntityHub>, IXFileRepositoryProvider
    {
        public XFileRepositoryProvider(
            IHubContext<XFileEntityHub> hub,
            IXFileRepository repository,
            XDataServiceConfiguration dataConfiguration,
            IXIdentityProvider identityProvider = null
        ) : base(
            hub,
            repository,
            dataConfiguration,
            identityProvider
        )
        { }
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xFileService\Providers\Entities\XFileSeederBase.cs

using System;
using xDataService.Configuration;
using xDataService.Providers;
using xFileService.Interfaces.Entities;
using xFileService.Models.Entities;

namespace xFileService.Providers.Entities
{
    public abstract class XFileSeederBase : XBaseDbSeeder<XFile, Guid>, IXFileSeeder
    {
        protected XFileSeederBase(
            string entity,
            string database,
            IXFileRepository repository,
            XDataServiceConfiguration dataServiceConfiguration
        ) : base(
            entity,
            database,
            repository,
            dataServiceConfiguration
        )
        { }
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xFileService\Providers\GraphQL\XFileGraphQLTypeHelper.cs

using System;
using xDataService.Configuration;
using xDataService.GraphQL;
using xFileService.Constants;
using xFileService.Interfaces.Entities;
using xFileService.Models.Entities;

namespace xFileService.Providers.GraphQL
{
    public class XFileGraphQLTypeHelper : XBaseGraphQLTypeHelper<XFile, Guid>, IXFileGraphQLTypeHelper
    {
        public XFileGraphQLTypeHelper(
            XDataServiceConfiguration configuration
        ) : base(configuration)
        { }

        public override string GetInQueryCollectionName()
        {
            return XFileServiceConstants.XFileCollectionName;
        }

        public override string GetInQuerySingleName()
        {
            return XFileServiceConstants.XFileSingleName;
        }
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xFileService\Providers\GraphQL\XFileGraphQuery.cs

using System;
using GraphQL.Types;
using xDataService.Configuration;
using xDataService.GraphQL;
using xFileService.Interfaces.Entities;
using xFileService.Models.Entities;

namespace xFileService.Providers.GraphQL
{
    public class XFileGraphQuery : XBaseGraphQLQuery<XFile, Guid, XFileGraphType, GuidGraphType>
    {
        public XFileGraphQuery(
            XDataServiceConfiguration configuration,
            IXFileRepository repository,
            IXFileGraphQLTypeHelper helper
        ) : base(
            configuration,
            repository,
            helper
        )
        { }
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xFileService\Providers\GraphQL\XFileGraphSchema.cs

using System;
using GraphQL.Types;

namespace xFileService.Providers.GraphQL
{
    public class XFileGraphSchema : Schema
    {
        public XFileGraphSchema(IServiceProvider services) : base(services)
        {
            Query = (XFileGraphQuery)services.GetService(typeof(XFileGraphQuery));
        }

    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xFileService\Providers\GraphQL\XFileGraphType.cs

using System;
using xDataService.GraphQL;
using xFileService.Models.Entities;

namespace xFileService.Providers.GraphQL
{
    public class XFileGraphType : XBaseGraphObjectType<XFile, Guid>
    {
        public XFileGraphType() : base()
        {
            Field(x => x.Type);
            Field(x => x.Name);
            Field(x => x.Path);
            Field(x => x.Thumb);
            Field(x => x.OwnerId);
            Field(x => x.FileName);
            Field(x => x.ThumbPath);
            Field(x => x.UploadedOn);
            Field(x => x.References);
        }
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xFileService\Providers\XFileEntityRegisterar.cs

using System;
using Microsoft.EntityFrameworkCore;
using xDataService.Interfaces;
using xDataService.Providers;
using xFileService.Configurations.Entities;
using xFileService.Models.Entities;

namespace xFileService.Providers
{
    public class XFileEntityRegisterar : XBaseEntityRegisterar, IXEntityRegisterar
    {
        public XFileEntityRegisterar()
        : base(nameof(XFileEntityRegisterar))
        {
            //
            // Add XFile Entity ...
            AddEntity<XFile, Guid>();
        }

        /// <summary>
        /// Configure Entities ...
        /// </summary>
        /// <param name="modelBuilder"></param>
        public override void ConfigureEntities(ModelBuilder modelBuilder)
        {
            //
            // Configure Entity Using Provided ...
            modelBuilder
                .ApplyConfigurationsFromAssembly(typeof(XFileEntityConfiguration).Assembly);

            //
            base.ConfigureEntities(modelBuilder);
        }
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xFileService\Providers\XFileProvider.cs

using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.StaticFiles;
using Microsoft.Extensions.FileProviders;
using xCommons.Extensions;
using xDataService.Models;
using xExceptions.Constants;
using xFileService.Extensions;
using xFileService.Interfaces;
using xFileService.Interfaces.Dtos;
using xFileService.Models.Dtos;
using xFileService.Models.Entities;
using xFileService.Providers.Dtos;
using xIdentityModels.Models;
using xStorageService.Interfaces;
using xTagService.Providers;

namespace xFileService.Providers
{
    public class XFileProvider : XBaseProvidedHasTag<XFile, XFileDto, Guid, XFileDtoHub>, IXFileProvider
    {
        private readonly IXFileServiceProvider provider;
        private readonly IXStorageProvider storageProvider;

        public XFileProvider(
            IXFileTagProvider tagProvider,
            IXFileServiceProvider provider,
            IXStorageProvider storageProvider
        ) : base(
            provider: provider,
            tagProvider: tagProvider,
            permittedRoles: new string[] { "admin" }
        )
        {
            this.provider = provider;
            this.storageProvider = storageProvider;
        }

        public override bool IsOwned(
            XFile item,
            XUserClaimsInfoDto userInfo
        )
        {
            //
            var result =
                !item.IsNullOrDefault() &&
                !userInfo.IsNullOrDefault() &&
                !item.OwnerId.IsNullOrEmpty() &&
                userInfo.UserId == item.OwnerId;

            //
            return result;
        }

        public override bool IsOwned(
            XFileDto item,
            XUserClaimsInfoDto userInfo
        )
        {
            //
            var result =
                !item.IsNullOrDefault() &&
                !userInfo.IsNullOrDefault() &&
                !item.OwnerId.IsNullOrEmpty() &&
                userInfo.UserId == item.OwnerId;

            //
            return result;
        }

        //
        #region Tools ...
        /// <summary>
        /// Stream Specified File ...
        /// </summary>
        /// <param name="id"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public virtual async Task<FileStreamResult> Stream(
            Guid id,
            CancellationToken cancellationToken = default
        )
        {
            //
            // Validate Args ...
            var isValid = !id.IsNull() &&
                !id.IsDefaultGuid();
            if (!isValid)
            {
                XException.InvalidArgs.Throw();
            }

            //
            // Generate Stream Info and Validate it ...
            var stream = await GetFileDescriptor(
                id: id,
                cancellationToken: cancellationToken
            );
            if (stream.IsNull())
            {
                XException.NotFound.Throw();
            }

            //
            // Generate Result Model ...
            var result = new FileStreamResult(
                stream.Stream,
                stream.MIMEType
            )
            {
                FileDownloadName = stream.Name
            };

            //
            return result;
        }

        /// <summary>
        /// Stream Specified File ...
        /// </summary>
        /// <param name="name"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public virtual async Task<FileStreamResult> Stream(
            string name,
            CancellationToken cancellationToken = default
        )
        {
            //
            // Validate Args ...
            var isValid = !name.IsNullOrEmpty();
            if (!isValid)
            {
                XException.InvalidArgs.Throw();
            }

            //
            // Generate Stream Info and Validate it ...
            var stream = await GetFileDescriptor(
                fileName: name,
                cancellationToken: cancellationToken
            );
            if (stream.IsNull())
            {
                XException.NotFound.Throw();
            }

            //
            // Generate Result Model ...
            var result = new FileStreamResult(
                stream.Stream,
                stream.MIMEType
            )
            {
                FileDownloadName = stream.Name
            };

            //
            return result;
        }

        /// <summary>
        /// Download Specified File ...
        /// </summary>
        /// <param name="id"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public virtual async Task<PhysicalFileResult> Download(
            Guid id,
            CancellationToken cancellationToken = default
        )
        {
            //
            // Validate Args ...
            var isValid = !id.IsNull() &&
                !id.IsDefaultGuid();
            if (!isValid)
            {
                XException.InvalidArgs.Throw();
            }

            //
            // Generate Stream Info and Validate it ...
            var stream = await GetFileDescriptor(
                id: id,
                cancellationToken: cancellationToken
            );
            if (stream.IsNull())
            {
                XException.NotFound.Throw();
            }

            //
            // Generate Result Model ...
            var result = new PhysicalFileResult(
                stream.Path,
                stream.MIMEType
            )
            {
                FileDownloadName = stream.Name
            };

            //
            return result;
        }

        /// <summary>
        /// Download Specified File ...
        /// </summary>
        /// <param name="name"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public virtual async Task<PhysicalFileResult> Download(
            string name,
            CancellationToken cancellationToken = default
        )
        {
            //
            // Validate Args ...
            var isValid = !name.IsNullOrEmpty();
            if (!isValid)
            {
                XException.InvalidArgs.Throw();
            }

            //
            // Generate Stream Info and Validate it ...
            var stream = await GetFileDescriptor(
                fileName: name,
                cancellationToken: cancellationToken
            );
            if (stream.IsNull())
            {
                XException.NotFound.Throw();
            }

            //
            // Generate Result Model ...
            var result = new PhysicalFileResult(
                stream.Path,
                stream.MIMEType
            )
            {
                FileDownloadName = stream.Name
            };

            //
            return result;
        }

        /// <summary>
        /// Upload Files ...
        /// </summary>
        /// <param name="files"></param>
        /// <param name="userInfo"></param>
        /// <param name="connectionId"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public virtual async Task<IEnumerable<XFileDto>> Upload(
            IFormFileCollection files,
            XUserClaimsInfoDto userInfo = null,
            string connectionId = null,
            CancellationToken cancellationToken = default
        )
        {
            //
            // Validate Args ...
            var isValid = !files.IsNull() &&
                files.HasChild() &&
                !userInfo.IsNullOrDefault();
            if (!isValid)
            {
                XException.InvalidArgs.Throw();
            }

            //
            // Save Files On Server Side Physically ...
            // and Validate it ...
            var uploadResults = await storageProvider
                .HandleFilesSave(files);
            isValid = uploadResults.HasChild();
            if (!isValid)
            {
                XException.ActionFailed.Throw();
            }

            //
            // Prepare Result ...
            var result = new List<XFileDto>();
            foreach (var ur in uploadResults)
            {
                //
                var fileType = storageProvider.GetFileType(ur.FileName);

                //
                // Create Item Model ...
                var item = new XFileDto
                {
                    Type = fileType,
                    FileName = ur.Name,
                    Name = ur.FileName,
                    Path = ur.FilePath,
                    Thumb = ur.Thmbnail,
                    OwnerId = userInfo.UserId,
                    ThumbPath = ur.ThmbnailPath,
                    UploadedOn = DateTime.UtcNow,
                };

                //
                try
                {
                    //
                    // Add Entity Model to DB ...
                    item = await Add(
                        item: item,
                        userInfo: userInfo,
                        connectionId: connectionId,
                        cancellationToken: cancellationToken
                    );

                    //
                    result.Add(item);
                }
                catch { }
            }

            //
            return result;
        }

        /// <summary>
        /// Remove Specified Files ...
        /// </summary>
        /// <param name="ids"></param>
        /// <param name="userInfo"></param>
        /// <param name="connectionId"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public virtual async Task<IEnumerable<Guid>> Remove(
            string ids,
            XUserClaimsInfoDto userInfo = null,
            string connectionId = null,
            CancellationToken cancellationToken = default
        )
        {
            //
            // Validate Args ...
            var isValid = !ids.IsNullOrEmpty() &&
                !userInfo.IsNullOrDefault();
            if (!isValid)
            {
                XException.InvalidArgs.Throw();
            }

            //
            // Parse ID(s) List ...
            var idsList = ids.ParseListGuid();
            isValid = !idsList.IsNull() &&
                idsList.HasChild();
            if (!isValid)
            {
                XException.ActionFailed.Throw();
            }

            //
            // Loop Through Parsed Ids and Try to Remove ...
            var result = new List<Guid>();
            foreach (var id in idsList)
            {
                //
                // Retrieve XFileDto and Validate it ...
                var model = await Get(id);
                isValid = !model.IsNull() && !model.Id.IsNull() && !model.Id.IsDefaultGuid();
                if (!isValid)
                {
                    continue;
                }

                //
                // Check Physical File Exists or not ...
                var fileFullPath = storageProvider.GetFileFullPath(model.Name);
                var thumbFullPath = model.Thumb.IsNullOrEmpty()
                    ? ""
                    : storageProvider.GetThumbnailFileFullPath(model.Thumb);
                var isFileExists = storageProvider.IsFileExists(fileFullPath);
                var isThumbExists = model.Thumb.IsNullOrEmpty()
                    ? false
                    : storageProvider.IsFileExists(thumbFullPath);

                //
                // Remove Physical Thumbnail File ...
                if (isThumbExists)
                {
                    //
                    try
                    {
                        //
                        // Removed Stored Thumbnail ...
                        storageProvider.DeleteFile(
                           fileFullPath: thumbFullPath,
                           forceFileExists: false
                        );
                    }
                    catch { }
                }

                //
                // Remove Pgysical File ...
                if (isFileExists)
                {
                    //
                    try
                    {
                        //
                        // Remove Stored File ...
                        storageProvider.DeleteFile(
                            fileFullPath: fileFullPath,
                            forceFileExists: false
                        );

                        //
                        // Remove Tags ...
                        await DetachTags(
                            id: id,
                            userInfo: userInfo,
                            connectionId: connectionId,
                            cancellationToken: cancellationToken
                        );
                    }
                    catch { }
                }

                //
                // Remove File Entty ...
                var item = await provider.RemoveAsync(
                    id: model.Id,
                    softDelete: false,
                    saveChanges: true,
                    connectionId: connectionId,
                    cancellationToken: cancellationToken
                );
                result.Add(model.Id);
            }

            //
            return result;
        }

        /// <summary>
        /// Retrieve Specified File Streaming Info ...
        /// </summary>
        /// <param name="id"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public virtual async Task<XFileStreamDescriptorDto> GetFileDescriptor(
            Guid id,
            CancellationToken cancellationToken = default
        )
        {
            //
            // Check File Model Exists or not ...
            var isExists = await IsExists(
                id: id,
                cancellationToken: cancellationToken
            );
            if (!isExists)
            {
                XException.NotFound.Throw();
            }

            //
            // Retrieve Item and Validate it ...
            var item = await Get(
                id: id,
                includeBuilder: null,
                cancellationToken: cancellationToken
            );
            if (item.IsNullOrDefault())
            {
                XException.NotFound.Throw();
            }

            //
            // Generate Physical File Path and Validate it ...
            var fileFullPath = storageProvider.GetFileFullPath(item.Name);
            isExists = storageProvider.IsFileExists(fileFullPath);
            var filePath = storageProvider.FilePathResolver(fileFullPath);
            filePath = Path.Combine("wwwroot", filePath);
            if (!isExists)
            {
                XException.NotFound.Throw();
            }

            //
            // Generate Physical File Info ...
            IFileInfo fileInfo = storageProvider.FileProvider.GetFileInfo(filePath);

            //
            // Prepare Default Streaming Requirements ...
            var mimeType = "application/octetstream";
            var readStream = fileInfo.CreateReadStream();
            var fileMimeProvider = new FileExtensionContentTypeProvider();
            var fileName = item.Name;

            //
            // Try to Find Physical File's Content Type ...
            fileMimeProvider.TryGetContentType(
                filePath,
                out mimeType
            );

            //
            // Prepare Result Model ...
            var result = new XFileStreamDescriptorDto
            {
                Stream = readStream,
                MIMEType = mimeType,
                Name = fileName,
                Path = fileFullPath
            };

            //
            return result;
        }

        /// <summary>
        /// Retrieve Specified File Streaming Info ...
        /// </summary>
        /// <param name="fileName"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public virtual async Task<XFileStreamDescriptorDto> GetFileDescriptor(
            string fileName,
            CancellationToken cancellationToken = default
        )
        {
            //
            if (fileName.IsNullOrEmpty())
            {
                XException.InvalidArgs.Throw();
            }
            var item = await FindOne(
                includeBuilder: null,
                predicate: e =>
                    e.Name.Contains(fileName) ||
                    e.Path.Contains(fileName) ||
                    e.Thumb.Contains(fileName) ||
                    e.FileName.Contains(fileName) ||
                    e.ThumbPath.Contains(fileName),
                cancellationToken: cancellationToken
            );
            var isExists = !item.IsNullOrDefault();
            if (!isExists)
            {
                XException.NotFound.Throw();
            }

            //
            // Extract File Name ...
            fileName = Path.GetFileName(fileName);

            //
            // Check File is Thumbnail or File ...
            var isThumb = fileName.StartsWith(storageProvider.Configuration.ThumbPrefix);
            var isFile = fileName.StartsWith(storageProvider.Configuration.FilePrefix);

            //
            // Check File Type is Valid ...
            isExists = isThumb || isFile;
            if (!isExists)
            {
                XException.UnsupportedFileType.Throw();
            }

            //
            // Extract File Full Path ...
            var fileFullPath = "";
            if (isThumb)
            {
                fileFullPath = storageProvider.GetThumbnailFileFullPath(fileName);
            }
            else
            {
                fileFullPath = storageProvider.GetFileFullPath(fileName);
            }

            //
            // Check Physical File Exists or Not ...
            isExists = storageProvider.IsFileExists(fileFullPath);
            if (!isExists)
            {
                XException.NotFound.Throw();
            }

            //
            // Generate Physical File Info ...
            var filePath = storageProvider.FilePathResolver(fileFullPath);
            filePath = Path.Combine("wwwroot", filePath);
            IFileInfo fileInfo = storageProvider.FileProvider.GetFileInfo(filePath);

            //
            // Prepare Default Streaming Requirements ...
            var mimeType = "application/octetstream";
            var readStream = fileInfo.CreateReadStream();
            var fileMimeProvider = new FileExtensionContentTypeProvider();

            //
            // Try to Find Physical File's Content Type ...
            fileMimeProvider.TryGetContentType(filePath, out mimeType);

            //
            // Prepare Result Model ...
            var result = new XFileStreamDescriptorDto
            {
                Stream = readStream,
                MIMEType = mimeType,
                Name = fileName,
                Path = fileFullPath
            };

            //
            return result;
        }
        #endregion

        //
        #region Referenced Actions ...
        /// <summary>
        /// Get Reference Identifier for Specified Provider and Specified Item ...
        /// </summary>
        /// <param name="providedFor"></param>
        /// <param name="forProvidedId"></param>
        /// <returns></returns>
        public string GetIdentifier<TReferenceKey>(
            string providedFor,
            TReferenceKey forProvidedId
        )
        {
            //
            var result = $"{providedFor}_{forProvidedId}";

            //
            return result;
        }

        /// <summary>
        /// Check Specified Item has Refernce to Provider ...
        /// </summary>
        /// <param name="providedFor"></param>
        /// <param name="forProvidedId"></param>
        /// <param name="id"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public async Task<bool> IsProvidedFor<TReferenceKey>(
            string providedFor,
            TReferenceKey forProvidedId,
            Guid id,
            CancellationToken cancellationToken = default
        )
        {
            //
            // Validate ...
            var isValid =
                !id.IsNull() &&
                !id.IsDefaultGuid() &&
                !forProvidedId.IsNull() &&
                !providedFor.IsNullOrEmpty();
            if (!isValid)
            {
                XException.InvalidArgs.Throw();
            }

            //
            // Check Exists ...
            isValid = await IsExists(
                id: id,
                cancellationToken: cancellationToken
            );
            if (!isValid)
            {
                XException.NotFound.Throw();
            }

            //
            var item = await Get(
                id: id,
                includeBuilder: null,
                cancellationToken: cancellationToken
            );
            isValid = !item.IsNullOrDefault();
            if (!isValid)
            {
                XException.ActionFailed.Throw();
            }

            //
            var references = item.GetReferences();
            var result =
                references.IsNull() &&
                references.HasChild() &&
                references.Any(r =>
                    r.ProvidedFor == providedFor &&
                    r.ReferencedTo == $"{forProvidedId}"
                );

            //
            return result;
        }

        /// <summary>
        /// Add Specified Reference to Specified Item ...
        /// </summary>
        /// <param name="providedFor"></param>
        /// <param name="forProvidedId"></param>
        /// <param name="id"></param>
        /// <param name="forIndex"></param>
        /// <param name="userInfo"></param>
        /// <param name="connectionId"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public async Task AddReference<TReferenceKey>(
            string providedFor,
            TReferenceKey forProvidedId,
            Guid id,
            int forIndex = 0,
            XUserClaimsInfoDto userInfo = null,
            string connectionId = null,
            CancellationToken cancellationToken = default
        )
        {
            //
            // Validate ...
            var isValid =
                !providedFor.IsNullOrEmpty() &&
                !id.IsNull() &&
                !id.IsDefaultGuid() &&
                !providedFor.IsNull() &&
                !userInfo.IsNullOrDefault();
            if (!isValid)
            {
                XException.InvalidArgs.Throw();
            }

            //
            // Check Has Reference or not ...
            isValid = await IsProvidedFor(
                id: id,
                providedFor: providedFor,
                forProvidedId: forProvidedId,
                cancellationToken: cancellationToken
            );
            if (isValid)
            {
                //
                // Prevent Moving Forward Since Reference Exists ...
                return;
            }

            //
            // Check Permissions ...
            var item = await Get(
                id: id,
                includeBuilder: null,
                cancellationToken: cancellationToken
            );
            isValid =
                !item.IsNullOrDefault() &&
                (IsOwned(item, userInfo) ||
                HasPermision(userInfo));
            if (!isValid)
            {
                XException.NotAllowed.Throw();
            }

            //
            var reference = new XReference<string>
            {
                Index = forIndex,
                ProvidedFor = providedFor,
                ReferencedTo = $"{forProvidedId}"
            };
            var references = item.GetReferences();
            references.Add(reference);
            item = item.UpdateReferences(references);
            item = await Update(
                id: id,
                item: item,
                userInfo: userInfo,
                connectionId: connectionId,
                cancellationToken: cancellationToken
            );
        }

        /// <summary>
        /// Remove Specified Reference from Specified Item ...
        /// </summary>
        /// <param name="providedFor"></param>
        /// <param name="forProvidedId"></param>
        /// <param name="id"></param>
        /// <param name="forIndex"></param>
        /// <param name="userInfo"></param>
        /// <param name="connectionId"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public async Task RemoveReference<TReferenceKey>(
            string providedFor,
            TReferenceKey forProvidedId,
            Guid id,
            int forIndex = 0,
            XUserClaimsInfoDto userInfo = null,
            string connectionId = null,
            CancellationToken cancellationToken = default
        )
        {
            //
            // Validate ...
            var isValid =
                !id.IsNull() &&
                !id.IsDefaultGuid() &&
                !forProvidedId.IsNull() &&
                !userInfo.IsNullOrDefault() &&
                !providedFor.IsNullOrEmpty();
            if (!isValid)
            {
                XException.InvalidArgs.Throw();
            }

            //
            // Check Has Reference or not ...
            isValid = await IsProvidedFor(
                id: id,
                providedFor: providedFor,
                forProvidedId: forProvidedId,
                cancellationToken: cancellationToken
            );
            if (!isValid)
            {
                //
                // Prevent Moving Forward Since Reference not Exists ...
                return;
            }

            //
            // Check Permissions ...
            var item = await Get(
                id: id,
                includeBuilder: null,
                cancellationToken: cancellationToken
            );
            isValid =
                !item.IsNullOrDefault() &&
                (IsOwned(item, userInfo) ||
                HasPermision(userInfo));
            if (!isValid)
            {
                XException.NotAllowed.Throw();
            }

            //
            var identifier = GetIdentifier(
                providedFor: providedFor,
                forProvidedId: forProvidedId
            );
            var references = item.GetReferences();
            references = references
                    .Where(r =>
                        r.Index != forIndex &&
                        r.ProvidedFor != providedFor &&
                        r.ReferencedTo != $"{forProvidedId}"
                    )
                    .ToList();
            item = item.UpdateReferences(references);

            //
            item = await Update(
                item: item,
                id: item.Id,
                userInfo: userInfo,
                connectionId: connectionId,
                cancellationToken: cancellationToken
            );
        }

        /// <summary>
        /// Get Specified References ...
        /// </summary>
        /// <param name="providedFor"></param>
        /// <param name="id"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public async Task<IEnumerable<XReference<string>>> GetReferences(
            string providedFor,
            Guid id,
            CancellationToken cancellationToken = default
        )
        {
            //
            IList<XReference<string>> result = new List<XReference<string>>();

            //
            var item = await provider.GetAsync(
                id: id,
                includeBuilder: null,
                ignoreSoftDeleteds: true,
                cancellationToken: cancellationToken
            );
            var isValid = !item.IsNullOrDefault();
            if (!isValid)
            {
                return result;
            }

            //
            result = item.GetReferences();

            //
            result = result.Where(r =>
                r.ProvidedFor == providedFor
            )
            .ToList();

            //
            return result;
        }
        #endregion
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xFileService\Providers\XFileTagProvided.cs

using System;
using xCommons.Extensions;
using xFileService.Interfaces;
using xFileService.Interfaces.Dtos;
using xFileService.Models.Dtos;
using xFileService.Models.Entities;
using xFileService.Providers.Dtos;
using xIdentityModels.Models;
using xTagService.Interfaces;
using xTagService.Providers;

namespace xFileService.Providers
{
    public class XFileTagProvided : XBaseTagProvided<XFile, XFileDto, Guid, XFileDtoHub>, IXFileTagProvided
    {
        public XFileTagProvided(
            IXFileTagProvider tagProvider,
            IXFileServiceProvider provider
        ) : base(
            provider: provider,
            tagProvider: tagProvider,
            permittedRoles: new string[] { "admin" }
        )
        { }

        public override bool IsOwned(
            XFileDto item,
            XUserClaimsInfoDto userInfo
        )
        {
            //
            var result =
                !item.IsNullOrDefault() &&
                !userInfo.IsNullOrDefault() &&
                item.OwnerId == userInfo.UserId;

            //
            return result;
        }

        public override bool IsOwned(
            XFile item,
            XUserClaimsInfoDto userInfo
        )
        {
            //
            var result =
                !item.IsNullOrDefault() &&
                !userInfo.IsNullOrDefault() &&
                item.OwnerId == userInfo.UserId;

            //
            return result;
        }
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xFileService\Providers\XFileTagProvider.cs

using System;
using xFileService.Constants;
using xFileService.Interfaces;
using xTagService.Interfaces.Dtos;
using xTagService.Providers;

namespace xFileService.Providers
{
    public class XFileTagProvider : XBaseTagProvider<Guid>, IXFileTagProvider
    {
        public XFileTagProvider(
            IXTagServiceProvider tagProvider
        ) : base(
            tagProvider: tagProvider,
            providedFor: XFileServiceConstants.XFileTagProvided
        )
        { }
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xHttpService\Configurations\XHttpServiceConfiguration.cs

namespace xHttpService.Configurations {
    public partial class XHttpServiceConfiguration {
        /// <summary>
        /// Determines Http Handler Check SSL or not ...
        /// </summary>
        /// <value></value>
        public bool DisableSSLCheck { get; set; }
        public int DefaultClientTimeout { get; set; } = 360;
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xHttpService\Constants\ConfigurationNodeNames.cs

namespace xHttpService.Constants {
    public partial struct ConfigurationNodeNames {
        public const string HTTP_SERVICE_NODE_NAME = "HttpServiceConfiguration";
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xHttpService\Constants\XHttpMethod.cs

using xExceptions.Attributes;

namespace xHttpService.Constants {
    public enum XHttpMethod {
        [StringValue ("GET")]
        GET,

        [StringValue ("POST")]
        POST,

        [StringValue ("PUT")]
        PUT,

        [StringValue ("DELETE")]
        DELETE
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xHttpService\DI\XDIHelperExtension.cs

using System;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using xCommons.Extensions;
using xHttpService.Configurations;
using xHttpService.Constants;
using xHttpService.Interfaces;
using xHttpService.Providers;

namespace xHttpService.DI {
    public static partial class XDIHelperExtension {
        /// <summary>
        /// Retrieve XHttpService Configuration from AppSettings
        /// </summary>
        /// <param name="configuration"></param>
        /// <returns></returns>
        public static XHttpServiceConfiguration GetXHttpServiceConfiguration (this IConfiguration configuration) {
            //
            var xHttpSection = configuration.GetSection (ConfigurationNodeNames.HTTP_SERVICE_NODE_NAME);
            return xHttpSection.Get<XHttpServiceConfiguration> ();
        }

        /// <summary>
        /// Register XHttpService Configuration
        /// </summary>
        /// <param name="services"></param>
        /// <param name="configuration"></param>
        public static void AddXHttpServiceConfiguration (
            this IServiceCollection services,
            IConfiguration configuration
        ) {
            //
            var httpServiceConfiguration = configuration.GetXHttpServiceConfiguration ();
            services.AddXHttpServiceConfiguration(httpServiceConfiguration);
        }

        /// <summary>
        /// Register XHttpService Configuration
        /// </summary>
        /// <param name="services"></param>
        /// <param name="configuration"></param>
        public static void AddXHttpServiceConfiguration (
            this IServiceCollection services,
            XHttpServiceConfiguration configuration
        ) {
            //
            if (configuration.IsNull ()) {
                Console.WriteLine($"xHttpService: there is no provided configurations, using default ...");
                configuration = new XHttpServiceConfiguration ();
            }

            //
            services.AddSingleton<XHttpServiceConfiguration> (configuration);
        }

        /// <summary>
        /// Register XHttpService on DI ...
        /// </summary>
        /// <param name="services"></param>
        /// <param name="configuration"></param>
        public static void AddXHttpService (
            this IServiceCollection services,
            IConfiguration configuration
        ) {
            //
            // Register Service Configuration ...
            if (services.GetRegisteredService<XHttpServiceConfiguration> ().IsNull ()) {
                services.AddXHttpServiceConfiguration (configuration);
            }

            //
            // Register Service ...
            services.AddSingleton<IXHttpProvider, XHttpProvider> ();
        }

        /// <summary>
        /// Register XHttpService on DI ...
        /// </summary>
        /// <param name="services"></param>
        /// <param name="configuration"></param>
        public static void AddXHttpService (
            this IServiceCollection services,
            XHttpServiceConfiguration configuration
        ) {
            //
            // Register Service Configuration ...
            if (services.GetRegisteredService<XHttpServiceConfiguration> ().IsNull ()) {
                services.AddXHttpServiceConfiguration (configuration);
            }

            //
            // Register Service ...
            services.AddSingleton<IXHttpProvider, XHttpProvider> ();
        }
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xHttpService\Extensions\RestSharpExtensions.cs

using System.ComponentModel.DataAnnotations;
using AutoMapper.Mappers;
using RestSharp;
using xCommons.Constants;
using xCommons.Extensions;
using xModels.Dtos;

namespace xHttpService.Extensions
{
    public static partial class RestSharpExtensions
    {
        /// <summary>
        /// Attach an instance of XQuery to a RestRequest object
        /// </summary>
        /// <param name="source"></param>
        /// <param name="query"></param>
        /// <returns></returns>
        public static RestRequest AttachXQuery(
            this RestRequest source,
            XQuery query
        )
        {
            //
            if (query.IsNull())
            {
                return source;
            }

            //
            // ContainsDetail ...
            //
            var containsDetailKey = System.Uri.EscapeDataString(nameof(query.ContainsDetail));
            var containsDetailValue = query.ContainsDetail.AsHttpParamString();
            source.AddQueryParameter(containsDetailKey, containsDetailValue);

            //
            // IsAscending ...
            var isAscendingKey = System.Uri.EscapeDataString(nameof(query.IsAscending));
            var isAscendingValue = query.IsAscending.AsHttpParamString();
            source.AddQueryParameter(isAscendingKey, isAscendingValue);

            //
            // Filter ...
            if (!query.Filter.IsNullOrEmpty())
            {
                //
                var key = System.Uri.EscapeDataString(nameof(query.Filter));
                var value = query.Filter.AsHttpParamString();
                source.AddQueryParameter(key, value);
            }

            //
            // SortBy ...
            if (!query.SortBy.IsNullOrEmpty())
            {
                //
                var key = System.Uri.EscapeDataString(nameof(query.SortBy));
                var value = query.SortBy.AsHttpParamString();
                source.AddQueryParameter(key, value);
            }

            //
            // Page ...
            if (query.Page > 0)
            {
                //
                var key = System.Uri.EscapeDataString(nameof(query.Page));
                var value = query.Page.AsHttpParamString();
                source.AddQueryParameter(key, value);
            }

            //
            // PageSize ...
            if (query.PageSize > 0)
            {
                //
                var key = System.Uri.EscapeDataString(nameof(query.PageSize));
                var value = query.PageSize.AsHttpParamString();
                source.AddQueryParameter(key, value);
            }

            //
            return source;
        }

        /// <summary>
        /// Add Dest User to Query Strings ...
        /// </summary>
        /// <param name="source"></param>
        /// <param name="destUser"></param>
        /// <returns></returns>
        public static RestRequest AttachDestUser(
            this RestRequest source,
            string destUser
        )
        {
            //
            if (destUser.IsNullOrEmpty())
            {
                return source;
            }

            //
            var destUserKey = System.Uri.EscapeDataString(nameof(destUser));
            var destUserValue = destUser.AsHttpParamString();
            source.AddQueryParameter(destUserKey, destUserValue);

            //
            return source;
        }

        /// <summary>
        /// Add XPoweredBy Header to specific RestRequest Headers ...
        /// </summary>
        /// <param name="source"></param>
        /// <param name="poweredByValue"></param>
        /// <returns></returns>
        public static RestRequest AddXPoweredBy(
            this RestRequest source,
            string poweredByValue
        )
        {
            //
            source.AddHeader(
                XAuthorization.XPoweredBy,
                poweredByValue
            );

            //
            return source;
        }

        /// <summary>
        /// Add XAccessToken Header to specific RestRequest Headers ...
        /// </summary>
        /// <param name="source"></param>
        /// <param name="poweredByValue"></param>
        /// <returns></returns>
        public static RestRequest AddXAccessToken(
            this RestRequest source,
            string token
        )
        {
            //
            token = $"{XAuthentication.BEARER} {token}";

            //
            source.AddHeader(
                XAuthorization.Header,
                token
            );

            //
            return source;
        }
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xHttpService\Interfaces\IXHttpProvider.cs

using System.Collections.Generic;
using System.Net.Http;
using System.Threading.Tasks;
using RestSharp;
using xHttpService.Constants;
using xIdentityModels.Models;

namespace xHttpService.Interfaces {
    public partial interface IXHttpProvider {
        HttpClient GetHttpClient ();
        RestClient GetRestClient (
            string baseUrl = null,
            string poweredByValue = null,
            XTokenResponse tokens = null
        );
        RestRequest GetRestRequet (
            string endpoint,
            IDictionary<string, string> @params = null,
            IDictionary<string, string> headers = null,
            IDictionary<string, string> queryStrings = null
        );
        Task<T> RunRestRequest<T> (
            RestClient client,
            RestRequest request,
            XHttpMethod method
        );
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xHttpService\Providers\XHttpProvider.cs

using System;
using System.Collections.Generic;
using System.Net.Http;
using System.Threading.Tasks;
using Microsoft.Extensions.Logging;
using RestSharp;
using RestSharp.Authenticators;
using xCommons.Constants;
using xCommons.Extensions;
using xExceptions.Constants;
using xHttpService.Configurations;
using xHttpService.Constants;
using xHttpService.Interfaces;
using xIdentityModels.Models;
using xModels.Base;

namespace xHttpService.Providers {
    public partial class XHttpProvider : XBaseClass, IXHttpProvider {

        private readonly XHttpServiceConfiguration configuration;

        public XHttpProvider (
            ILoggerFactory loggerFactory,
            XHttpServiceConfiguration configuration
        ) : base (loggerFactory) {
            this.configuration = configuration;
        }

        //
        #region Actions ...
        /// <summary>
        /// Get an Instance of Http Client 
        /// </summary>
        /// <returns></returns>
        public HttpClient GetHttpClient () {
            //
            HttpClient httpClient = null;
            httpClient = new HttpClient ();

            //
            if (configuration.DisableSSLCheck) {
                //
                var httpHandler = new HttpClientHandler ();
                httpHandler.ServerCertificateCustomValidationCallback = (sender, certificate, chain, sslPolicyErrors) => true;

                //
                httpClient = new HttpClient (httpHandler);
            }

            //
            // Set Timeout ...
            httpClient.Timeout = TimeSpan
                .FromSeconds (configuration.DefaultClientTimeout);

            //
            return httpClient;
        }

        /// <summary>
        /// Get an Instance of RestClient
        /// </summary>
        /// <param name="baseUrl"></param>
        /// <param name="poweredByValue"></param>
        /// <param name="tokens"></param>
        /// <returns></returns>
        public RestClient GetRestClient (
            string baseUrl = null,
            string poweredByValue = null,
            XTokenResponse tokens = null
        ) {
            //
            var client = new RestClient (baseUrl);

            //
            // Add XPowered By to Default Headers ...
            if (!poweredByValue.IsNullOrEmpty ()) {
                client.AddDefaultHeader (XAuthorization.XPoweredBy, poweredByValue);
            }

            //
            // Set Authenticator ...
            if (!tokens.IsNull () &&
                !tokens.AccessToken.IsNullOrEmpty ()) {
                client.Authenticator = new JwtAuthenticator (tokens.AccessToken);
            }

            //
            // Refresh Token ...
            if (!tokens.IsNull () &&
                !tokens.RefreshToken.IsNullOrEmpty ()) {
                client.AddDefaultHeader (XAuthorization.RefreshToken, tokens.RefreshToken);
            }

            //
            // ExpiresAt ...
            if (!tokens.IsNull () &&
                tokens.ExpiresAt > 0) {
                client.AddDefaultHeader (XAuthorization.ExpiresAt, tokens.ExpiresAt.AsHttpParamString ());
            }

            //
            // Set Default Timeout ...
            client.Timeout = configuration.DefaultClientTimeout;

            //
            // SSL Validation Handler ...
            if (configuration.DisableSSLCheck) {
                client.RemoteCertificateValidationCallback = (sender, cert, chain, sslPolicyErrors) => true;
            }

            //
            return client;
        }

        /// <summary>
        /// Get an Instance of RestRequest 
        /// </summary>
        /// <param name="endpoint"></param>
        /// <param name="params"></param>
        /// <param name="headers"></param>
        /// <param name="queryStrings"></param>
        /// <returns></returns>
        public RestRequest GetRestRequet (
            string endpoint,
            IDictionary<string, string> @params = null,
            IDictionary<string, string> headers = null,
            IDictionary<string, string> queryStrings = null
        ) {
            //
            var url = endpoint.ToString ();

            //
            // Add Route Payloads ...
            if (!@params.IsNull () && @params.Count > 0) {
                //
                var enumerator = @params.GetEnumerator ();
                while (enumerator.MoveNext ()) {
                    //
                    var item = enumerator.Current;

                    //
                    url = url.Replace (item.Key, item.Value.ToUrlEncoded ());
                }
            }

            //
            // Add Query Strings ...
            if (!queryStrings.IsNull () && queryStrings.Count > 0) {
                //
                url = $"{url}?";
                var enumerator = queryStrings.GetEnumerator ();
                while (enumerator.MoveNext ()) {
                    //
                    var item = enumerator.Current;

                    //
                    url += $"{item.Key}={item.Value.ToUrlEncoded ()}&";
                }

                //
                // remove lates & ...
                if (url.EndsWith ("&")) {
                    url = url.Substring (0, url.Length - 1);
                }
            }

            //
            // Create request ...
            var request = new RestRequest (url, DataFormat.Json);

            //
            // Add Headers to request ...
            if (!headers.IsNull () && headers.Count > 0) {
                //
                var enumerator = headers.GetEnumerator ();
                while (enumerator.MoveNext ()) {
                    //
                    var item = enumerator.Current;
                    request.AddHeader (item.Key, item.Value);
                }
            }

            //
            return request;
        }

        /// <summary>
        /// Handle Call Specific Request and retrieve Response
        /// </summary>
        /// <param name="client"></param>
        /// <param name="request"></param>
        /// <param name="method"></param>
        /// <typeparam name="T"></typeparam>
        /// <returns></returns>
        public async Task<T> RunRestRequest<T> (
            RestClient client,
            RestRequest request,
            XHttpMethod method
        ) {
            //
            var response = await Task.Run (() => {
                //
                IRestResponse resp = null;

                //
                // Call Endpoint Service using Specified Method ...
                switch (method) {
                    //
                    // Get ...
                    case XHttpMethod.GET:
                        resp = client.Get (request);
                        break;

                        //
                        // Put ...
                    case XHttpMethod.PUT:
                        resp = client.Put (request);
                        break;

                        //
                        // Post ...
                    case XHttpMethod.POST:
                        resp = client.Post (request);
                        break;

                        //
                        // Delete ...
                    case XHttpMethod.DELETE:
                        resp = client.Delete (request);
                        break;
                }

                //
                if (!resp.IsSuccessful) {
                    //
                    // UnAuthorized ...
                    if (resp.StatusCode == System.Net.HttpStatusCode.Unauthorized) {
                        XException.NotAuthorized.Throw ();
                    }

                    //
                    // NotFound ...
                    if (resp.StatusCode == System.Net.HttpStatusCode.NotFound) {
                        XException.NotFound.Throw ();
                    }

                    //
                    // Timeout ...
                    if (!resp.ErrorMessage.IsNullOrEmpty () &&
                        resp.ErrorMessage.Contains ("timed out")) {
                        XException.Timeout.Throw ();
                    }

                    //
                    // ErrorMessage ...
                    if (!resp.ErrorMessage.IsNullOrEmpty ()) {
                        throw new Exception (resp.ErrorMessage);
                    }

                    //
                    // Default Exception ...
                    XException.BadRequest.Throw ();
                }

                //
                var result = resp.Content.FromJSON<T> ();
                return result;
            });

            //
            return response;
        }
        #endregion
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xIdentityHelper\Extensions\XIdentityHelperExtensions.cs

using System;
using System.Linq;
using xCommons.Extensions;
using xIdentityModels.Models;

namespace xIdentityHelper.Extensions
{
    public static class XIdentityHelperExtensions
    {
        /// <summary>
        /// Check User Claims ia Admin Role or not ...
        /// </summary>
        /// <param name="source"></param>
        /// <returns></returns>
        public static bool IsAdmin(this XUserClaimsInfoDto source)
        {
            //
            var result = false;

            //
            if (source.IsNull() ||
                source.Roles.IsNull() ||
                !source.Roles.HasChild())
            {
                return result;
            }

            //
            result = source.Roles.Contains(XUserRoles.ADMIN);

            //
            return result;
        }

        /// <summary>
        /// Check Actor is Valid for UserSelectByParam or not ...
        /// </summary>
        /// <param name="source"></param>
        /// <param name="userSelectByParam"></param>
        /// <returns></returns>
        public static bool IsValidActor(this XUserClaimsInfoDto source, string userSelectByParam)
        {
            //
            var result = false;

            //
            if (source.IsNull() ||
                userSelectByParam.IsNullOrEmpty())
            {
                return result;
            }

            //
            bool isAdmin = source.IsAdmin();
            result = isAdmin ||
                userSelectByParam == source.Email ||
                userSelectByParam == source.UserId ||
                userSelectByParam == source.UserName ||
                userSelectByParam == source.PhoneNumber;

            //
            return result;
        }
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xIdentityHelper\Extensions\XUserRoleExtensions.cs

using System;
using System.Collections.Generic;
using System.Linq;
using xCommons.Extensions;
using xExceptions.Constants;

namespace xIdentityHelper.Extensions
{
    public static class XUserRoleExtensions
    {
        /// <summary>
        /// Converts an String to XUserRole ...
        /// </summary>
        /// <param name="role"></param>
        /// <returns></returns>
        public static XUserRole ToXUserRole(this string role)
        {
            //
            var result = XUserRole.User;

            //
            // Validate ...
            if (role.IsNullOrEmpty())
            {
                XException.InvalidArgs.Throw();
            }

            //
            var roles = new List<string>
            {
                role
            };
            result = roles.GetTopRole();

            //
            return result;
        }

        /// <summary>
        /// Retrieve User Top Role based on Role Lists ... 
        /// </summary>
        /// <param name="roles"></param>
        /// <returns></returns>
        public static XUserRole GetTopRole(this IEnumerable<string> roles)
        {
            //
            // Validate ...
            if (roles.IsNull() || !roles.HasChild())
            {
                XException.InvalidArgs.Throw();
            }

            //
            // Normalize Roles ...
            roles = roles.Select(r => r.ToNormalString());

            //
            var result = XUserRole.User;

            //
            // Admin ...
            if (roles.Contains(XUserRole.Admin.GetStringValue().ToNormalString()))
            {
                result = XUserRole.Admin;
            }
            //
            // ResponsibleManager ...
            else if (roles.Contains(XUserRole.ResponsibleManager.GetStringValue().ToNormalString()))
            {
                result = XUserRole.ResponsibleManager;
            }
            //
            // Journalist ...
            else if (roles.Contains(XUserRole.Journalist.GetStringValue().ToNormalString()))
            {
                result = XUserRole.Journalist;
            }
            //
            // ChiefClerk ...
            else if (roles.Contains(XUserRole.ChiefClerk.GetStringValue().ToNormalString()))
            {
                result = XUserRole.ChiefClerk;
            }
            //
            // ChiefClerkAssistant ...
            else if (roles.Contains(XUserRole.ChiefClerkAssistant.GetStringValue().ToNormalString()))
            {
                result = XUserRole.ChiefClerkAssistant;
            }
            //
            // Actuary ...
            else if (roles.Contains(XUserRole.Actuary.GetStringValue().ToNormalString()))
            {
                result = XUserRole.Actuary;
            }
            //
            // ActuaryAssistant ...
            else if (roles.Contains(XUserRole.ActuaryAssistant.GetStringValue().ToNormalString()))
            {
                result = XUserRole.ActuaryAssistant;
            }
            //
            // Reporter ...
            else if (roles.Contains(XUserRole.Reporter.GetStringValue().ToNormalString()))
            {
                result = XUserRole.Reporter;
            }
            //
            // ReporterAssistant ...
            else if (roles.Contains(XUserRole.ReporterAssistant.GetStringValue().ToNormalString()))
            {
                result = XUserRole.ReporterAssistant;
            }
            //
            // Agent ...
            else if (roles.Contains(XUserRole.Agent.GetStringValue().ToNormalString()))
            {
                result = XUserRole.Agent;
            }
            //
            // User ...
            else if (roles.Contains(XUserRole.User.GetStringValue().ToNormalString()))
            {
                result = XUserRole.User;
            }
            else
            {
                XException.InvalidData.Throw();
            }

            //
            return result;
        }

        /// <summary>
        /// Check User Roles has Specified Permissions or not ...
        /// </summary>
        /// <param name="roles"></param>
        /// <param name="role"></param>
        /// <returns></returns>
        public static bool HasRolePermissions(this IEnumerable<string> roles, XUserRole role)
        {
            //
            // Validate ...
            var result =
                !roles.IsNull() &&
                roles.HasChild();
            if (!result)
            {
                return result;
            }

            //
            try
            {
                //
                var topRole = roles.GetTopRole();

                //
                result = (int)topRole >= (int)role;
            }
            catch
            {
                result = false;
            }

            //
            return result;
        }
        public static bool HasRolePermissions(this IEnumerable<string> roles, string role)
        {
            //
            // Validate ...
            var result =
                !roles.IsNull() &&
                roles.HasChild() &&
                !role.IsNullOrEmpty();
            if (!result)
            {
                return result;
            }

            //
            var roleEnum = role.ToXUserRole();
            result = roles.HasRolePermissions(roleEnum);

            //
            return result;
        }
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xIdentityHelper\XApiScopeHelper.cs

using xExceptions.Attributes;

namespace xIdentityHelper {
    public static class XApiScopeHelper {
        public partial struct XApiScopes {
            public const string Read = "XAPI.read";
            public const string Write = "XAPI.write";
            public const string Admin = "XAPI.admin";
            public const string Manage = "manage";
        }

        public  enum XApiScope {
            [StringValue ("XAPI.read")]
            Read, 
            
            [StringValue ("XAPI.write")]
            Write, 
            
            [StringValue ("XAPI.admin")]
            Admin, 
            
            [StringValue ("manage")]
            Manage,
        }
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xIdentityHelper\XAuthorizationHelper.cs

using System.Collections.Generic;
using IdentityModel;
using Microsoft.AspNetCore.Authorization;
using xCommons.Authorization;
using xCommons.Constants;
using xCommons.Extensions;
using static xIdentityHelper.XApiScopeHelper;

namespace xIdentityHelper
{
    public class XAuthorizationHelper
    {
        public static IDictionary<string, AuthorizationPolicy> GetXAuthorizationPolicies()
        {
            //
            var result = new Dictionary<string, AuthorizationPolicy>();

            //
            RequiredRolesRequirement roleRequirements = null;

            //
            #region Build Policies ...
            //
            // Scope Policies ...
            #region Scope Policies ...
            //
            // Read Scope ...
            result.Add(XPolicies.ReadAccess,
                new AuthorizationPolicyBuilder()
                .RequireClaim(JwtClaimTypes.Scope, XApiScopes.Read)
                .Build()
            );

            //
            // Write Scope ...
            result.Add(XPolicies.WriteAccess,
                new AuthorizationPolicyBuilder()
                .RequireClaim(
                    JwtClaimTypes.Scope,
                    XApiScopes.Read,
                    XApiScopes.Write
                )
                .Build()
            );

            //
            // Admin Scope ...
            result.Add(XPolicies.AdminAccess,
                new AuthorizationPolicyBuilder()
                .RequireClaim(
                    JwtClaimTypes.Scope,
                    XApiScopes.Read,
                    XApiScopes.Write,
                    XApiScopes.Admin
                )
                .Build()
            );

            //
            // Manage Scope ...
            result.Add(XPolicies.ManageAccess,
                new AuthorizationPolicyBuilder()
                .RequireClaim(
                    JwtClaimTypes.Scope,
                    XApiScopes.Read,
                    XApiScopes.Write,
                    XApiScopes.Admin,
                    XApiScopes.Manage
                )
                .Build()
            );
            #endregion

            //
            // Roles Policies ...
            #region Roles Policies ...
            //
            // User ...
            #region User Related Policies ...
            //
            roleRequirements = new RequiredRolesRequirement(
                    XUserRoles.USER,
                    XUserRoles.AGENT,
                    XUserRoles.REPORTER_ASSISTANT,
                    XUserRoles.REPORTER,
                    XUserRoles.ACTUARY_ASSISTANT,
                    XUserRoles.ACTUARY,
                    XUserRoles.CHIEF_CLERK_ASSISTANT,
                    XUserRoles.CHIEF_CLERK,
                    XUserRoles.JOURNALIST,
                    XUserRoles.RESPONSIBLE_MANAGER,
                    XUserRoles.ADMIN
            );

            //
            // User Policy ...
            result.Add(XPolicies.User,
                new AuthorizationPolicyBuilder()
                .RequireAuthenticatedUser()
                .AddRequirements(roleRequirements)
                .Build()
            );

            //
            // Enabled User Policy ...
            result.Add(XPolicies.EnabledUser,
                new AuthorizationPolicyBuilder()
                .RequireAuthenticatedUser()
                .AddRequirements(roleRequirements)
                .RequireClaim(
                    XCustomClaims.IsBanned,
                    false.ToString(),
                    false.ToString()
                    .ToNormalString()
                )
                .RequireClaim(
                    XCustomClaims.IsEnabled,
                    true.ToString(),
                    true.ToString()
                    .ToNormalString()
                )
                .Build()
            );
            #endregion

            //
            // Agent ...
            #region Agent Related Policies ...
            //
            roleRequirements = new RequiredRolesRequirement(
                    XUserRoles.AGENT,
                    XUserRoles.REPORTER_ASSISTANT,
                    XUserRoles.REPORTER,
                    XUserRoles.ACTUARY_ASSISTANT,
                    XUserRoles.ACTUARY,
                    XUserRoles.CHIEF_CLERK_ASSISTANT,
                    XUserRoles.CHIEF_CLERK,
                    XUserRoles.JOURNALIST,
                    XUserRoles.RESPONSIBLE_MANAGER,
                    XUserRoles.ADMIN
            );

            //
            // Agent Policy  ...
            result.Add(XPolicies.Agent,
                new AuthorizationPolicyBuilder()
                .RequireAuthenticatedUser()
                .AddRequirements(roleRequirements)
                .Build()
            );

            //
            // Enabled Agent Policy  ...
            result.Add(XPolicies.EnabledAgent,
                new AuthorizationPolicyBuilder()
                .RequireAuthenticatedUser()
                .AddRequirements(roleRequirements)
                .RequireClaim(
                    XCustomClaims.IsBanned,
                    false.ToString(),
                    false.ToString()
                    .ToNormalString()
                )
                .RequireClaim(
                    XCustomClaims.IsEnabled,
                    true.ToString(),
                    true.ToString()
                    .ToNormalString()
                )
                .Build()
            );
            #endregion

            //
            // ReporterAssistant ...
            #region Reporter Assistant Related Policies ...
            //
            roleRequirements = new RequiredRolesRequirement(
                    XUserRoles.REPORTER_ASSISTANT,
                    XUserRoles.REPORTER,
                    XUserRoles.ACTUARY_ASSISTANT,
                    XUserRoles.ACTUARY,
                    XUserRoles.CHIEF_CLERK_ASSISTANT,
                    XUserRoles.CHIEF_CLERK,
                    XUserRoles.JOURNALIST,
                    XUserRoles.RESPONSIBLE_MANAGER,
                    XUserRoles.ADMIN
            );

            //
            // ReporterAssistant ...
            result.Add(XPolicies.ReporterAssistant,
                new AuthorizationPolicyBuilder()
                .RequireAuthenticatedUser()
                .AddRequirements(roleRequirements)
                .Build()
            );

            //
            // Enabled ReporterAssistant ...
            result.Add(XPolicies.EnabledReporterAssistant,
                new AuthorizationPolicyBuilder()
                .RequireAuthenticatedUser()
                .AddRequirements(roleRequirements)
                .RequireClaim(
                    XCustomClaims.IsBanned,
                    false.ToString(),
                    false.ToString()
                    .ToNormalString()
                )
                .RequireClaim(
                    XCustomClaims.IsEnabled,
                    true.ToString(),
                    true.ToString()
                    .ToNormalString()
                )
                .Build()
            );
            #endregion

            //
            // Reporter ...
            #region Reporter Related Policies ...
            //
            roleRequirements = new RequiredRolesRequirement(
                    XUserRoles.REPORTER,
                    XUserRoles.ACTUARY_ASSISTANT,
                    XUserRoles.ACTUARY,
                    XUserRoles.CHIEF_CLERK_ASSISTANT,
                    XUserRoles.CHIEF_CLERK,
                    XUserRoles.JOURNALIST,
                    XUserRoles.RESPONSIBLE_MANAGER,
                    XUserRoles.ADMIN
            );

            //
            // Reporter ...
            result.Add(XPolicies.Reporter,
                new AuthorizationPolicyBuilder()
                .RequireAuthenticatedUser()
                .AddRequirements(roleRequirements)
                .Build()
            );

            //
            // Enabled Reporter ...
            result.Add(XPolicies.EnabledReporter,
                new AuthorizationPolicyBuilder()
                .RequireAuthenticatedUser()
                .AddRequirements(roleRequirements)
                .RequireClaim(
                    XCustomClaims.IsBanned,
                    false.ToString(),
                    false.ToString()
                    .ToNormalString()
                )
                .RequireClaim(
                    XCustomClaims.IsEnabled,
                    true.ToString(),
                    true.ToString()
                    .ToNormalString()
                )
                .Build()
            );
            #endregion

            //
            // ActuaryAssistant ...
            #region Actuary Assistant Related Policies ...
            //
            roleRequirements = new RequiredRolesRequirement(
                    XUserRoles.ACTUARY_ASSISTANT,
                    XUserRoles.ACTUARY,
                    XUserRoles.CHIEF_CLERK_ASSISTANT,
                    XUserRoles.CHIEF_CLERK,
                    XUserRoles.JOURNALIST,
                    XUserRoles.RESPONSIBLE_MANAGER,
                    XUserRoles.ADMIN
            );

            //
            // ActuaryAssistant ...
            result.Add(XPolicies.ActuaryAssistant,
                new AuthorizationPolicyBuilder()
                .RequireAuthenticatedUser()
                .AddRequirements(roleRequirements)
                .Build()
            );

            //
            // Enabled ActuaryAssistant ...
            result.Add(XPolicies.EnabledActuaryAssistant,
                new AuthorizationPolicyBuilder()
                .RequireAuthenticatedUser()
                .AddRequirements(roleRequirements)
                .RequireClaim(
                    XCustomClaims.IsBanned,
                    false.ToString(),
                    false.ToString()
                    .ToNormalString()
                )
                .RequireClaim(
                    XCustomClaims.IsEnabled,
                    true.ToString(),
                    true.ToString()
                    .ToNormalString()
                )
                .Build()
            );
            #endregion

            //
            // Actuary ...
            #region Actuary Related Policies ...
            //
            roleRequirements = new RequiredRolesRequirement(
                    XUserRoles.ACTUARY,
                    XUserRoles.CHIEF_CLERK_ASSISTANT,
                    XUserRoles.CHIEF_CLERK,
                    XUserRoles.JOURNALIST,
                    XUserRoles.RESPONSIBLE_MANAGER,
                    XUserRoles.ADMIN
            );

            //
            // Actuary ...
            result.Add(XPolicies.Actuary,
                new AuthorizationPolicyBuilder()
                .RequireAuthenticatedUser()
                .AddRequirements(roleRequirements)
                .Build()
            );

            //
            // Enabled Actuary ...
            result.Add(XPolicies.EnabledActuary,
                new AuthorizationPolicyBuilder()
                .RequireAuthenticatedUser()
                .AddRequirements(roleRequirements)
                .RequireClaim(
                    XCustomClaims.IsBanned,
                    false.ToString(),
                    false.ToString()
                    .ToNormalString()
                )
                .RequireClaim(
                    XCustomClaims.IsEnabled,
                    true.ToString(),
                    true.ToString()
                    .ToNormalString()
                )
                .Build()
            );
            #endregion

            //
            // ChiefClerkAssistant ...
            #region Chief Clerk Assistant Related Policies ...
            //
            roleRequirements = new RequiredRolesRequirement(
                    XUserRoles.CHIEF_CLERK_ASSISTANT,
                    XUserRoles.CHIEF_CLERK,
                    XUserRoles.JOURNALIST,
                    XUserRoles.RESPONSIBLE_MANAGER,
                    XUserRoles.ADMIN
            );

            //
            // ChiefClerkAssistant ...
            result.Add(XPolicies.ChiefClerkAssistant,
                new AuthorizationPolicyBuilder()
                .RequireAuthenticatedUser()
                .AddRequirements(roleRequirements)
                .Build()
            );

            //
            // Enabled ChiefClerkAssistant ...
            result.Add(XPolicies.EnabledChiefClerkAssistant,
                new AuthorizationPolicyBuilder()
                .RequireAuthenticatedUser()
                .AddRequirements(roleRequirements)
                .RequireClaim(
                    XCustomClaims.IsBanned,
                    false.ToString(),
                    false.ToString()
                    .ToNormalString()
                )
                .RequireClaim(
                    XCustomClaims.IsEnabled,
                    true.ToString(),
                    true.ToString()
                    .ToNormalString()
                )
                .Build()
            );
            #endregion

            //
            // ChiefClerk ...
            #region Chief Clerk Related Policies ...
            //
            roleRequirements = new RequiredRolesRequirement(
                    XUserRoles.CHIEF_CLERK,
                    XUserRoles.JOURNALIST,
                    XUserRoles.RESPONSIBLE_MANAGER,
                    XUserRoles.ADMIN
            );

            //
            // ChiefClerk ...
            result.Add(XPolicies.ChiefClerk,
                new AuthorizationPolicyBuilder()
                .RequireAuthenticatedUser()
                .AddRequirements(roleRequirements)
                .Build()
            );

            //
            // Enabled ChiefClerk ... 
            result.Add(XPolicies.EnabledChiefClerk,
                new AuthorizationPolicyBuilder()
                .RequireAuthenticatedUser()
                .AddRequirements(roleRequirements)
                .RequireClaim(
                    XCustomClaims.IsBanned,
                    false.ToString(),
                    false.ToString()
                    .ToNormalString()
                )
                .RequireClaim(
                    XCustomClaims.IsEnabled,
                    true.ToString(),
                    true.ToString()
                    .ToNormalString()
                )
                .Build()
            );
            #endregion

            //
            // Journalist ...
            #region Journalist Related Policies ...
            //
            roleRequirements = new RequiredRolesRequirement(
                    XUserRoles.JOURNALIST,
                    XUserRoles.RESPONSIBLE_MANAGER,
                    XUserRoles.ADMIN
            );

            //
            // Journalist ...
            result.Add(XPolicies.Journalist,
                new AuthorizationPolicyBuilder()
                .RequireAuthenticatedUser()
                .AddRequirements(roleRequirements)
                .Build()
            );

            //
            // Enabled Journalist ...
            result.Add(XPolicies.EnabledJournalist,
                new AuthorizationPolicyBuilder()
                .RequireAuthenticatedUser()
                .AddRequirements(roleRequirements)
                .RequireClaim(
                    XCustomClaims.IsBanned,
                    false.ToString(),
                    false.ToString()
                    .ToNormalString()
                )
                .RequireClaim(
                    XCustomClaims.IsEnabled,
                    true.ToString(),
                    true.ToString()
                    .ToNormalString()
                )
                .Build()
            );
            #endregion

            //
            // ResponsibleManager ...
            #region Responsible Manager Related Policies ...
            //
            roleRequirements = new RequiredRolesRequirement(
                    XUserRoles.RESPONSIBLE_MANAGER,
                    XUserRoles.ADMIN
            );

            //
            // ResponsibleManager ...
            result.Add(XPolicies.ResponsibleManager,
                new AuthorizationPolicyBuilder()
                .RequireAuthenticatedUser()
                .AddRequirements(roleRequirements)
                .Build()
            );

            //
            // Enabled ResponsibleManager ...
            result.Add(XPolicies.EnabledResponsibleManager,
                new AuthorizationPolicyBuilder()
                .RequireAuthenticatedUser()
                .AddRequirements(roleRequirements)
                .RequireClaim(
                    XCustomClaims.IsBanned,
                    false.ToString(),
                    false.ToString()
                    .ToNormalString()
                )
                .RequireClaim(
                    XCustomClaims.IsEnabled,
                    true.ToString(),
                    true.ToString()
                    .ToNormalString()
                )
                .Build()
            );
            #endregion

            //
            // Admin ...
            #region Admin Related Policies ...
            //
            roleRequirements = new RequiredRolesRequirement(
                    XUserRoles.ADMIN
            );

            //
            // Admin Policy  ...
            result.Add(XPolicies.Admin,
                new AuthorizationPolicyBuilder()
                .RequireAuthenticatedUser()
                .AddRequirements(roleRequirements)
                .Build()
            );

            //
            // Enabled Admin Policy  ...
            result.Add(XPolicies.EnabledAdmin,
                new AuthorizationPolicyBuilder()
                .RequireAuthenticatedUser()
                .AddRequirements(roleRequirements)
                .RequireClaim(
                    XCustomClaims.IsBanned,
                    false.ToString(),
                    false.ToString()
                    .ToNormalString()
                )
                .RequireClaim(
                    XCustomClaims.IsEnabled,
                    true.ToString(),
                    true.ToString()
                    .ToNormalString()
                )
                .Build()
            );
            #endregion
            #endregion

            //
            // Complex Policies ...
            #region AdminOrAgent Related Policies ...
            //
            // Admin Or Agent Policy  ...
            result.Add(XPolicies.AdminOrAgent,
                new AuthorizationPolicyBuilder()
                .RequireAuthenticatedUser()
                .AddRequirements(new RequiredRolesRequirement(
                    XUserRoles.ADMIN,
                    XUserRoles.AGENT
                ))
                .Build()
            );

            //
            // Enabled Admin Or Agent Policy  ...
            result.Add(XPolicies.EnabledAdminOrAgent,
                new AuthorizationPolicyBuilder()
                .RequireAuthenticatedUser()
                .AddRequirements(new RequiredRolesRequirement(
                    XUserRoles.ADMIN,
                    XUserRoles.AGENT
                ))
                .RequireClaim(
                    XCustomClaims.IsBanned,
                    false.ToString(),
                    false.ToString()
                    .ToNormalString()
                )
                .RequireClaim(
                    XCustomClaims.IsEnabled,
                    true.ToString(),
                    true.ToString()
                    .ToNormalString()
                )
                .Build()
            );
            #endregion
            #endregion

            //
            return result;
        }
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xIdentityHelper\XPolicies.cs

namespace xIdentityHelper
{
    public partial struct XPolicies
    {
        //
        // Scopes ...
        public const string ReadAccess = "readScopePolicy";
        public const string WriteAccess = "writeScopePolicy";
        public const string AdminAccess = "adminScopePolicy";
        public const string ManageAccess = "manageScopePolicy";
        //
        // Admin ...
        public const string Admin = "adminPolicy";
        public const string EnabledAdmin = "enabledAdminPolicy";
        //
        // Responsible Manager ...
        public const string ResponsibleManager = "responsibleManagerPolicy";
        public const string EnabledResponsibleManager = "enabledResponsibleManagerPolicy";
        //
        // Journalist ...
        public const string Journalist = "journalistPolicy";
        public const string EnabledJournalist = "enabledJournalistPolicy";
        //
        // Chief Clerk ...
        public const string ChiefClerk = "chiefClerkPolicy";
        public const string EnabledChiefClerk = "enabledChiefClerkPolicy";
        //
        // Chief Clerk Assistant ...
        public const string ChiefClerkAssistant = "chiefClerkAssistantPolicy";
        public const string EnabledChiefClerkAssistant = "enabledChiefClerkAssistantPolicy";
        //
        // Actuary ...
        public const string Actuary = "actuaryPolicy";
        public const string EnabledActuary = "enabledActuaryPolicy";
        //
        // Actuary Assistant ...
        public const string ActuaryAssistant = "actuaryAssistantPolicy";
        public const string EnabledActuaryAssistant = "enabledActuaryAssistantPolicy";
        //
        // Reporter ...
        public const string Reporter = "reporterPolicy";
        public const string EnabledReporter = "enabledReporterPolicy";
        //
        // Reporter Assistant ...
        public const string ReporterAssistant = "reporterAssistantPolicy";
        public const string EnabledReporterAssistant = "enabledReporterAssistantPolicy";
        //
        // Agent ...
        public const string Agent = "agentPolicy";
        public const string EnabledAgent = "enabledAgentPolicy";
        //
        // User ...
        public const string User = "userPolicy";
        public const string EnabledUser = "enabledUserPolicy";
        //
        // Complex Policies ...
        public const string AdminOrAgent = "adminOrAgentPolicy";
        public const string EnabledAdminOrAgent = "enabledAdminOrAgentPolicy";
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xIdentityHelper\XUserRoles.cs

using System.Collections.Generic;
using xExceptions.Attributes;

namespace xIdentityHelper
{
    public partial struct XUserRoles
    {
        /// <summary>
        /// Must Top Role of System ...
        /// </summary>
        public const string ADMIN = "admin";

        /// <summary>
        /// مدیر مسئول
        /// </summary>
        public const string RESPONSIBLE_MANAGER = "responsible_manager";

        /// <summary>
        /// روزنامه نگار
        /// </summary>
        public const string JOURNALIST = "journalist";

        /// <summary>
        /// سر دبیر
        /// </summary>
        public const string CHIEF_CLERK = "chief_clerk";

        /// <summary>
        /// دستیار سرد بیر
        /// </summary>
        public const string CHIEF_CLERK_ASSISTANT = "chief_clerk_assistant";

        /// <summary>
        /// دبیر
        /// </summary>
        public const string ACTUARY = "actuary";

        /// <summary>
        /// دستیار دبیر
        /// </summary>
        public const string ACTUARY_ASSISTANT = "actuary_assistant";

        /// <summary>
        /// خبرنگار
        /// </summary>
        public const string REPORTER = "reporter";

        /// <summary>
        /// دستیار خبرنگار
        /// </summary>
        public const string REPORTER_ASSISTANT = "reporter_assistant";

        /// <summary>
        /// دستیار
        /// </summary>
        public const string AGENT = "agent";

        /// <summary>
        /// کاربر
        /// </summary>
        public const string USER = "user";
    }

    public enum XUserRole
    {
        /// <summary>
        /// Must Top Role of System ...
        /// </summary>
        [StringValue("admin")]
        Admin = 10,

        /// <summary>
        /// مدیر مسئول
        /// </summary>
        [StringValue("responsible_manager")]
        ResponsibleManager = 9,

        /// <summary>
        /// روزنامه نگار
        /// </summary>
        [StringValue("journalist")]
        Journalist = 8,

        /// <summary>
        /// سر دبیر
        /// </summary>
        [StringValue("chief_clerk")]
        ChiefClerk = 7,

        /// <summary>
        /// دستیار سرد بیر
        /// </summary>
        [StringValue("chief_clerk_assistant")]
        ChiefClerkAssistant = 6,

        /// <summary>
        /// دبیر
        /// </summary>
        [StringValue("actuary")]
        Actuary = 5,

        /// <summary>
        /// دستیار دبیر
        /// </summary>
        [StringValue("actuary_assistant")]
        ActuaryAssistant = 4,

        /// <summary>
        /// خبرنگار
        /// </summary>
        [StringValue("reporter")]
        Reporter = 3,

        /// <summary>
        /// دستیار خبرنگار
        /// </summary>
        [StringValue("reporter_assistant")]
        ReporterAssistant = 2,

        /// <summary>
        /// دستیار
        /// </summary>
        [StringValue("agent")]
        Agent = 1,

        /// <summary>
        /// کاربر
        /// </summary>
        [StringValue("user")]
        User = 0
    }

    public static class XUserRoleHelper
    {
        public static List<string> GetAllRoles()
        {
            //
            var result = new List<string>
            {
                XUserRoles.ADMIN,
                XUserRoles.RESPONSIBLE_MANAGER,
                XUserRoles.JOURNALIST,
                XUserRoles.CHIEF_CLERK,
                XUserRoles.CHIEF_CLERK_ASSISTANT,
                XUserRoles.ACTUARY,
                XUserRoles.ACTUARY_ASSISTANT,
                XUserRoles.REPORTER,
                XUserRoles.REPORTER_ASSISTANT,
                XUserRoles.AGENT,
                XUserRoles.USER
            };

            //
            return result;
        }
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xIdentityModels\Configurations\XIdentityConfiguration.cs

using System.Collections.Generic;
using xIdentityModels.Dtos;

namespace xIdentityModels.Configurations {
    public class XIdentityConfiguration {
        //
        // Define All Policies which can Apply to Identity Framework
        // and also create a Default instance if it's not Exists
        // in AppSetting JSON file ...
        public XIdentityPolicy Policy { get; set; }

        /// <summary>
        /// the Security Key which used to Signing JWT Tokens
        /// in Authentication Provider
        /// </summary>
        /// <value></value>
        public string IdentitySecretKey { get; set; }

        /// <summary>
        /// the Issuer and Creator of Token 
        /// </summary>
        /// <value></value>
        public string IdentityIssuer { get; set; }

        /// <summary>
        /// the Audience and Consumer of Token
        /// </summary>
        /// <value></value>
        public string IdentityAudience { get; set; }

        /// <summary>
        /// the List of Users Roles which must Provides in Identity
        /// </summary>
        /// <value></value>
        public HashSet<string> IdentityRoles { get; set; }

        /// <summary>
        /// determines All new users must Assign to which role in Registration
        /// </summary>
        /// <value></value>
        public string NewUsersRole { get; set; }

        /// <summary>
        /// determines New Registered Users Confirm Email or not
        /// </summary>
        /// <value></value>
        public bool AutoConfirmNewUsersEmail { get; set; }

        /// <summary>
        /// determines New Registered Users Confirm PhoneNumber or not
        /// </summary>
        /// <value></value>
        public bool AutoConfirmNewUsersPhoneNumber { get; set; }

        /// <summary>
        /// determines the Registration only Can be done with Invitation or not
        /// </summary>
        /// <value></value>
        public bool RegistrationJustWithInvite { get; set; }

        /// <summary>
        /// determines the Registration required confirmation with email or not 
        /// </summary>
        /// <value></value>
        public bool RequireRegistrationConfirm { get; set; }

        //
        public int MaxNumberOfVerificationCodeSend { get; set; }

        //
        public int DeleyBetweenTwoVerificationCode { get; set; }

        public int BannedDeviceTimeout { get; set; }

        /// <summary>
        /// an string Which Provide how long a action token can be valid
        /// </summary>
        /// <value></value>
        public string ActionTokenExpirationDateProvider { get; set; }

        public HashSet<XIdentityMessageDto> IdentityMessages { get; set; }
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xIdentityModels\Configurations\XIdentityPolicy.cs

namespace xIdentityModels.Configurations {
    /// <summary>
    /// Provide the Available Policies with their Default Values
    /// </summary>
    public class XIdentityPolicy {
        /// <summary>
        /// User Account Lock Policies
        /// </summary>
        /// <value></value>
        public XIdentityPolicyLockout Lockout { get; set; }

        /// <summary>
        /// User Password Policies
        /// </summary>
        /// <value></value>
        public XIdentityPolicyPassword Password { get; set; }

        /// <summary>
        /// the Policies for User for Allowing to SignIn 
        /// </summary>
        /// <value></value>
        public XIdentityPolicySignIn SignIn { get; set; }

        /// <summary>
        /// the Policies for User
        /// </summary>
        /// <value></value>
        public XIdentityPolicyUser User { get; set; }

        /// <summary>
        /// the policies which determines how to 
        /// populate user profile
        /// </summary>
        /// <value></value>
        public XIdentityProfile Profile { get; set; }
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xIdentityModels\Configurations\XIdentityPolicyLockout.cs

namespace xIdentityModels.Configurations {
    /// <summary>
    /// User Account Lock Policies
    /// </summary>
    public class XIdentityPolicyLockout {
        /// <summary>
        /// The String which Provide Time Span Delais 
        /// between Lockout and UnLock a User Account
        /// this Provided String the Parsed before Use
        /// </summary>
        /// <value></value>
        public string LockoutTimeSpanProvider { get; set; }

        /// <summary>
        /// the Number of InvalidLoginAttemps which can
        /// Happens to Lockout User Account
        /// </summary>
        /// <value></value>
        public byte MaxFailedAccessAttempts { get; set; }

        /// <summary>
        /// determines Lockout mechanism allowed for new Users or not
        /// </summary>
        /// <value></value>
        public bool AllowedForNewUsers { get; set; }
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xIdentityModels\Configurations\XIdentityPolicyPassword.cs

namespace xIdentityModels.Configurations {
    /// <summary>
    /// User Password Policies
    /// </summary>
    public class XIdentityPolicyPassword {
        /// <summary>
        /// determines Password must contains digits or not
        /// </summary>
        /// <value></value>
        public bool RequireDigit { get; set; }

        /// <summary>
        /// determines the minimum allowed length for a password
        /// </summary>
        /// <value></value>
        public byte RequiredLength { get; set; }

        /// <summary>
        /// determines the number of Unique Chars must be included in a Password
        /// </summary>
        /// <value></value>
        public byte RequiredUniqueChars { get; set; }

        /// <summary>
        /// determines Password must contains LowerCase chars or not
        /// </summary>
        /// <value></value>
        public bool RequireLowercase { get; set; }

        /// <summary>
        /// determines Password must contains Non-Alphabetical chars or not
        /// </summary>
        /// <value></value>
        public bool RequireNonAlphanumeric { get; set; }

        /// <summary>
        /// determines Password must contains UpperCase chars or not
        /// </summary>
        /// <value></value>
        public bool RequireUppercase { get; set; }
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xIdentityModels\Configurations\XIdentityPolicySignIn.cs

namespace xIdentityModels.Configurations {
    /// <summary>
    /// the Policies for User for Allowing to SignIn
    /// </summary>
    public class XIdentityPolicySignIn {
        /// <summary>
        /// determines only enabled users can SignIn
        /// </summary>
        /// <value></value>
        public bool RequiredEnabled { get; set; }

        /// <summary>
        /// determines User must Confirm the given Email Address
        /// before Login or not
        /// </summary>
        /// <value></value>
        public bool RequireConfirmedEmail { get; set; }

        /// <summary>
        /// determines User must Confirm the given Phone Number 
        /// before Login or not
        /// </summary>
        /// <value></value>
        public bool RequireConfirmedPhoneNumber { get; set; }
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xIdentityModels\Configurations\XIdentityPolicyUser.cs

using System.Collections.Generic;

namespace xIdentityModels.Configurations {
    /// <summary>
    /// the Policies for User
    /// </summary>
    public class XIdentityPolicyUser {
        /// <summary>
        /// determines Allowed characters which can used in UserName
        /// </summary>
        /// <value></value>
        public string AllowedUserNameCharacters { get; set; }

        /// <summary>
        /// determines the Email Address of each User must be Unique or not
        /// </summary>
        /// <value></value>
        public bool RequireUniqueEmail { get; set; }

        /// <summary>
        /// minimum length of User Name
        /// </summary>
        /// <value></value>
        public byte MinLength { get; set; }

        /// <summary>
        /// maximum length of user name
        /// </summary>
        /// <value></value>
        public byte MaxLength { get; set; }

        /// <summary>
        /// Minimum Age for Registration
        /// </summary>
        /// <value></value>
        public int MinAgeForRegistration { get; set; }

        /// <summary>
        /// Maximum age for Registration
        /// </summary>
        /// <value></value>
        public int MaxAgeForRegistration { get; set; }

        /// <summary>
        /// a collection of invalid usernames
        /// </summary>
        /// <value></value>
        public ICollection<string> InvalidUserNames { get; set; } = new HashSet<string> ();
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xIdentityModels\Configurations\XIdentityProfile.cs

namespace xIdentityModels.Configurations {
    /// <summary>
    /// contains user profile configuration
    /// </summary>
    public class XIdentityProfile {
        /// <summary>
        /// determines user profile contain email or not
        /// </summary>
        /// <value></value>
        public bool ContainsEmail { get; set; }

        /// <summary>
        /// determines user profile contains phone number or not
        /// </summary>
        /// <value></value>
        public bool ContainsPhoneNumber { get; set; }

        /// <summary>
        /// determines user profile contains Roles collection or not
        /// </summary>
        /// <value></value>
        public bool ContainsRoles { get; set; }

        public bool ContainsDateOfBirth { get; set; }

        public bool ContainsLastLogin { get; set; }

        public bool ContainsCreationDate { get; set; }
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xIdentityModels\Constants\XAction.cs

namespace xIdentityModels.Constants {
    public enum XAction {
        Authentication,
        Invite,
        Registration,
        RequestMobileVerificationCode,
        ConfirmMobileNumber,
        RequestEmailVerificationCode,
        ConfirmEmailAddress,
        AddAccountInfo,
        AttachProfileImage,
        RequestResetPassword,
        ProfileAction,
        Finish,
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xIdentityModels\Constants\XFriendshipState.cs

namespace xIdentityModels.Constants {
    /// <summary>
    /// Represent State of Friendship between to Users
    /// </summary>
    public enum XFriendshipState {
        None,
        Pending,
        Accepted,
        Rejected,
        Blocked,
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xIdentityModels\Constants\XGender.cs

namespace xIdentityModels.Constants {
    /// <summary>
    /// Determines Available Genders
    /// </summary>
    public enum XGender {
        Male,
        Female
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xIdentityModels\Constants\xIdentityModelsConstants.cs

namespace xIdentityModels.Constants {
    public class xIdentityModelsConstants { }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xIdentityModels\Constants\XUserSelectBy.cs

namespace xIdentityModels.Constants {
    public enum XUserSelectBy {
        NotSpecified,
        ID,
        Username,
        Email,
        MobileNumber
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xIdentityModels\Descriptors\XIdentityUserDescriptor.cs

namespace xIdentityModels.Descriptors {
    /// <summary>
    /// contains default users information
    /// </summary>
    public class XIdentityUserDescriptor {
        public string Id { get; set; }
        public string FirstName { get; set; }
        public string LastName { get; set; }
        public string UserName { get; set; }
        public string Email { get; set; }
        public bool EmailConfirmed { get; set; }
        public string PhoneNumber { get; set; }
        public bool PhoneNumberConfirmed { get; set; }
        public string Password { get; set; }
        public string Role { get; set; }
        public bool IsEnable { get; set; }
        public bool IsBanned { get; set; }
        public string DateOfBirth { get; set; }
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xIdentityModels\DI\XDIHelperExtension.cs

namespace xIdentityModels.DI {
    public static partial class XDIHelperExtension { }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xIdentityModels\Dtos\XDiscoveryDocumentDto.cs

using System.Collections.Generic;
using Newtonsoft.Json;

namespace xIdentityModels.Dtos
{
    public class XDiscoveryDocumentDto
    {
        [JsonProperty ("issuer")]
        public string Issuer { get; set; }

        [JsonProperty ("jwks_uri")]
        public string JwksUri { get; set; }

        [JsonProperty ("authorization_endpoint")]
        public string AuthorizationEndpoint { get; set; }

        [JsonProperty ("token_endpoint")]
        public string TokenEndpoint { get; set; }

        [JsonProperty ("userinfo_endpoint")]
        public string UserinfoEndpoint { get; set; }

        [JsonProperty ("end_session_endpoint")]
        public string EndSessionEndpoint { get; set; }

        [JsonProperty ("check_session_iframe")]
        public string CheckSessionIframe { get; set; }

        [JsonProperty ("revocation_endpoint")]
        public string RevocationEndpoint { get; set; }

        [JsonProperty ("introspection_endpoint")]
        public string IntrospectionEndpoint { get; set; }

        [JsonProperty ("device_authorization_endpoint")]
        public string DeviceAuthorizationEndpoint { get; set; }

        [JsonProperty ("frontchannel_logout_supported")]
        public bool FrontchannelLogoutSupported { get; set; }

        [JsonProperty ("frontchannel_logout_session_supported")]
        public bool FrontchannelLogoutSessionSupported { get; set; }

        [JsonProperty ("backchannel_logout_supported")]
        public bool BackchannelLogoutSupported { get; set; }

        [JsonProperty ("backchannel_logout_session_supported")]
        public bool BackchannelLogoutSessionSupported { get; set; }

        [JsonProperty ("scopes_supported")]
        public List<string> ScopesSupported { get; set; }

        [JsonProperty ("claims_supported")]
        public List<string> ClaimsSupported { get; set; }

        [JsonProperty ("grant_types_supported")]
        public List<string> GrantTypesSupported { get; set; }

        [JsonProperty ("response_types_supported")]
        public List<string> ResponseTypesSupported { get; set; }

        [JsonProperty ("response_modes_supported")]
        public List<string> ResponseModesSupported { get; set; }

        [JsonProperty ("token_endpoint_auth_methods_supported")]
        public List<string> TokenEndpointAuthMethodsSupported { get; set; }

        [JsonProperty ("id_token_signing_alg_values_supported")]
        public List<string> IdTokenSigningAlgValuesSupported { get; set; }

        [JsonProperty ("subject_types_supported")]
        public List<string> SubjectTypesSupported { get; set; }

        [JsonProperty ("code_challenge_methods_supported")]
        public List<string> CodeChallengeMethodsSupported { get; set; }

        [JsonProperty ("request_parameter_supported")]
        public bool RequestParameterSupported { get; set; }

        [JsonProperty ("account_api")]
        public string AccountApi { get; set; }        
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xIdentityModels\Dtos\XFriendDto.cs

using xIdentityModels.Constants;
using xModels.Base;

namespace xIdentityModels.Dtos
{
    /// <summary>
    /// All Available Friendship Types ...
    /// </summary>
    public enum XFriendshipType
    {
        Follower = 0,
        Following = 1,
    }

    /// <summary>
    /// a DTO Class Which Represent a User Friends ...
    /// </summary>
    public class XFriendDto : XBaseDto
    {
        public string Avatar { get; set; }
        public string UserId { get; set; }
        public string Username { get; set; }
        public string Lastname { get; set; }
        public string Firstname { get; set; }
        public XFriendshipType Type { get; set; }
        public XFriendshipState State { get; set; }
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xIdentityModels\Dtos\XFriendshipInfoDto.cs

using xModels.Base;
using xIdentityModels.Constants;

namespace xIdentityModels.Dtos {
    public class XFriendshipInfoDto : XBaseDto {
        public string UserId { get; set; }
        public bool IsFollower { get; set; }
        public bool IsFollowing { get; set; }
        public XFriendshipState FollowerState { get; set; }
        public XFriendshipState FollowingState { get; set; }
        public long Followers { get; set; }
        public long Followings { get; set; }
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xIdentityModels\Dtos\XIdentityMessageDto.cs

using xModels.Base;

namespace xIdentityModels.Dtos {
    public class XIdentityMessageDto : XBaseDto {
        public string Language { get; set; }
        public string ResourceTitle { get; set; }
        public string TranslatedValue { get; set; }
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xIdentityModels\Dtos\XOpenActionDto.cs

using System;
using xCommons.Extensions;
using xModels.Base;
using xModels.Dtos;

namespace xIdentityModels.Dtos
{
    /// <summary>
    /// a List of Available Open Actions ...
    /// </summary>
    public struct XOpenActions
    {
        public const string HandShake = "HandShake";
        public const string GetUserInfo = "GetUserInfo";
        public const string GetUserInfos = "GetUserInfos";
    }

    /// <summary>
    /// Open Actions Request Model ...
    /// </summary>
    public class XOpenActionRequestDto : XBaseDto
    {
        //
        public string Action { get; set; }
        public string Payload { get; set; }
        public string Checksum { get; set; }
        public XDeviceDto Device { get; set; }
        public string Timestamp { get; set; }

        /// <summary>
        /// Validate Model ...
        /// </summary>
        /// <returns></returns>
        public bool Validate()
        {
            //
            var result =
                !Device.IsNull() &&
                !Timestamp.IsNull() &&
                !Action.IsNullOrEmpty() &&
                (Action == XOpenActions.HandShake ||
                Action == XOpenActions.GetUserInfo ||
                Action == XOpenActions.GetUserInfos) &&
                !Int64.Parse(Timestamp).FromTimestamp().IsExPired();

            //
            return result;
        }

        /// <summary>
        /// Checksum Digest Model ...
        /// </summary>
        /// <returns></returns>
        public string ToOpenActionToken()
        {
            //
            var result = string.Empty;
            if (!Validate())
            {
                return result;
            }

            //
            var tmp = this;
            tmp.Checksum = string.Empty;

            //
            result = $"{tmp.ToJSON()}"
                .ToMd5String();
            return result;
        }

        /// <summary>
        /// Validate a Token is Correspond to Model or not ...
        /// </summary>
        /// <param name="token"></param>
        /// <returns></returns>
        public bool ValidateToken(string token)
        {
            //
            var result =
                Validate() &&
                !token.IsNullOrEmpty() &&
                token == ToOpenActionToken();

            //
            return result;
        }
    }

    /// <summary>
    /// aa Dto which used between Api's ...
    /// </summary>
    public class XOpenActionInnerDto : XBaseDto
    {
        public string Token { get; set; }
        public string Payload { get; set; }
    }

    /// <summary>
    /// User Info Providing in Open Actions ...
    /// </summary>
    public class XOpenActionUserInfoDto : XBaseDto
    {
        public string Username { get; set; }
        public string Firstname { get; set; }
        public string Lastname { get; set; }
        public string Avatar { get; set; }
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xIdentityModels\Dtos\XProfileImageDto.cs

using System;
using Newtonsoft.Json;
using xModels.Base;

namespace xIdentityModels.Dtos {
    public class XProfileImageDto : XBaseDto {
        public int Id { get; set; }

        [JsonProperty (
            "name",
            Required = Required.Default,
            NullValueHandling = NullValueHandling.Ignore)]
        public string Name { get; set; }

        [JsonProperty (
            "thumb",
            Required = Required.Default,
            NullValueHandling = NullValueHandling.Ignore)]
        public string Thumb { get; set; }

        [JsonProperty (
            "path",
            Required = Required.Default,
            NullValueHandling = NullValueHandling.Ignore)]
        public string Path { get; set; }

        [JsonProperty (
            "thumbPath",
            Required = Required.Default,
            NullValueHandling = NullValueHandling.Ignore)]
        public string ThumbPath { get; set; }

        [JsonProperty (
            "creationDate",
            Required = Required.Default,
            NullValueHandling = NullValueHandling.Ignore)]
        public DateTime CreationDate { get; set; }
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xIdentityModels\Dtos\XUserNameIdRequest.cs

using System.Collections.Generic;
using xModels.Base;

namespace xIdentityModels.Dtos {
    public class XUserNameIdRequest : XBaseDto {
        public IEnumerable<string> Ids { get; set; }
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xIdentityModels\Dtos\XUserNameIdResponse.cs

using xModels.Base;

namespace xIdentityModels.Dtos {
    public class XUserNameIdResponse : XBaseDto {
        public string Id { get; set; }
        public string UserName { get; set; }
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xIdentityModels\Dtos\XUserProfileDto.cs

using System;
using System.Collections.Generic;
using Newtonsoft.Json;
using xIdentityModels.Constants;
using xModels.Base;

namespace xIdentityModels.Dtos {
    public class XUserProfileDto : XBaseDto {
        [JsonProperty (
            "userId",
            Required = Required.Default,
            NullValueHandling = NullValueHandling.Ignore)]
        public string UserId { get; set; }

        [JsonProperty (
            "userName",
            Required = Required.Default,
            NullValueHandling = NullValueHandling.Ignore)]
        public string UserName { get; set; }

        [JsonProperty (
            "email",
            Required = Required.Default,
            NullValueHandling = NullValueHandling.Ignore)]
        public string Email { get; set; }

        [JsonProperty (
            "emailConfirmed",
            Required = Required.Default,
            NullValueHandling = NullValueHandling.Ignore)]
        public bool EmailConfirmed { get; set; }

        [JsonProperty (
            "phoneNumber",
            Required = Required.Default,
            NullValueHandling = NullValueHandling.Ignore)]
        public string PhoneNumber { get; set; }

        [JsonProperty (
            "phoneNumberConfirmed",
            Required = Required.Default,
            NullValueHandling = NullValueHandling.Ignore)]
        public bool PhoneNumberConfirmed { get; set; }

        [JsonProperty (
            "firstName",
            Required = Required.Default,
            NullValueHandling = NullValueHandling.Ignore)]
        public string FirstName { get; set; }

        [JsonProperty (
            "lastName",
            Required = Required.Default,
            NullValueHandling = NullValueHandling.Ignore)]
        public string LastName { get; set; }

        [JsonProperty (
            "dateOfBirth",
            Required = Required.Default,
            NullValueHandling = NullValueHandling.Ignore)]
        public DateTime? DateOfBirth { get; set; }

        [JsonProperty (
            "creationDate",
            Required = Required.Default,
            NullValueHandling = NullValueHandling.Ignore)]
        public DateTime? CreationDate { get; set; }

        [JsonProperty (
            "lastLogin",
            Required = Required.Default,
            NullValueHandling = NullValueHandling.Ignore)]
        public DateTime? LastLogin { get; set; }

        [JsonProperty (
            "avatar",
            Required = Required.Default,
            NullValueHandling = NullValueHandling.Ignore)]
        public string Avatar { get; set; }

        [JsonProperty (
            "gender",
            Required = Required.Default,
            NullValueHandling = NullValueHandling.Ignore)]
        public XGender Gender { get; set; }

        [JsonProperty (
            "bio",
            Required = Required.Default,
            NullValueHandling = NullValueHandling.Ignore)]
        public string Bio { get; set; }

        [JsonProperty (
            "coverImage",
            Required = Required.Default,
            NullValueHandling = NullValueHandling.Ignore)]
        public string CoverImage { get; set; }

        [JsonProperty (
            "openToSearch",
            Required = Required.Default,
            NullValueHandling = NullValueHandling.Ignore)]
        public bool OpenToSearch { get; set; }

        [JsonProperty (
            "friendshipInfo",
            Required = Required.Default,
            NullValueHandling = NullValueHandling.Ignore)]
        public XFriendshipInfoDto FriendshipInfo { get; set; }

        [JsonProperty (
            "roles",
            Required = Required.Default,
            NullValueHandling = NullValueHandling.Ignore)]
        public ICollection<string> Roles { get; set; } = new HashSet<string> ();

        [JsonProperty (
            "avatars",
            Required = Required.Default,
            NullValueHandling = NullValueHandling.Ignore)]
        public ICollection<XProfileImageDto> Avatars { get; set; } = new HashSet<XProfileImageDto> ();

        [JsonProperty (
            "isEnable",
            Required = Required.Default,
            NullValueHandling = NullValueHandling.Ignore)]
        public bool IsEnable { get; set; }

        [JsonProperty (
            "isBanned",
            Required = Required.Default,
            NullValueHandling = NullValueHandling.Ignore)]
        public bool IsBanned { get; set; }
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xIdentityModels\Extensions\DIExtensions.cs

using Microsoft.Extensions.DependencyInjection;
using xCommons.Extensions;
using xIdentityModels.Interfaces;
using xIdentityModels.Providers;

namespace xIdentityModels.Extensions {
    public static class DIExtensions {
        /// <summary>
        /// since registering IXUserRoleHelper need to add default instance if
        /// user not provided we create this helper ...
        /// </summary>
        /// <param name="services"></param>
        public static void AddXUserRoleHandler (
            this IServiceCollection services,
            IXUserRoleHelper helper = null
        ) {
            //
            // Check if Provider is null ...
            if (helper.IsNull ()) {
                helper = services.GetRegisteredService<IXUserRoleHelper> ();
            }

            //
            // check if Provider registered or not ...
            if (helper.IsNull ()) {
                //
                // Create Default provider ...
                services.AddSingleton<IXUserRoleHelper> (new XDefaultUserRoleHelper ());
            } else {
                //
                // Register Given Helper ...
                services.AddSingleton<IXUserRoleHelper> (helper);
            }
        }
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xIdentityModels\Extensions\XIdentityExtensions.cs

using System.Collections.Generic;
using xCommons.Extensions;
using xExceptions.Constants;
using xIdentityModels.Constants;
using xIdentityModels.Models;

namespace xIdentityModels.Extensions {
    public static class XIdentityExtensions {
        public static XUserSelectBy GetUserSelectByType (
            this string source,
            bool forceUserSelectByParamNotEmpty = true,
            bool forceUserSelectByTypeMustSpecified = false
        ) {
            //
            // Validate Args ...
            if (source.IsNullOrEmpty () &&
                forceUserSelectByParamNotEmpty) {
                XException.InvalidArgs.Throw ();
            }

            //
            var result = XUserSelectBy.NotSpecified;
            var userSelectByParam = source.ToNormalString ();
            if (userSelectByParam.IsValidEmail ()) {
                //
                // Find User by Email ...
                result = XUserSelectBy.Email;
            } else if (userSelectByParam.IsValidMobileNumber ()) {
                //
                // Find User by Mobile Number ...
                result = XUserSelectBy.MobileNumber;
            } else if (userSelectByParam.IsGuid ()) {
                //
                // Find User By it's ID ...
                result = XUserSelectBy.ID;
            } else {
                //
                // UserName ...
                result = XUserSelectBy.Username;
            }

            //
            // Validation Result ...
            if (forceUserSelectByTypeMustSpecified &&
                result == XUserSelectBy.NotSpecified) {
                XException.InvalidData.Throw ();
            }

            //
            return result;
        }

        public static string GetUserSelectByParam (
            this XActionRequest source,
            bool forceNotNull = true,
            ICollection<XUserSelectBy> excludes = null
        ) {
            //
            // Validate Args ...
            if (source.IsNull ()) {
                XException.InvalidArgs.Throw ();
            }

            //
            var id = source.UserId;
            var userName = source.UserName;
            var email = source.Email;
            var phoneNumber = source.MobileNumber;

            //
            if (excludes != null) {
                //
                if (excludes.Contains (XUserSelectBy.ID)) {
                    id = null;
                }
                if (excludes.Contains (XUserSelectBy.Email)) {
                    email = null;
                }
                if (excludes.Contains (XUserSelectBy.MobileNumber)) {
                    phoneNumber = null;
                }
                if (excludes.Contains (XUserSelectBy.Username)) {
                    userName = null;
                }
            }

            //
            var selectByParam =
                id.IsNullOrEmpty () ?
                userName.IsNullOrEmpty () ?
                email.IsNullOrEmpty () ?
                phoneNumber.IsNullOrEmpty () ? null : phoneNumber : email : userName : id;

            //
            // Check result ...
            if (forceNotNull &&
                selectByParam.IsNullOrEmpty ()) {
                XException.InvalidData.Throw ();
            }

            //
            return selectByParam;
        }
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xIdentityModels\Extensions\xIdentityModelsExtensions.cs

using System.Collections.Generic;
using System.Linq;
using xCommons.Extensions;
using xIdentityModels.Configurations;
using xIdentityModels.Constants;
using xIdentityModels.Dtos;
using xIdentityModels.Models;

namespace xIdentityModels.Extensions
{
    public static class xIdentityModelsExtensions
    {
        /// <summary>
        /// Converts a User Entity to Profile Dto ...
        /// </summary>
        /// <param name="source"></param>
        /// <param name="isAdmin"></param>
        /// <param name="isSameUser"></param>
        /// <param name="roles"></param>
        /// <param name="friendship"></param>
        /// <param name="profileConfig"></param>
        /// <returns></returns>
        public static XUserProfileDto ToXProfileDto(
            this XUser source,
            bool isAdmin = false,
            bool isSameUser = false,
            IEnumerable<string> roles = null,
            XFriendshipInfoDto friendship = null,
            XIdentityProfile profileConfig = null
        )
        {
            //
            XUserProfileDto result = null;

            //
            if (roles == null)
            {
                roles = new List<string>();
            }

            //
            // Prepare Dto ...
            if (!source.IsNullOrDefault())
            {
                //
                result = new XUserProfileDto
                {
                    Bio = source.Bio,
                    UserId = source.Id,
                    Email = source.Email,
                    Roles = roles.ToList(),
                    Avatar = source.Avatar,
                    IsEnable = source.IsEnable,
                    IsBanned = source.IsBanned,
                    UserName = source.UserName,
                    LastName = source.LastName,
                    FriendshipInfo = friendship,
                    FirstName = source.FirstName,
                    LastLogin = source.LastLogin,
                    CoverImage = source.CoverImage,
                    PhoneNumber = source.PhoneNumber,
                    DateOfBirth = source.DateOfBirth,
                    CreationDate = source.CreationDate,
                    OpenToSearch = source.OpenToSearch,
                    Gender = (XGender)(int)source.Gender,
                    EmailConfirmed = source.EmailConfirmed,
                    PhoneNumberConfirmed = source.PhoneNumberConfirmed,
                    Avatars = source.Avatars.Select(pfi =>
                    {
                        //
                        return new XProfileImageDto
                        {
                            Id = pfi.Id,
                            Name = pfi.Name,
                            Path = pfi.Path,
                            Thumb = pfi.Thumb,
                            ThumbPath = pfi.ThumbPath,
                            CreationDate = pfi.CreationDate
                        };
                    }).ToList(),
                };
            }

            //
            // Apply Profiling Configuration ...

            //
            bool isPassed = false;

            //
            // Handle Friendship ...
            isPassed = !isSameUser;
            if (!isPassed)
            {
                result.FriendshipInfo = null;
            }

            //
            // Handle Email Info ...
            isPassed = isAdmin || isSameUser || (!profileConfig.IsNullOrDefault() && profileConfig.ContainsEmail);
            if (!isPassed)
            {
                result.Email = string.Empty;
                result.EmailConfirmed = false;
            }

            //
            // Handle PhoneNumber Info ...
            isPassed = isAdmin || isSameUser || (!profileConfig.IsNullOrDefault() && profileConfig.ContainsPhoneNumber);
            if (!isPassed)
            {
                source.PhoneNumber = string.Empty;
                source.PhoneNumberConfirmed = false;
            }

            //
            // Handle Last Login ...
            isPassed = isAdmin || isSameUser || (!profileConfig.IsNullOrDefault() && profileConfig.ContainsLastLogin);
            if (!isPassed)
            {
                result.LastLogin = null;
            }

            //
            // Handle Date Of Birth ...
            isPassed = isAdmin || isSameUser || (!profileConfig.IsNullOrDefault() && profileConfig.ContainsDateOfBirth);
            if (!isPassed)
            {
                result.DateOfBirth = null;
            }

            //
            // Handle Creation Date ...
            isPassed = isAdmin || isSameUser || (!profileConfig.IsNullOrDefault() && profileConfig.ContainsCreationDate);
            if (!isPassed)
            {
                result.CreationDate = null;
            }

            //
            // Handle Roles ...
            isPassed = isAdmin || isSameUser || (!profileConfig.IsNullOrDefault() && profileConfig.ContainsRoles);
            if (!isPassed)
            {
                result.Roles = new List<string>();
            }

            //
            return result;
        }

        /// <summary>
        /// Check Specified User Has Access to Provided Roles ...
        /// </summary>
        /// <param name="source"></param>
        /// <param name="roles"></param>
        /// <returns></returns>
        public static bool HasAccess(
            this XUserClaimsInfoDto source,
            string[] roles
        )
        {
            //
            var result = 
                !source.IsNullOrDefault() &&
                source.Roles
                    .Any(r => roles
                        .Any(ar => r.ToNormalString()
                            .Contains(ar.ToNormalString())));

            //
            return result;
        }

        /// <summary>
        /// Check Specified User Contains Specified UserSelectByParam or not ...
        /// </summary>
        /// <param name="source"></param>
        /// <param name="userSelectByParam"></param>
        /// <returns></returns>
        public static bool ContainsUserSelectByParam(
            this XUser source,
            string userSelectByParam
        )
        {
            //
            var result =
                !source.IsNull() &&
                !userSelectByParam.IsNullOrEmpty() &&
                (source.Id == userSelectByParam ||
                source.Email.ToNormalString() == userSelectByParam.ToNormalString() ||
                source.UserName.ToNormalString() == userSelectByParam.ToNormalString() ||
                source.PhoneNumber.ToNormalString() == userSelectByParam.ToNormalString());

            //
            return result;
        }
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xIdentityModels\Extensions\XModelExtensions.cs

using System;
using System.Collections.Generic;
using xCommons.Extensions;
using xIdentityModels.Descriptors;
using xIdentityModels.Models;
using xIdentityModels.Navigations;

namespace xIdentityModels.Extensions {
    public static class XModelExtensions {
        /// <summary>
        /// /// Convert XIdentityUserDescriptor instance to XUser
        /// </summary>
        /// <param name="source"></param>
        /// <returns></returns>
        public static XUser ToXUser (this XIdentityUserDescriptor source) {
            return new XUser {
                Id = source.Id,
                    FirstName = source.FirstName,
                    LastName = source.LastName,
                    UserName = source.UserName,
                    Email = source.Email,
                    EmailConfirmed = source.EmailConfirmed,
                    PhoneNumber = source.PhoneNumber,
                    PhoneNumberConfirmed = source.PhoneNumberConfirmed,
                    IsEnable = true,
                    IsBanned = false,
                    CreationDate = DateTime.UtcNow,
                    DateOfBirth = DateTime.Parse (source.DateOfBirth)
            };
        }

        /// <summary>
        /// Check a User is Same as Descriptor User
        /// </summary>
        /// <param name="source"></param>
        /// <param name="dest"></param>
        /// <returns></returns>
        public static bool IsSameAs (this XUser source, XIdentityUserDescriptor dest) {
            //
            if (source.IsNull () ||
                dest.IsNull ()) {
                return false;
            }

            //
            var isSame = source.IsSameContent (dest, propertyWhiteList : new [] {
                    nameof (XIdentityUserDescriptor.FirstName),
                    nameof (XIdentityUserDescriptor.LastName),
                    nameof (XIdentityUserDescriptor.UserName),
                    nameof (XIdentityUserDescriptor.Email),
                    nameof (XIdentityUserDescriptor.EmailConfirmed),
                    nameof (XIdentityUserDescriptor.PhoneNumber),
                    nameof (XIdentityUserDescriptor.PhoneNumberConfirmed),
                    nameof (XIdentityUserDescriptor.IsEnable),
                    nameof (XIdentityUserDescriptor.IsBanned),
                    nameof (XIdentityUserDescriptor.DateOfBirth)
                },
                propertyValueCheckers : new [] {
                    new KeyValuePair<string, Func<XUser, XIdentityUserDescriptor, bool>> (
                        nameof (XIdentityUserDescriptor.DateOfBirth),
                        (user, descriptorUser) => {
                            //
                            var descriptorUserDateOfBirth = DateTime.Parse (descriptorUser.DateOfBirth);
                            return DateTime.Equals (user.DateOfBirth, descriptorUserDateOfBirth);
                        })
                }
            );

            //
            return isSame;
        }

        /// <summary>
        /// Check to XDevice instance to be same or not
        /// </summary>
        /// <param name="source"></param>
        /// <param name="dest"></param>
        /// <returns></returns>
        public static bool IsSameAs (this XDevice source, XDevice dest) {
            //
            if (source.IsNull () ||
                dest.IsNull ()) {
                return false;
            }

            //
            var isSame = source.Os.ToNormalString () == dest.Os.ToNormalString () &&
                source.OsVersion.ToNormalString () == dest.OsVersion.ToNormalString () &&
                source.Browser.ToNormalString () == dest.Browser.ToNormalString () &&
                source.UserAgent.ToNormalString () == dest.UserAgent.ToNormalString () &&
                source.DeviceType == dest.DeviceType;

            //
            return isSame;
        }

        /// <summary>
        /// convert UserClaimsInfo to TokenResponse ...
        /// </summary>
        /// <param name="source"></param>
        /// <returns></returns>
        public static XTokenResponse ToXTokenResponse (this XUserClaimsInfoDto source) {
            //
            if (source.IsNull () ||
                (source.AccessToken.IsNullOrEmpty () && source.RefreshToken.IsNullOrEmpty ())) {
                return null;
            }

            //
            var result = new XTokenResponse {
                AccessToken = source.AccessToken,
                RefreshToken = source.RefreshToken,
                ExpiresAt = source.ExpiresAt
            };

            //
            return result;
        }
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xIdentityModels\Extensions\XTokenExtensions.cs

using System;
using System.IdentityModel.Tokens.Jwt;
using System.Linq;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Security.Claims;
using System.Threading.Tasks;
using IdentityModel.Client;
using Microsoft.AspNetCore.Authentication;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc.Filters;
using Microsoft.IdentityModel.Tokens;
using xCommons.Constants;
using xCommons.Extensions;
using xExceptions.Constants;
using xIdentityModels.Constants;
using xIdentityModels.Models;

namespace xIdentityModels.Extensions {
    public static class XTokenExtensions {
        //
        #region Identity Token Extensions ...
        /// <summary>
        /// Convert a SecurityToken to it's Token String
        /// </summary>
        /// <param name="source"></param>
        /// <param name="tokenHandler"></param>
        /// <returns></returns>
        public static string ToTokenString (
            this SecurityToken source,
            JwtSecurityTokenHandler tokenHandler
        ) {
            return tokenHandler.WriteToken (source);
        }

        /// <summary>
        /// Validate a Token
        /// </summary>
        /// <param name="token"></param>
        /// <param name="tokenHandler"></param>
        /// <param name="tokenValidationParams"></param>
        /// <returns></returns>
        public static bool ValidateToken (
            this string token,
            JwtSecurityTokenHandler tokenHandler,
            TokenValidationParameters tokenValidationParams) {
            //
            if (token.IsNullOrEmpty ()) {
                return false;
            }

            //
            SecurityToken tokenObj = null;
            try {
                tokenHandler.ValidateToken (token, tokenValidationParams, out tokenObj);
            } catch {
                return false;
            }

            //
            return tokenObj != null;
        }

        /// <summary>
        /// Convert a token string to Security Token
        /// </summary>
        /// <param name="token"></param>
        /// <param name="tokenHandler"></param>
        /// <param name="tokenValidationParams"></param>
        /// <returns></returns>
        public static SecurityToken ToSecurityToken (
            this string token,
            JwtSecurityTokenHandler tokenHandler,
            TokenValidationParameters tokenValidationParams) {
            //
            if (token.IsNullOrEmpty () ||
                !token.ValidateToken (tokenHandler, tokenValidationParams)) {
                //
                return null;
            }

            //
            // convert token from String to JWTSecurity Token ...
            try {
                return tokenHandler.ReadToken (token);
            } catch {
                return null;
            }
        }

        /// <summary>
        /// Parse Action Token and return Corresponding RegistrationRequestDto
        /// </summary>
        /// <param name="token"></param>
        /// <param name="tokenHandler"></param>
        /// <param name="tokenValidationParams"></param>
        /// <returns></returns>
        public static XActionRequestToken ParseActionRequestToken (
            this string token,
            JwtSecurityTokenHandler tokenHandler,
            TokenValidationParameters tokenValidationParams) {
            //
            if (token.IsNullOrEmpty () ||
                !token.ValidateToken (tokenHandler, tokenValidationParams)) {
                //
                return null;
            }

            //
            // convert token from String to JWTSecurity Token ...
            JwtSecurityToken tokenObj = null;
            try {
                tokenObj = tokenHandler.ReadToken (token) as JwtSecurityToken;
            } catch {
                return null;
            }

            //
            if (tokenObj == null) {
                return null;
            }

            //
            // Extract Registered Payload Claims ...
            var mCurrentStepClaim = tokenObj.Claims
                .FirstOrDefault (c => c.Type == nameof (XActionRequestToken.Action));
            var mContextClaim = tokenObj.Claims
                .FirstOrDefault (c => c.Type == nameof (XActionRequestToken.Context));
            var mTokenClaim = tokenObj.Claims
                .FirstOrDefault (c => c.Type == nameof (XActionRequestToken.Token));

            //
            // Check All Claims to be NotNull ...
            if (mCurrentStepClaim == null ||
                mContextClaim == null ||
                mTokenClaim == null) {
                return null;
            }

            //
            // Reading all Claims Values ...
            var mCurrentStepStr = mCurrentStepClaim.Value;
            var mCurrentStep = 0;
            try {
                int.TryParse (mCurrentStepStr, out mCurrentStep);
            } catch { }

            //
            var mContext = mContextClaim.Value.IsNullOrEmpty () ?
                null : mContextClaim.Value.FromJSON<XActionRequestContext> ();
            var mToken = mTokenClaim.Value;

            //
            // Create Instance of UserInvite ...
            var result = new XActionRequestToken {
                Action = (XAction) mCurrentStep,
                Context = mContext,
                Token = mToken
            };

            //
            return result;
        }

        /// <summary>
        /// Check to ActionRequestContext object is same or not 
        /// </summary>
        /// <param name="source"></param>
        /// <param name="dest"></param>
        /// <returns></returns>
        public static bool IsSameAs (
            this XActionRequestContext source,
            XActionRequestContext dest
        ) {
            //
            if (source == null ||
                dest == null) {
                return false;
            }

            //
            var result = source.ToJSON () == dest.ToJSON ();

            //
            return result;
        }

        /// <summary>
        /// Convert a RegistrationRequestDto object to it's jwt token Claims
        /// </summary>
        /// <param name="source"></param>
        /// <returns></returns>        
        public static Claim[] ToJwtClaims (this XActionRequestToken source) {
            //
            // Generate Required Fields ...
            var action = source.Action;
            var context = source.Context;
            var token = source.Token;

            //
            // Generate Claims Array ...
            var claims = new Claim[] {
                new Claim (nameof (XActionRequestToken.Action), ((int) action).ToString (), ClaimValueTypes.Integer),
                new Claim (nameof (XActionRequestToken.Context), context == null ? "" : context.ToJSON (), ClaimValueTypes.String),
                new Claim (nameof (XActionRequestToken.Token), token.IsNullOrEmpty () ? "" : token, ClaimValueTypes.String)
            };

            //
            // Return Result ...
            return claims;
        }

        /// <summary>
        /// Generate a SecurityToken based on RegistrationRequestDto object
        /// </summary>
        /// <param name="source"></param>
        /// <param name="tokenHandler"></param>
        /// <param name="tokenDescriptor"></param>
        /// <returns></returns>
        public static SecurityToken ToJwtToken (
            this XActionRequestToken source,
            JwtSecurityTokenHandler tokenHandler,
            SecurityTokenDescriptor tokenDescriptor) {
            //
            // Getting Claims ...
            var claims = source.ToJwtClaims ();
            tokenDescriptor.Subject = new ClaimsIdentity (claims);

            //
            // Generate Token Object ...
            var tokenObject = tokenHandler.CreateToken (tokenDescriptor);

            //
            // Return Result ...
            return tokenObject;
        }
        #endregion

        //
        #region IdentityServer Token Extensions ...
        /// <summary>
        /// Retrieve Tokens From Headers
        /// </summary>
        /// <param name="source"></param>
        /// <returns></returns>
        public static XTokenResponse RetrieveTokens (this HttpRequest source) {
            //
            var accessToken = source.Headers[XAuthorization.Header].ToString ();
            var refreshToken = source.Headers[XAuthorization.RefreshToken].ToString ();

            //
            var expiresAtStr = source.Headers[XAuthorization.ExpiresAt].ToString ();
            long expiresAt = expiresAtStr.ConvertTo<long> ();

            //
            if (accessToken
                .ToNormalString ()
                .Contains (XAuthorization.TokenIdentifier.ToNormalString ())) {
                accessToken = accessToken.Remove (0, XAuthorization.TokenIdentifier.Length);
            }

            //
            return new XTokenResponse {
                AccessToken = accessToken,
                    RefreshToken = refreshToken,
                    ExpiresAt = expiresAt
            };
        }

        /// <summary>
        /// Retrieve Tokens From HttpContext
        /// </summary>
        /// <param name="source"></param>
        /// <returns></returns>
        public static async Task<XTokenResponse> RetrieveTokens (this HttpContext source) {
            //
            var accessToken = await source.GetTokenAsync (XAuthorization.AccessToken);
            if (accessToken
                .ToNormalString ()
                .Contains (XAuthorization.TokenIdentifier.ToNormalString ())) {
                accessToken = accessToken.Remove (0, XAuthorization.TokenIdentifier.Length);
            }

            var refreshToken = await source.GetTokenAsync (XAuthorization.RefreshToken);
            var expiresAtStr = await source.GetTokenAsync (XAuthorization.ExpiresAt);
            long expiresAt = expiresAtStr.ConvertTo<long> ();

            //
            var headerRequestTokens = source.Request.RetrieveTokens ();

            //
            var result = new XTokenResponse {
                AccessToken = accessToken ?? headerRequestTokens.AccessToken,
                RefreshToken = refreshToken ?? headerRequestTokens.RefreshToken,
                ExpiresAt = expiresAt != 0 ? expiresAt : headerRequestTokens.ExpiresAt
            };

            //
            return result;
        }

        /// <summary>
        /// Retrieve Tokens From ActionExecutingContext
        /// </summary>
        /// <param name="source"></param>
        /// <returns></returns>
        public static async Task<XTokenResponse> RetrieveTokens (this ActionExecutingContext source) {
            //
            var result = await source.HttpContext.RetrieveTokens ();
            return result;
        }

        /// <summary>
        /// Retrieve Tokens From XUserInfo instance
        /// </summary>
        /// <param name="source"></param>
        /// <returns></returns>
        public static XTokenResponse RetrieveTokens (this XUserClaimsInfoDto source) {
            //
            var result = new XTokenResponse {
                AccessToken = source.AccessToken,
                RefreshToken = source.RefreshToken,
                ExpiresAt = source.ExpiresAt
            };

            //
            return result;
        }

        /// <summary>
        /// Retrieve Tokens From IHeader Dictionary 
        /// </summary>
        /// <param name="source"></param>
        /// <returns></returns>
        public static XTokenResponse RetrieveTokens (this IHeaderDictionary source) {
            //
            var accessToken = source[XAuthorization.Header].ToString () ?? "";
            if (accessToken
                .ToNormalString ()
                .Contains (XAuthorization.TokenIdentifier.ToNormalString ())) {
                accessToken = accessToken.Remove (0, XAuthorization.TokenIdentifier.Length);
            }

            //
            var refreshToken = source[XAuthorization.RefreshToken].ToString () ?? "";

            //
            var expiresAtStr = source[XAuthorization.ExpiresAt].ToString () ?? "";
            var expiresAt = expiresAtStr.ConvertTo<long> ();

            //
            var result = new XTokenResponse {
                AccessToken = accessToken,
                RefreshToken = refreshToken,
                ExpiresAt = expiresAt
            };

            //
            return result;
        }

        /// <summary>
        /// Generate XTokenResponse instance based on TokenResponse
        /// </summary>
        /// <param name="source"></param>
        /// <returns></returns>
        public static XLoginResponse CreateXLoginResponse (this TokenResponse source) {
            //
            if (source.IsNull () ||
                source.IsError) {
                XException.InvalidToken.Throw ();
            }

            //
            var expiresAt = new DateTimeOffset (DateTime.UtcNow)
                .ToUnixTimeSeconds () +
                source.ExpiresIn;

            //
            var result = new XLoginResponse {
                AccessToken = source.AccessToken,
                RefreshToken = source.RefreshToken,
                ExpiresAt = expiresAt
            };

            //
            return result;
        }

        /// <summary>
        /// Generate XTokenResponse instance based on TokenResponse
        /// </summary>
        /// <param name="source"></param>
        /// <returns></returns>
        public static XTokenResponse CreateXTokenResponse (this TokenResponse source) {
            //
            if (source.IsNull () ||
                source.IsError) {
                XException.InvalidToken.Throw ();
            }

            //
            var expiresAt = new DateTimeOffset (DateTime.UtcNow)
                .ToUnixTimeSeconds () +
                source.ExpiresIn;

            //
            var result = new XTokenResponse {
                AccessToken = source.AccessToken,
                RefreshToken = source.RefreshToken,
                ExpiresAt = expiresAt
            };

            //
            return result;
        }

        /// <summary>
        /// Convert XLoginResponse to XTokenResponse
        /// </summary>
        /// <param name="source"></param>
        /// <returns></returns>
        public static XTokenResponse ToXTokenResponse (this XLoginResponse source) {
            //
            if (source.IsNull ()) {
                return null;
            }

            //
            return new XTokenResponse {
                AccessToken = source.AccessToken,
                    RefreshToken = source.RefreshToken,
                    ExpiresAt = source.ExpiresAt
            };
        }

        /// <summary>
        /// Add Authorization Tokens in Headers of
        /// Specific IHeaderDictionary instance
        /// </summary>
        /// <param name="source"></param>
        /// <param name="model"></param>
        public static void SetXAuthenticationTokens (
            this IHeaderDictionary source,
            XLoginResponse model,
            string secret = null
        ) {
            //
            source.Remove (XAuthorization.Header);
            source.Remove (XAuthorization.RefreshToken);
            source.Remove (XAuthorization.ExpiresAt);
            source.Remove (XAuthorization.RevisionChecksum);

            //
            source.Add (XAuthorization.Header, $"{XAuthorization.TokenIdentifier}{model.AccessToken}");
            source.Add (XAuthorization.RefreshToken, $"{model.RefreshToken}");
            source.Add (XAuthorization.ExpiresAt, $"{model.ExpiresAt}");

            //
            if (!secret.IsNullOrEmpty ()) {
                var revisionChecksum = model.GetRevisionChecksum (secret);
                source.Add (XAuthorization.RevisionChecksum, revisionChecksum);
            }
        }

        /// <summary>
        /// Add Authorization Tokens in Headers of
        /// Specific IHeaderDictionary instance
        /// </summary>
        /// <param name="source"></param>
        /// <param name="model"></param>
        public static void SetXAuthenticationTokens (
            this IHeaderDictionary source,
            XTokenResponse model,
            string secret = null
        ) {
            //
            source.Remove (XAuthorization.Header);
            source.Remove (XAuthorization.RefreshToken);
            source.Remove (XAuthorization.ExpiresAt);
            source.Remove (XAuthorization.RevisionChecksum);

            //
            source.Add (XAuthorization.Header, $"{XAuthorization.TokenIdentifier}{model.AccessToken}");
            source.Add (XAuthorization.RefreshToken, $"{model.RefreshToken}");
            source.Add (XAuthorization.ExpiresAt, $"{model.ExpiresAt}");

            //
            if (!secret.IsNullOrEmpty ()) {
                var revisionChecksum = model.GetRevisionChecksum (secret);
                source.Add (XAuthorization.RevisionChecksum, revisionChecksum);
            }
        }

        /// <summary>
        /// Add Authorization Tokens in Headers of
        /// Specific IHeaderDictionary instance
        /// </summary>
        /// <param name="source"></param>
        /// <param name="model"></param>
        public static void SetXAuthenticationTokens (
            this HttpRequestHeaders source,
            XLoginResponse model
        ) {
            //
            source.Remove (XAuthorization.Header);
            source.Remove (XAuthorization.RefreshToken);
            source.Remove (XAuthorization.ExpiresAt);
            source.Remove (XAuthorization.RevisionChecksum);

            //
            source.Add (XAuthorization.Header, $"{XAuthorization.TokenIdentifier}{model.AccessToken}");
            source.Add (XAuthorization.RefreshToken, $"{model.RefreshToken}");
            source.Add (XAuthorization.ExpiresAt, $"{model.ExpiresAt}");
        }

        /// <summary>
        /// Add Authorization Tokens in Headers of
        /// Specific IHeaderDictionary instance
        /// </summary>
        /// <param name="source"></param>
        /// <param name="model"></param>
        public static void SetXAuthenticationTokens (
            this HttpRequestHeaders source,
            XTokenResponse model
        ) {
            //
            source.Remove (XAuthorization.Header);
            source.Remove (XAuthorization.RefreshToken);
            source.Remove (XAuthorization.ExpiresAt);
            source.Remove (XAuthorization.RevisionChecksum);

            //
            source.Add (XAuthorization.Header, $"{XAuthorization.TokenIdentifier}{model.AccessToken}");
            source.Add (XAuthorization.RefreshToken, $"{model.RefreshToken}");
            source.Add (XAuthorization.ExpiresAt, $"{model.ExpiresAt}");
        }

        /// <summary>
        /// Add Authorization Tokens in Headers of
        /// Specific HttpRequest instance
        /// </summary>
        /// <param name="source"></param>
        /// <param name="model"></param>
        public static void SetXAuthenticationTokens (
            this HttpRequest source,
            XLoginResponse model
        ) {
            source.Headers.SetXAuthenticationTokens (model);
        }

        /// <summary>
        /// Add Authorization Tokens in Headers of
        /// Specific HttpRequest instance
        /// </summary>
        /// <param name="source"></param>
        /// <param name="model"></param>
        public static void SetXAuthenticationTokens (
            this HttpRequest source,
            XTokenResponse model
        ) {
            source.Headers.SetXAuthenticationTokens (model);
        }

        /// <summary>
        /// Add Authorization Tokens in Headers of
        /// Specific HttpRequest instance
        /// </summary>
        /// <param name="source"></param>
        /// <param name="model"></param>
        public static void SetXAuthenticationTokens (
            this HttpRequestMessage source,
            XLoginResponse model
        ) {
            source.Headers.SetXAuthenticationTokens (model);
        }

        /// <summary>
        /// Add Authorization Tokens in Headers of
        /// Specific HttpRequest instance
        /// </summary>
        /// <param name="source"></param>
        /// <param name="model"></param>
        public static void SetXAuthenticationTokens (
            this HttpRequestMessage source,
            XTokenResponse model
        ) {
            source.Headers.SetXAuthenticationTokens (model);
        }

        /// <summary>
        /// Add ReNewed Authorization Tokens in Headers of 
        /// Specific Response.
        /// Later in HttpInterceptors we can Look for AccessToken-ReNewed
        /// header Value and Renew User Tokens based on it
        /// </summary>
        /// <param name="source"></param>
        /// <param name="model"></param>
        public static void SetXAuthenticationTokens (
            this HttpResponse source,
            XLoginResponse model,
            string secret
        ) {
            source.Headers.SetXAuthenticationTokens (model, secret);
        }

        /// <summary>
        /// Add ReNewed Authorization Tokens in Headers of 
        /// Specific Response.
        /// Later in HttpInterceptors we can Look for AccessToken-ReNewed
        /// header Value and Renew User Tokens based on it
        /// </summary>
        /// <param name="source"></param>
        /// <param name="model"></param>
        public static void SetXAuthenticationTokens (
            this HttpResponse source,
            XTokenResponse model,
            string secret
        ) {
            source.Headers.SetXAuthenticationTokens (model, secret);
        }

        /// <summary>
        /// Determines a Token Can Refrsh or not
        /// </summary>
        /// <param name="source"></param>
        /// <returns></returns>
        public static bool IsRefreshable (this XLoginResponse source) {
            //
            var containsTokenData = !source.IsNull () &&
                !source.AccessToken.IsNullOrEmpty () &&
                !source.RefreshToken.IsNullOrEmpty ();
            if (!containsTokenData) {
                return false;
            }

            //
            var current = new DateTimeOffset (DateTime.UtcNow)
                .ToUnixTimeSeconds ();

            //
            // var result = current > source.ExpiresAt || current > source.ExpiresAt - XAuthorization.ThresholdBeforeTokenExpiration;
            var result = current > source.ExpiresAt - XAuthorization.ThresholdBeforeTokenExpiration;

            //
            return result;
        }

        /// <summary>
        /// Determines a Token Can Refrsh or not
        /// </summary>
        /// <param name="source"></param>
        /// <returns></returns>
        public static bool IsRefreshable (this XTokenResponse source) {
            //
            var containsTokenData = !source.IsNull () &&
                !source.AccessToken.IsNullOrEmpty () &&
                !source.RefreshToken.IsNullOrEmpty ();
            if (!containsTokenData) {
                return false;
            }

            //
            var current = new DateTimeOffset (DateTime.UtcNow)
                .ToUnixTimeSeconds ();

            //
            // var result = current > source.ExpiresAt || current > source.ExpiresAt - XAuthorization.ThresholdBeforeTokenExpiration;
            var result = current > source.ExpiresAt - XAuthorization.ThresholdBeforeTokenExpiration;

            //
            return result;
        }

        /// <summary>
        /// Generate a Revision Checksum for new Tokens
        /// </summary>
        /// <param name="source"></param>
        /// <param name="secret"></param>
        /// <returns></returns>
        public static string GetRevisionChecksum (
            this XLoginResponse source,
            string secret
        ) {
            return (source.AccessToken +
                    secret +
                    source.RefreshToken +
                    secret +
                    source.ExpiresAt.ToString ()
                )
                .ToMd5String ();
        }

        /// <summary>
        /// Generate a Revision Checksum for new Tokens
        /// </summary>
        /// <param name="source"></param>
        /// <param name="secret"></param>
        /// <returns></returns>
        public static string GetRevisionChecksum (
            this XTokenResponse source,
            string secret
        ) {
            return (source.AccessToken +
                    secret +
                    source.RefreshToken +
                    secret +
                    source.ExpiresAt.ToString ()
                )
                .ToMd5String ();
        }

        /// <summary>
        /// Check an XLoginResponse instance is Valid with it's revision
        /// </summary>
        /// <param name="source"></param>
        /// <param name="checksum"></param>
        /// <param name="secret"></param>
        /// <returns></returns>
        public static bool ValidateRevisionChecksum (
            this XLoginResponse source,
            string checksum,
            string secret
        ) {
            //
            var xChecksum = source.GetRevisionChecksum (secret);
            return checksum == xChecksum;
        }

        /// <summary>
        /// Check an XTokenResponse instance is Valid with it's revision
        /// </summary>
        /// <param name="source"></param>
        /// <param name="checksum"></param>
        /// <param name="secret"></param>
        /// <returns></returns>
        public static bool ValidateRevisionChecksum (
            this XTokenResponse source,
            string checksum,
            string secret
        ) {
            //
            var xChecksum = source.GetRevisionChecksum (secret);
            return checksum == xChecksum;
        }
        #endregion
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xIdentityModels\Interfaces\IXUserRoleHelper.cs

using xIdentityModels.Models;

namespace xIdentityModels.Interfaces {
    public interface IXUserRoleHelper {
        bool canReadCriticalData (XUserClaimsInfoDto userInfo);
        bool canDoDangerousAction (XUserClaimsInfoDto userInfo);
        bool isInRole (XUserClaimsInfoDto userInfo, string role);
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xIdentityModels\Models\XActionRequest.cs

using System;
using Microsoft.AspNetCore.Http;
using xIdentityModels.Navigations;

namespace xIdentityModels.Models {
    /// <summary>
    /// represent a system wide actions
    /// </summary>
    public class XActionRequest {
        /// <summary>
        /// Client Device Locale
        /// </summary>
        /// <value>user's client device local such as en-US</value>
        public string Lang { get; set; } = null;
        /// <summary>
        /// Requested Action Token
        /// </summary>
        /// <value>a hashed content</value>
        public string ActionToken { get; set; } = null;
        /// <summary>
        /// user's device
        /// </summary>
        /// <value>an instance of <see>XDevice</see> which represent user's device</value>
        public XDevice Device { get; set; } = null;
        /// <summary>
        /// FirstName 
        /// </summary>
        /// <value>users FirstName</value>
        public string FirstName { get; set; } = null;
        /// <summary>
        /// LastName 
        /// </summary>
        /// <value>user's LastName</value>
        public string LastName { get; set; } = null;
        /// <summary>
        /// an Optional Value which represetns User's DateOfBirth
        /// </summary>
        /// <value>user's DateOfBirth</value>
        public DateTime? DateOfBirth { get; set; } = DateTime.MinValue;
        /// <summary>
        /// User's Id
        /// </summary>
        /// <value>a GUID string which represent user's Id</value>
        public string UserId { get; set; } = null;
        /// <summary>
        /// UserName
        /// </summary>
        /// <value>user's UserName</value>
        public string UserName { get; set; } = null;
        /// <summary>
        /// Email
        /// </summary>
        /// <value>user's Email address</value>
        public string Email { get; set; } = null;
        /// <summary>
        /// MobileNumber / PhoneNumber
        /// </summary>
        /// <value>user's PhoneNumber</value>
        public string MobileNumber { get; set; } = null;
        /// <summary>
        /// Password
        /// </summary>
        /// <value>user's Password</value>
        public string Password { get; set; } = null;
        /// <summary>
        /// NewPassword
        /// </summary>
        /// <value>a passwor string which used to Change/Reset password</value>
        public string NewPassword { get; set; } = null;
        /// <summary>
        /// EmailVerificationCode
        /// </summary>
        /// <value>a Verification Code which assign to user's for confirm it's Email Address</value>
        public string EmailVerificationCode { get; set; } = null;
        /// <summary>
        /// MobileVerificationCode
        /// </summary>
        /// <value>a Verification Code which assign to user's for confirm it's Phone Number</value>
        public string MobileVerificationCode { get; set; } = null;
        /// <summary>
        /// Thumbnail
        /// </summary>
        /// <value>an instance of <see>IFormFile</see> which is used as user's avatar</value>
        public IFormFile Thumbnail { get; set; }
        /// <summary>
        /// ReturnUrl
        /// </summary>
        /// <value>
        /// a url string which used in many used cases for providing a way to lead users to right places.
        /// </value>
        public string ReturnUrl { get; set; } = null;
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xIdentityModels\Models\XActionRequestContext.cs

using System;
using Microsoft.AspNetCore.Http;
using xIdentityModels.Navigations;

namespace xIdentityModels.Models {
    public class XActionRequestContext {
        //
        public string Lang { get; set; }

        //
        public string UserId { get; set; }
        public string UserName { get; set; }

        //
        public string MobileNumber { get; set; }
        public string MobileVerificationCode { get; set; }
        public bool MobileVerified { get; set; }

        //
        public string Email { get; set; }
        public string EmailVerificationCode { get; set; }
        public bool EmailVerified { get; set; }

        //
        public string FirstName { get; set; }
        public string LastName { get; set; }
        public DateTime DateOfBirth { get; set; }

        //
        public XDevice Device { get; set; }
        public IFormFile Thubmnail { get; set; }
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xIdentityModels\Models\XActionRequestToken.cs

using xCommons.Extensions;
using xIdentityModels.Constants;

namespace xIdentityModels.Models {
    public class XActionRequestToken {
        public XAction Action { get; set; }
        public XActionRequestContext Context { get; set; }
        public string Token { get; set; }

        public void Prepare (string secret) {
            Token = (Action.ToString () +
                secret +
                Context.ToJSON ()).ToMd5String ();
        }

        public bool Validate (string secret) {
            return (Action.ToString () +
                secret +
                Context.ToJSON ()).ToMd5String () == Token;
        }
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xIdentityModels\Models\XActionResponse.cs

using System;
using Newtonsoft.Json;

namespace xIdentityModels.Models {
    /// <summary>
    /// represent a system wide action result
    /// </summary>
    public class XActionResponse {
        /// <summary>
        /// ActionToken
        /// </summary>
        /// <value>a hashed string which carry required info for doing system actions.</value>
        [JsonProperty (
            "token",
            Required = Required.Default,
            NullValueHandling = NullValueHandling.Ignore)]
        public string Token { get; set; }

        /// <summary>
        /// ActionToken Lifetime
        /// </summary>
        /// <value>an instance of <see>DateTime</see> which represent token expiration time</value>
        [JsonProperty (
            "expiration",
            Required = Required.DisallowNull,
            NullValueHandling = NullValueHandling.Ignore)]
        public DateTime Expiration { get; set; }
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xIdentityModels\Models\XBannedDevice.cs

using System;
using System.ComponentModel.DataAnnotations.Schema;
using xCommons.Extensions;
using xIdentityModels.Navigations;
using xModels.Base;

namespace xIdentityModels.Models {
    public class XBannedDevice : XBaseIntIDEntity {
        public DateTime BannedOn { get; set; }

        public string DeviceStr { get; set; }

        [NotMapped]
        public XDevice Device {
            get {
                return DeviceStr.FromJSON<XDevice> ();
            }
            set {
                DeviceStr = value.ToJSON ();
            }
        }
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xIdentityModels\Models\XLoginRequest.cs

using System.ComponentModel.DataAnnotations;
using xIdentityModels.Navigations;

namespace xIdentityModels.Models {
    /// <summary>
    /// Represent Requirements for Authenticationg a User
    /// </summary>
    public class XLoginRequest {
        /// <summary>
        /// how select an specific User
        /// </summary>
        /// <value>an string value which represent how system select user such as: UserName, Email Address or MobileNumber</value>
        [Required]
        public string UserSelectBy { get; set; }

        /// <summary>
        /// user's password
        /// </summary>
        /// <value>an string which represent user's pasword</value>
        [Required]
        public string Password { get; set; }

        /// <summary>
        /// user's device
        /// </summary>
        /// <value>an instance of <see>XDevice</see> which represent user's device</value>
        public XDevice Device { get; set; }

        /// <summary>
        /// user's language
        /// </summary>
        /// <value>an string which represent user's language and locale, such as: en-US</value>
        public string Language { get; set; }
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xIdentityModels\Models\XLoginResponse.cs

using xIdentityModels.Dtos;

namespace xIdentityModels.Models {
    public class XLoginResponse : XTokenResponse {
        public XUserProfileDto Profile { get; set; }
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xIdentityModels\Models\XProfileUpdateRequest.cs

using System;
using System.Collections.Generic;
using xIdentityModels.Constants;

namespace xIdentityModels.Models {
    public class XProfileUpdateRequest {
        public string Email { get; set; }
        public bool? EmailConfirmed { get; set; }
        public string PhoneNumber { get; set; }
        public bool? PhoneNumberConfirmed { get; set; }
        public string FirstName { get; set; }
        public string LastName { get; set; }
        public string Avatar { get; set; }
        public DateTime? DateOfBirth { get; set; }
        public DateTime? CreationDate { get; set; }
        public DateTime? LastLogin { get; set; }
        public XGender? Gender { get; set; }
        public ICollection<string> Roles { get; set; } = new HashSet<string> ();
        public bool? IsEnable { get; set; }
        public bool? IsBanned { get; set; }
        public string Bio { get; set; }
        public string CoverImage { get; set; }
        public bool OpenToSearch { get; set; }
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xIdentityModels\Models\XToken.cs

using System.ComponentModel.DataAnnotations.Schema;
using xCommons.Extensions;
using xIdentityModels.Constants;
using xIdentityModels.Navigations;
using xModels.Base;

namespace xIdentityModels.Models {
    public class XToken : XBaseIntIDEntity {
        public string Token { get; set; }
        public string Hash { get; set; }
        public string UserSelectByParam { get; set; }
        public string DeviceStr { get; set; }
        public XAction Type { get; set; }

        [NotMapped]
        public XDevice Device {
            get {
                return DeviceStr.FromJSON<XDevice> ();
            }

            set {
                DeviceStr = value.ToJSON ();
            }
        }
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xIdentityModels\Models\XTokenResponse.cs

using System.ComponentModel.DataAnnotations;

namespace xIdentityModels.Models {
    public class XTokenResponse {
        [Required]
        public string AccessToken { get; set; }
        public string RefreshToken { get; set; }
        public long ExpiresAt { get; set; }
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xIdentityModels\Models\XUserClaimsInfoDto.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Security.Claims;
using xCommons.Constants;
using xCommons.Extensions;
using xCommons.Helpers;
using xExceptions.Constants;
using xIdentityModels.Constants;
using xModels.Base;

namespace xIdentityModels.Models
{
    public class XUserClaimsInfoDto : XBaseDto
    {
        //
        #region Properties ...
        public string AccessToken { get; }
        public string RefreshToken { get; }
        public long ExpiresAt { get; }
        public string UserId { get; }
        public string UserName { get; }
        public string FirstName { get; }
        public string LastName { get; }
        public string Picture { get; }
        public string Email { get; }
        public string PhoneNumber { get; }
        public XGender Gender { get; }
        public bool IsBanned { get; }
        public bool IsEnabled { get; }
        public bool EmailConfirmed { get; }
        public bool PhoneNumberConfirmed { get; }
        public string Bio { get; set; }
        public string CoverImage { get; set; }
        public bool OpenToSearch { get; set; }
        public long? ExpiredOn { get; }
        public long? AuthenticatedOn { get; }
        public DateTime? BrithDate { get; }
        public IEnumerable<string> Issuers { get; } = new HashSet<string>();
        public IEnumerable<string> Audiences { get; } = new HashSet<string>();
        public IEnumerable<string> ClientIds { get; } = new HashSet<string>();
        public IEnumerable<string> Scopes { get; } = new HashSet<string>();
        public IEnumerable<string> Roles { get; } = new HashSet<string>();
        #endregion

        //
        public XUserClaimsInfoDto() { }

        public XUserClaimsInfoDto(
            string accessToken,
            string refreshToken,
            long expiresAt,
            IEnumerable<Claim> claims
        )
        {
            //
            // refreshToken.IsNullOrEmpty ()
            if (claims.IsNull() ||
                accessToken.IsNullOrEmpty())
            {
                XException.InvalidArgs.Throw();
            }

            //
            // Attach XLogin Properties ...
            AccessToken = accessToken;
            RefreshToken = refreshToken;
            ExpiresAt = expiresAt;

            //
            if (!claims.IsNull())
            {
                //
                UserId = claims.FirstOrDefault(c => c.Type == XCustomClaims.UserId)?.Value ?? "";
                UserName = claims.FirstOrDefault(c => c.Type == XCustomClaims.UserName)?.Value ?? "";
                FirstName = claims.FirstOrDefault(c => c.Type == XCustomClaims.FirstName)?.Value ?? "";
                LastName = claims.FirstOrDefault(c => c.Type == XCustomClaims.LastName)?.Value ?? "";
                Picture = claims.FirstOrDefault(c => c.Type == XCustomClaims.Picture)?.Value ?? "";
                Email = claims.FirstOrDefault(c => c.Type == XCustomClaims.Email)?.Value ?? null;
                PhoneNumber = claims.FirstOrDefault(c => c.Type == XCustomClaims.PhoneNumber)?.Value ?? null;

                //
                Bio = claims.FirstOrDefault(c => c.Type == XCustomClaims.Bio)?.Value ?? null;
                CoverImage = claims.FirstOrDefault(c => c.Type == XCustomClaims.CoverImage)?.Value ?? null;

                //
                var openToSearchStr = claims.FirstOrDefault(c => c.Type == XCustomClaims.OpenToSearch)?.Value ?? null;
                if (openToSearchStr.IsNullOrEmpty())
                {
                    OpenToSearch = false;
                }
                else
                {
                    //
                    var openToSearch = false;
                    bool.TryParse(openToSearchStr, out openToSearch);

                    //
                    OpenToSearch = openToSearch;
                }

                //
                // Handle Gender ...
                var genders = ObjectHelper.ToEnumerableKeys<XGender>();
                var genderStr = claims.FirstOrDefault(c => c.Type == XCustomClaims.Gender).Value ?? null;
                if (genderStr.IsNullOrEmpty())
                {
                    Gender = XGender.Male;
                }
                else
                {
                    Gender = genderStr.GetValue<XGender>();
                }

                //
                // Handle IsBanned ...
                var isBannedStr = claims.FirstOrDefault(c => c.Type == XCustomClaims.IsBanned).Value ?? null;
                if (isBannedStr.IsNullOrEmpty())
                {
                    IsBanned = false;
                }
                else
                {
                    //
                    var isBanned = false;
                    Boolean.TryParse(isBannedStr, out isBanned);

                    //
                    IsBanned = isBanned;
                }

                //
                // Handle IsEnabled ...
                var isEnabledStr = claims.FirstOrDefault(c => c.Type == XCustomClaims.IsEnabled).Value ?? null;
                if (isEnabledStr.IsNullOrEmpty())
                {
                    IsEnabled = false;
                }
                else
                {
                    //
                    var isEnabled = false;
                    Boolean.TryParse(isEnabledStr, out isEnabled);

                    //
                    IsEnabled = isEnabled;
                }

                //
                // Handle Email Confirmed ...
                var emailConfirmedStr = claims.FirstOrDefault(c => c.Type == XCustomClaims.EmailVerified).Value ?? null;
                if (emailConfirmedStr.IsNullOrEmpty())
                {
                    EmailConfirmed = false;
                }
                else
                {
                    //
                    var emailConfirmed = false;
                    Boolean.TryParse(emailConfirmedStr, out emailConfirmed);

                    //
                    EmailConfirmed = emailConfirmed;
                }

                //
                // Handle PhoneNumber Confirmed ...
                var phoneNumberConfirmedStr = claims.FirstOrDefault(c => c.Type == XCustomClaims.PhoneNumberVerified).Value ?? null;
                if (phoneNumberConfirmedStr.IsNullOrEmpty())
                {
                    PhoneNumberConfirmed = false;
                }
                else
                {
                    //
                    var phoneNumberConfirmed = false;
                    Boolean.TryParse(phoneNumberConfirmedStr, out phoneNumberConfirmed);

                    //
                    PhoneNumberConfirmed = phoneNumberConfirmed;
                }

                //
                // Handle ExpiredOn ...
                var expiredOnStr = claims.FirstOrDefault(c => c.Type == XCustomClaims.ExpiredOn).Value ?? null;
                if (expiredOnStr.IsNullOrEmpty())
                {
                    ExpiredOn = null;
                }
                else
                {
                    //
                    long expiredOn = 0;
                    long.TryParse(expiredOnStr, out expiredOn);

                    //
                    ExpiredOn = expiredOn;
                }

                //
                // Handle AuthenticatedOn ...
                var authenticatedOnStr = claims.FirstOrDefault(c => c.Type == XCustomClaims.AuthenticatedOn).Value ?? null;
                if (authenticatedOnStr.IsNullOrEmpty())
                {
                    AuthenticatedOn = null;
                }
                else
                {
                    //
                    long authenticatedOn = 0;
                    long.TryParse(authenticatedOnStr, out authenticatedOn);

                    //
                    AuthenticatedOn = authenticatedOn;
                }

                //
                // Handle BrithDate ...
                var brithDateStr = claims.FirstOrDefault(c => c.Type == XCustomClaims.BrithDate)?.Value ?? "";
                if (brithDateStr.IsNullOrEmpty())
                {
                    // BrithDate = null;
                }
                else
                {
                    //
                    DateTime bDate;
                    DateTime.TryParse(brithDateStr, out bDate);

                    //
                    BrithDate = bDate;
                }

                //
                // Collections ...
                Issuers = claims.Where(c => c.Type == XCustomClaims.Issuer)?
                    .Select(c => c.Value) ?? new HashSet<string>();
                Audiences = claims.Where(c => c.Type == XCustomClaims.Audience)?
                    .Select(c => c.Value) ?? new HashSet<string>();
                ClientIds = claims.Where(c => c.Type == XCustomClaims.ClientId)?
                    .Select(c => c.Value) ?? new HashSet<string>();
                Scopes = claims.Where(c => c.Type == XCustomClaims.Scope)?
                    .Select(c => c.Value) ?? new HashSet<string>();
                Roles = claims.Where(c => c.Type == XCustomClaims.Role)?
                    .Select(c => c.Value) ?? new HashSet<string>();
            }
        }
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xIdentityModels\Models\XVerificationRequest.cs

using System;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
using xCommons.Extensions;
using xIdentityModels.Navigations;
using xModels.Base;

namespace xIdentityModels.Models {
    public class XVerificationRequest : XBaseIntIDEntity {

        [Required]
        public string VerificationCode { get; set; }

        public int NumberOfTries { get; set; }
        public DateTime LastTryOn { get; set; }

        [NotMapped]
        public XActionRequestToken Request {
            get {
                return RequestStr.FromJSON<XActionRequestToken> ();
            }
            set {
                RequestStr = value.ToJSON ();
            }
        }

        public string RequestStr { get; set; }

        [NotMapped]
        public XDevice Device {
            get {
                return DeviceStr.FromJSON<XDevice> ();
            }
            set {
                DeviceStr = value.ToJSON ();
            }
        }

        public string DeviceStr { get; set; }
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xIdentityModels\Navigations\XDevice.cs

using System.ComponentModel.DataAnnotations.Schema;
using xCommons.Constants;
using xModels.Base;

namespace xIdentityModels.Navigations {
    /// <summary>
    /// Represent a Client Device which used by User
    /// </summary>
    public class XDevice : XBaseIntIDEntity {
        /// <summary>
        /// Operating System
        /// </summary>
        /// <value>device operating system identifier</value>
        public string Os { get; set; }
        /// <summary>
        /// Operating System Version
        /// </summary>
        /// <value>which version of operatin system is in use</value>
        public string OsVersion { get; set; }
        /// <summary>
        /// Device Browser
        /// </summary>
        /// <value>the Browser identifier</value>
        public string Browser { get; set; }
        /// <summary>
        /// Browser Engine Agent
        /// </summary>
        /// <value>browser engine Agent</value>
        public string UserAgent { get; set; }
        /// <summary>
        /// Type of client Device
        /// </summary>
        /// <value>represent device type <see>XDeviceType</see></value>
        public XDeviceType DeviceType { get; set; }

        //
        #region User ...
        /// <summary>
        /// UserId
        /// </summary>
        /// <value>Represent this Devie belong to which User Identifier</value>
        public string UserId { get; set; }
        /// <summary>
        /// User
        /// </summary>
        /// <value>Represent Device User <see>XUser</see></value>
        [ForeignKey (nameof (UserId))]
        public virtual XUser User { get; set; }
        #endregion
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xIdentityModels\Navigations\XFriendshipFollower.cs

using System.ComponentModel.DataAnnotations.Schema;
using xIdentityModels.Constants;
using xModels.Base;

namespace xIdentityModels.Navigations {
    /// <summary>
    /// represent a Follower of specific User
    /// </summary>
    public class XFriendshipFollower : XBaseIntIDEntity {
        /// <summary>
        /// XFriendshipState
        /// </summary>
        /// <value>state of Friendship at current moment <see>XFriendshipState</see></value>
        public XFriendshipState State { get; set; }

        //
        #region User ...
        /// <summary>
        /// UserId
        /// </summary>
        /// <value>source User's Id</value>
        public string UserId { get; set; }
        /// <summary>
        /// User
        /// </summary>
        /// <value>source User <see>XUser</see></value>
        [ForeignKey (nameof (UserId))]
        public virtual XUser User { get; set; }
        #endregion

        //
        #region Dest User ...
        /// <summary>
        /// DestId
        /// </summary>
        /// <value>destination User's Id</value>
        public string DestId { get; set; }
        /// <summary>
        /// Dest
        /// </summary>
        /// <value>dest User <see>XUser</see></value>
        [ForeignKey (nameof (DestId))]
        public virtual XUser Dest { get; set; }
        #endregion
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xIdentityModels\Navigations\XFriendshipFollowing.cs

using System.ComponentModel.DataAnnotations.Schema;
using xIdentityModels.Constants;
using xModels.Base;

namespace xIdentityModels.Navigations {
    /// <summary>
    /// represent a Following of specific User
    /// </summary>
    public class XFriendshipFollowing : XBaseIntIDEntity {
        /// <summary>
        /// XFriendshipState
        /// </summary>
        /// <value>state of Friendship at current moment <see>XFriendshipState</see></value>
        public XFriendshipState State { get; set; }

        //
        #region User ...
        /// <summary>
        /// UserId
        /// </summary>
        /// <value>source User's Id</value>
        public string UserId { get; set; }
        /// <summary>
        /// User
        /// </summary>
        /// <value>source User <see>XUser</see></value>
        [ForeignKey (nameof (UserId))]
        public virtual XUser User { get; set; }
        #endregion

        //
        #region Dest User ...
        /// <summary>
        /// DestId
        /// </summary>
        /// <value>destination User's Id</value>
        public string DestId { get; set; }
        /// <summary>
        /// Dest
        /// </summary>
        /// <value>dest User <see>XUser</see></value>
        [ForeignKey (nameof (DestId))]
        public virtual XUser Dest { get; set; }
        #endregion
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xIdentityModels\Navigations\XProfileImage.cs

using System;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
using xModels.Base;

namespace xIdentityModels.Navigations {
    /// <summary>
    /// Represent a User's Avatar Entity
    /// </summary>
    public class XProfileImage : XBaseIntIDEntity {
        /// <summary>
        /// UserId
        /// </summary>
        /// <value>represent current Avatar belongs to which User</value>
        public string UserId { get; set; }
        /// <summary>
        /// User
        /// </summary>
        /// <value>User instance <see>XUser</see></value>
        [ForeignKey (nameof (UserId))]
        public XUser User { get; set; }
        /// <summary>
        /// Name
        /// </summary>
        /// <value>Avatar's file name</value>
        [Required]
        [StringLength (255)]
        public string Name { get; set; }
        /// <summary>
        /// Thumb
        /// </summary>
        /// <value>Avatar's thumbnail file's name</value>
        [Required]
        [StringLength (255)]
        public string Thumb { get; set; }
        /// <summary>
        /// Path
        /// </summary>
        /// <value>Avatar's Image path on Profile Server</value>
        [Required]
        [StringLength (255)]
        public string Path { get; set; }
        /// <summary>
        /// ThumbPath
        /// </summary>
        /// <value>Avatar's Thumbnail Image path on Profile Service</value>
        [Required]
        [StringLength (255)]
        public string ThumbPath { get; set; }
        /// <summary>
        /// CreationDate
        /// </summary>
        /// <value>Upload Time</value>
        public DateTime CreationDate { get; set; }
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xIdentityModels\Providers\XDefaultUserRoleHelper.cs

using System.Linq;
using xCommons.Extensions;
using xIdentityModels.Models;
using xIdentityModels.Interfaces;

namespace xIdentityModels.Providers {
    public class XDefaultUserRoleHelper : IXUserRoleHelper {
        public bool canReadCriticalData (XUserClaimsInfoDto userInfo) {
            return isInRole (userInfo, "admin");
        }

        public bool canDoDangerousAction (XUserClaimsInfoDto userInfo) {
            return isInRole (userInfo, "admin");
        }

        public bool isInRole (XUserClaimsInfoDto userInfo, string role) {
            return userInfo.Roles
                .Any (r =>
                    r.ToNormalString () == role.ToNormalString ()
                );
        }
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xIdentityModels\XApiToken.cs

using System.ComponentModel.DataAnnotations.Schema;
using xCommons.Extensions;
using xModels.Base;
using xIdentityModels.Models;

namespace xIdentityModels {
    public class XApiToken : XBaseIntIDEntity {
        public string Content { get; set; }

        [NotMapped]
        public XTokenResponse Tokens {
            get { return Content.IsNullOrEmpty () ? null : Content.FromJSON<XTokenResponse> (); }
            set { Content = value.ToJSON (); }
        }
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xIdentityModels\XUser.cs

using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
using Microsoft.AspNetCore.Identity;
using xIdentityModels.Constants;
using xIdentityModels.Navigations;

namespace xIdentityModels
{
    /// <summary>
    /// represnt a User of System
    /// </summary>
    public partial class XUser : IdentityUser
    {
        //
        #region Properties ...
        /// <summary>
        /// FirstName
        /// </summary>
        /// <value>user's FirstName</value>
        [Required]
        [StringLength(50)]
        public string FirstName { get; set; }
        /// <summary>
        /// LastName
        /// </summary>
        /// <value>user's LastName</value>
        [Required]
        [StringLength(100)]
        public string LastName { get; set; }
        /// <summary>
        /// User is Enabled or not
        /// </summary>
        /// <remarks>
        /// system was restrict Disabled Users access to Many Resources
        /// </remarks>
        /// <value>boolean value represent User is Enable or not</value>
        public bool IsEnable { get; set; }
        /// <summary>
        /// User is Banned or not
        /// </summary>
        /// <remarks>
        /// system was reject Banned Users access to Almost all Resources
        /// </remarks>
        /// <value>boolean value represent User is Banned or not</value>
        public bool IsBanned { get; set; }
        /// <summary>
        /// DateOfBirth
        /// </summary>
        /// <value>user's DateOfBirth</value>
        [Required]
        public DateTime DateOfBirth { get; set; }
        /// <summary>
        /// CreationDate
        /// </summary>
        /// <value>user's Creation/Registration Date</value>
        [Required]
        public DateTime CreationDate { get; set; }
        /// <summary>
        /// LastLogin
        /// </summary>
        /// <value>user's Last Successfull Login Date</value>
        public DateTime? LastLogin { get; set; }
        /// <summary>
        /// ProfileImage/Avatar
        /// </summary>
        /// <value>user's current Avatar</value>
        public string Avatar { get; set; }
        /// <summary>
        /// Gender
        /// </summary>
        /// <value>user's Gender</value>
        [Required]
        public XGender Gender { get; set; }
        /// <summary>
        /// User Biography ...
        /// </summary>
        /// <value></value>
        public string Bio { get; set; }
        /// <summary>
        /// User Bio Cover Image ...
        /// </summary>
        /// <value></value>
        public string CoverImage { get; set; }
        /// <summary>
        /// Can Discover User ...
        /// </summary>
        /// <value></value>
        public bool OpenToSearch { get; set; }
        #endregion

        //
        #region Navigation Properties ...
        /// <summary>
        /// User's Devices
        /// </summary>
        /// <typeparam name="XDevice"><see>XDevice</see></typeparam>
        /// <returns>a Collection of all assigned Devices to User</returns>
        [InverseProperty("User")]
        public virtual ICollection<XDevice> Devices { get; set; } = new HashSet<XDevice>();
        /// <summary>
        /// User's Avatars
        /// </summary>
        /// <typeparam name="XProfileImage"><see>XProfileImage</see></typeparam>
        /// <returns>a Collection of all assigned Avatars to User</returns>
        [InverseProperty("User")]
        public virtual ICollection<XProfileImage> Avatars { get; set; } = new HashSet<XProfileImage>();
        /// <summary>
        /// User's Followers
        /// </summary>
        /// <typeparam name="XFriendshipFollower"><see>XFriendshipFollower</see></typeparam>
        /// <returns>a Collection of all User's Followers</returns>
        [InverseProperty("User")]
        public virtual ICollection<XFriendshipFollower> Followers { get; set; } = new HashSet<XFriendshipFollower>();
        /// <summary>
        /// User's Followings
        /// </summary>
        /// <typeparam name="XFriendshipFollowing"><see>XFriendshipFollowing</see></typeparam>
        /// <returns>a Collection of all User's Followings</returns>
        [InverseProperty("User")]
        public virtual ICollection<XFriendshipFollowing> Followings { get; set; } = new HashSet<XFriendshipFollowing>();
        /// <summary>
        /// User's Roles
        /// </summary>
        /// <returns>a Collection of all User's Roles in System</returns>
        public virtual ICollection<IdentityUserRole<string>> Roles { get; set; } = new HashSet<IdentityUserRole<string>>();
        #endregion
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xIdentityService\Configuration\XIdentityServiceConfiguration.cs

using xIdentityService.Constants;

namespace xIdentityService.Configuration {
    public partial class XIdentityServiceConfiguration {
        public string Authority { get; set; }
        public string ApiName { get; set; }
        public string ApiSecret { get; set; }
        public string ClientId { get; set; }
        public string ClientSecret { get; set; }
        public string XPoweredValue { get; set; }
        public XTokenType TokenType { get; set; }
        public string XRevisionSecretKey { get; set; }
        public int DefaultClientTimeout { get; set; } = 360;
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xIdentityService\Configuration\XProxyConfiguration.cs

using System.Collections.Generic;
using xModels.Base;

namespace xIdentityService.Configuration {
    /// <summary>
    /// XProxy Middleware Configuration ...
    /// </summary>
    public class XProxyConfiguration {
        /// <summary>
        /// Proxy Host Address for Clients Which Use XProxy Server ...
        /// </summary>
        /// <value></value>
        public string Host { get; set; }

        /// <summary>
        /// if EnableXPoweredByAthorization property setted to true, this property determines
        /// the header must be this value ...
        /// </summary>
        /// <value></value>
        public string XPoweredValue { get; set; }

        /// <summary>
        /// Determines Proxy Http Handler Check SSL or not ...
        /// </summary>
        /// <value></value>
        public bool DisableSSLCheck { get; set; }

        /// <summary>
        /// Determines Http Client Handler Allow Auto Redirect or not ...
        /// </summary>
        /// <value></value>
        public bool AllowAutoRedirect { get; set; }

        /// <summary>
        /// Determines Proxy Server Log Received Requests or not ...
        /// </summary>
        /// <value></value>
        public bool EnableLogging { get; set; }

        /// <summary>
        /// DefineRoutes for Handling ...
        /// </summary>
        /// <value></value>
        public HashSet<XProxyRouteDescriptor> Routes { get; set; }
    }

    /// <summary>
    /// Describe a Proxy Route ...
    /// </summary>
    public class XProxyRouteDescriptor : XBaseDescriptor {
        /// <summary>
        /// Determines which route can handled for Proxyfing ...
        /// </summary>
        /// <value></value>
        public string Route { get; set; }

        /// <summary>
        /// Determines Proxy Server Handle Athorization or not ...
        /// </summary>
        /// <value></value>
        public bool EnableAuthorization { get; set; }

        /// <summary>
        /// Determines Which Scopes allowed to this route if authorizations enabled ...
        /// </summary>
        /// <value></value>
        public HashSet<string> AllowedScopes { get; set; }

        /// <summary>
        /// Determines Which Roles allowed to this route if authorizations enabled ...
        /// </summary>
        /// <value></value>
        public HashSet<string> AllowedRoles { get; set; }

        /// <summary>
        /// Determines XProxy Can Check XPowered By Authorization or not ...
        /// </summary>
        /// <value></value>
        public bool EnableXPoweredByAthorization { get; set; }
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xIdentityService\Constants\ConfigurationNodeNames.cs

namespace xIdentityService.Constants {
    public partial struct ConfigurationNodeNames {
        public const string XPROXY_CONFIGURATION_NODE_NAME = "ProxyConfiguration";
        public const string IDENTITY_SERVICE_NODE_NAME = "IdentityServiceConfiguration";
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xIdentityService\Constants\XApiAccountEndpoint.cs

using xExceptions.Attributes;

namespace xIdentityService.Constants
{
    public enum XApiAccountEndpoint
    {
        //
        #region Authentication ...
        [StringValue("Account/DiscoveryDocument")]
        DiscoveryDocument,

        [StringValue("Account/RequestScopeAccessToken")]
        RequestScopeAccessToken,

        [StringValue("Account/Authenticate")]
        Authenticate,

        [StringValue("Account/Login")]
        Login,

        [StringValue("Account/RefreshTokens")]
        RefreshTokens,

        [StringValue("Account/ChangePassword")]
        ChangePassword,

        [StringValue("Account/ResetPassword")]
        ResetPassword,
        #endregion

        //
        #region Proile ...
        [StringValue("Account/Profile/{ids}/GetNames")]
        GetNames,

        [StringValue("Account/Profile/GetNameIds")]
        GetNameIds,

        [StringValue("Account/Profile/{userSelectByParam}")]
        GetProfile,

        [StringValue("Account/Profile/Query")]
        QueryProfiles,

        [StringValue("Account/Profile/Avatars/Query/{userSelectByParam}")]
        QueryAvatars,

        [StringValue("Account/Profile/Update/{userSelectByParam}")]
        UpdateProfile,

        [StringValue("Account/Profile/{userSelectByParam}")]
        FullUpdateProfile,

        [StringValue("Account/Profile/Avatar")]
        AddAvatar,

        [StringValue("Account/Profile/Avatars")]
        AddAvatars,

        [StringValue("Account/Profile/Avatars/{ids}")]
        RemoveAvatars,

        [StringValue("Account/Profile/Avatars/{id}/Set")]
        SetAvatar,
        #endregion

        //
        #region Search ...
        [StringValue("Account/OpenToSearch/Query")]
        QueryOpenToSearchProfiles,
        #endregion

        //
        #region Registration ...
        [StringValue("Account/CanRegisterUserName/{userName}")]
        CanRegisterUserName,

        [StringValue("Account/CanRegisterMobileNumber/{mobileNumber}")]
        CanRegisterMobileNumber,

        [StringValue("Account/CanRegisterEmail/{email}")]
        CanRegisterEmail,

        [StringValue("Account/IsConfirmedEmail")]
        IsConfirmedEmail,

        [StringValue("Account/IsConfirmedMobile")]
        IsConfirmedMobile,

        [StringValue("Account/ConfirmRegistration")]
        ConfirmRegistration,

        [StringValue("Account/ConfirmMobileNumber")]
        ConfirmMobileNumber,

        [StringValue("Account/ConfirmEmailAddress")]
        ConfirmEmailAddress,

        [StringValue("Account/RequestConfirmMobile")]
        RequestConfirmMobile,

        [StringValue("Account/RequestConfirmEmail")]
        RequestConfirmEmail,

        [StringValue("Account/RequestResetPassword")]
        RequestResetPassword,

        [StringValue("Account/RequestConfirmRegistration")]
        RequestConfirmRegistration,

        [StringValue("Account/InviteUser")]
        InviteUser,

        [StringValue("Account/RequestRegistration")]
        RequestRegistration,

        [StringValue("Account/AddAccountInfo")]
        AddAccountInfo,

        [StringValue("Account/AttachProfileImage")]
        AttachProfileImage,

        [StringValue("Account/FinishRegistration")]
        FinishRegistration,
        #endregion

        //
        #region Friendship ...
        [StringValue("Account/Friendship/{destUser}/Follow")]
        Follow,

        [StringValue("Account/Friendship/{destUser}/Cancel")]
        Cancel,

        [StringValue("Account/Friendship/{destUser}/UnFollowFollower")]
        UnFollowFollower,

        [StringValue("Account/Friendship/{destUser}/UnFollowFollowing")]
        UnFollowFollowing,

        [StringValue("Account/Friendship/{destUser}/Block")]
        Block,

        [StringValue("Account/Friendship/{destUser}/UnBlock")]
        UnBlock,

        [StringValue("Account/Friendship/{destUser}/AcceptRequest")]
        AcceptRequest,

        [StringValue("Account/Friendship/{destUser}/RejectRequest")]
        RejectRequest,

        [StringValue("Account/Friendship/{destUser}/FriendshipInfo")]
        FriendshipInfo,

        [StringValue("Account/Friendship/{destUser}/IsFollower")]
        IsFollower,

        [StringValue("Account/Friendship/{destUser}/FollowerState")]
        FollowerState,

        [StringValue("Account/Friendship/{destUser}/Follower")]
        Follower,

        [StringValue("Account/Friendship/Followers")]
        Followers,

        [StringValue("Account/Friendship/AllFollowers")]
        AllFollowers,

        [StringValue("Account/Friendship/FollowersList")]
        FollowersList,

        [StringValue("Account/Friendship/QueryFollowers")]
        QueryFollowers,

        [StringValue("Account/Friendship/{destUser}/IsFollowing")]
        IsFollowing,

        [StringValue("Account/Friendship/{destUser}/FollowingState")]
        FollowingState,

        [StringValue("Account/Friendship/{destUser}/Following")]
        Following,

        [StringValue("Account/Friendship/Followings")]
        Followings,

        [StringValue("Account/Friendship/AllFollowings")]
        AllFollowings,

        [StringValue("Account/Friendship/FollowingsList")]
        FollowingsList,

        [StringValue("Account/Friendship/QueryFollowings")]
        QueryFollowings,
        #endregion

        //
        #region Admin ...
        [StringValue("Account/Ban")]
        Ban,

        [StringValue("Account/UnBan")]
        UnBan,

        [StringValue("Account/IsBanned/{userSelectByParam}")]
        IsBanned,
        #endregion

        //
        #region Open Actions ...
        [StringValue("Account/Open")]
        Open,
        #endregion
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xIdentityService\Constants\XAuthenticationScheme.cs

using xExceptions.Attributes;

namespace xIdentityService.Constants {
    public enum XAuthenticationScheme {
        [StringValue ("token")]
        XToken, 
        [StringValue ("introspection")]
        XIntrospection,
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xIdentityService\Constants\XHeader.cs

using xExceptions.Attributes;

namespace xIdentityService.Constants
{
    /// <summary>
    /// All Available Headers ...
    /// </summary>
    public enum XHeader
    {
        /// <summary>
        /// Hub Connection ID Header Keys ...
        /// </summary>
        [StringValue("requestID")]
        ConnectionId,
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xIdentityService\Constants\XParam.cs

using xExceptions.Attributes;

namespace xIdentityService.Constants {
    public enum XParam {
        [StringValue ("Content-Type")]
        XContentType,

        [StringValue ("{boundary}")]
        XBoundary,

        [StringValue ("{userSelectByParam}")]
        XUserSelectByParam,

        [StringValue ("{destUser}")]
        XDestUser,

        [StringValue ("{id}")]
        XId,

        [StringValue ("{ids}")]
        XIds,

        [StringValue ("Origin")]
        XOrigin,

        [StringValue ("{userName}")]
        XUserName,

        [StringValue ("{mobileNumber}")]
        XMobileNumber,

        [StringValue ("{email}")]
        XEmail,

        [StringValue ("role")]
        XRole,

        [StringValue ("forceRole")]
        XForceRole,

        [StringValue ("IsRefreshed")]
        XIsRefreshed,

        [StringValue ("file")]
        XFile,

        [StringValue ("files")]
        XFiles,

        [StringValue ("actionToken")]
        XActionToken,

        [StringValue ("request")]
        XRequest,

        [StringValue ("scope")]
        XScope,
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xIdentityService\Constants\XProxyConstants.cs

namespace xIdentityService.Constants {
    public struct XProxyConstants {
        public const string XPROXY_HTTP_CLIENT = "XProxyHttpClient";
        public const string XPROXY_FORWARD_HEADER = "xForwardHeader";
        public const string XPROXY_ACCEPTED_HEADERS = "xAcceptedHeaders";
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xIdentityService\Constants\XResponseContentTypes.cs

namespace xIdentityService.Constants {
    public struct XResponseContentTypes {
        public const string HTML = "text/html";
        public const string JSON = "application/json";
        public const string JavaScript = "text/javascript";
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xIdentityService\Constants\XTokenType.cs

namespace xIdentityService.Constants {
    public enum XTokenType {
        //
        // Summary:
        //     Self-contained Json Web Token
        Jwt,
        //
        // Summary:
        //     Reference token
        Reference
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xIdentityService\Controllers\XBaseIdentityApiController.cs

using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Logging;
using xCommons.Attributes;
using xCommons.Configurations;
using xCommons.Providers;
using xIdentityService.Interfaces;

namespace xIdentityService.Controllers
{
    /// <summary>
    /// Base Identity Api Controller 
    /// </summary>
    [ApiController]
    [RequireXPowered(true)]
    [Route("api/[controller]")]
    [Produces("application/json")]
    public abstract class XBaseIdentityApiController : XBaseIdentityController
    {
        protected XBaseIdentityApiController(
            ILogger logger, 
            XAppConfiguration appConfiguration, 
            IXIdentityProvider identityProvider, 
            XValidationProvider validationProvider
        ) : base(
            logger, 
            appConfiguration, 
            identityProvider, 
            validationProvider
        )
        { }
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xIdentityService\Controllers\XBaseIdentityApiV1Controller.cs

using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Logging;
using xCommons.Attributes;
using xCommons.Configurations;
using xCommons.Providers;
using xIdentityService.Interfaces;

namespace xIdentityService.Controllers
{
    /// <summary>
    /// Base Identity Api V1 Controller 
    /// </summary>
    [ApiController]
    [ApiVersion("1.0")]
    [RequireXPowered(true)]
    [Route("api/v{version:apiVersion}/[controller]")]
    public abstract class XBaseIdentityApiV1Controller : XBaseIdentityApiController
    {
        protected XBaseIdentityApiV1Controller(
            ILogger logger,
            XAppConfiguration appConfiguration,
            IXIdentityProvider identityProvider,
            XValidationProvider validationProvider
        ) : base(
            logger,
            appConfiguration,
            identityProvider,
            validationProvider
        )
        { }
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xIdentityService\Controllers\XBaseIdentityController.cs

using System.Collections.Generic;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Authentication;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Logging;
using xCommons.Configurations;
using xCommons.Constants;
using xCommons.Controllers;
using xCommons.Extensions;
using xCommons.Providers;
using xExceptions.Constants;
using xIdentityModels.Constants;
using xIdentityModels.Models;
using xIdentityService.Constants;
using xIdentityService.Interfaces;

namespace xIdentityService.Controllers
{
    public abstract class XBaseIdentityController : XBaseController
    {
        //
        public IXIdentityProvider IdentityProvider { get; }

        protected XBaseIdentityController(
            ILogger logger,
            XAppConfiguration appConfiguration,
            IXIdentityProvider identityProvider,
            XValidationProvider validationProvider
        ) : base(
            logger,
            appConfiguration,
            validationProvider
        )
        {
            IdentityProvider = identityProvider;
        }

        //
        #region NonActions ...
        /// <summary>
        /// Retrieve Connection ID for Hubs ...
        /// </summary>
        /// <returns></returns>
        [NonAction]
        public string GetConnectionId()
        {
            //
            var result = "";

            //
            var headerKey = XHeader.ConnectionId.GetStringValue();

            //
            // Check if Connection ID is Provided ...
            if (Request.Headers.ContainsKey(headerKey))
            {
                result = Request.Headers[headerKey];
            }

            //
            return result;
        }

        /// <summary>
        /// Retrieve User Identifier Base on XActionRequest
        /// </summary>
        /// <param name="model"></param>
        /// <param name="forceNotNull"></param>
        /// <param name="excludes"></param>
        /// <returns></returns>
        [NonAction]
        public string GetUserSelectByParam(
            XActionRequest model,
            bool forceNotNull = true,
            ICollection<XUserSelectBy> excludes = null
        )
        {
            //
            // Validate Args ...
            ValidationProvider.NotNull(model);

            //
            var result = IdentityProvider.GetUserSelectByParam(
                model,
                forceNotNull,
                excludes
            );

            //
            return result;
        }

        /// <summary>
        /// Retrieve Access Token
        /// </summary>
        /// <returns></returns>
        [NonAction]
        public async Task<string> GetAccessToken()
        {
            //
            var accessToken = Request.Headers[XAuthorization.Header].ToString();
            if (accessToken.IsNullOrEmpty())
            {
                //
                accessToken = await HttpContext
                    .GetTokenAsync(XAuthorization.AccessToken);
            }

            //
            if (accessToken
                .ToNormalString()
                .Contains(XAuthorization.TokenIdentifier
                    .ToNormalString()))
            {
                //
                accessToken = accessToken
                    .Remove(0, XAuthorization.TokenIdentifier.Length);
            }

            //
            return accessToken;
        }

        /// <summary>
        /// Retrieve Refresh Token
        /// </summary>
        /// <returns></returns>
        [NonAction]
        public async Task<string> GetRefreshToken()
        {
            //
            var refreshToken = Request.Headers[XAuthorization.RefreshToken].ToString();
            if (refreshToken.IsNullOrEmpty())
            {
                //
                refreshToken = await HttpContext
                    .GetTokenAsync(XAuthorization.RefreshToken);
            }

            //
            return refreshToken;
        }

        /// <summary>
        /// Retrieve Access Token Expiration Date
        /// </summary>
        /// <returns></returns>
        [NonAction]
        public async Task<long> GetTokenExpiresAt()
        {
            //
            var expiresAtStr = Request.Headers[XAuthorization.ExpiresAt].ToString();
            if (expiresAtStr.IsNullOrEmpty())
            {
                //
                expiresAtStr = await HttpContext
                    .GetTokenAsync(XAuthorization.ExpiresAt);
            }

            //
            var expiresAt = expiresAtStr.ConvertTo<long>();

            //
            return expiresAt;
        }

        /// <summary>
        /// Retrieve All Required Tokens
        /// </summary>
        /// <returns></returns>
        [NonAction]
        public async Task<XLoginResponse> RetrieveTokensAsXLoginResponse()
        {
            //
            var accessToken = await GetAccessToken();
            var refreshToken = await GetRefreshToken();
            var expiresAt = await GetTokenExpiresAt();

            //
            return new XLoginResponse
            {
                AccessToken = accessToken,
                RefreshToken = refreshToken,
                ExpiresAt = expiresAt
            };
        }

        /// <summary>
        /// Retrieve All Required Tokens
        /// </summary>
        /// <returns></returns>
        [NonAction]
        public async Task<XTokenResponse> RetrieveTokensAsXTokenResponse()
        {
            //
            var accessToken = await GetAccessToken();
            var refreshToken = await GetRefreshToken();
            var expiresAt = await GetTokenExpiresAt();

            //
            return new XTokenResponse
            {
                AccessToken = accessToken,
                RefreshToken = refreshToken,
                ExpiresAt = expiresAt
            };
        }

        /// <summary>
        /// Retrive UserInfo
        /// </summary>
        /// <returns></returns>
        [NonAction]
        public async Task<XUserClaimsInfoDto> GetUserInfo()
        {
            //
            var claims = User.Claims ?? null;
            if (!claims.HasChild())
            {
                return null;
            }

            var xTokens = await RetrieveTokensAsXTokenResponse();
            var result = new XUserClaimsInfoDto(
                xTokens.AccessToken,
                xTokens.RefreshToken,
                xTokens.ExpiresAt,
                User.Claims
            );

            //
            return result;
        }

        /// <summary>
        /// Validate User Authenticated and Retrieve User Info
        /// </summary>
        /// <returns></returns>
        [NonAction]
        public async Task<XUserClaimsInfoDto> ValidateAndGetUserInfo()
        {
            //
            if (!User.Identity.IsAuthenticated)
            {
                XException.NotAuthorized.Throw();
            }

            //
            var result = await GetUserInfo();
            if (result.IsNull())
            {
                XException.NotAuthorized.Throw();
            }

            //
            return result;
        }
        #endregion
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xIdentityService\DI\XDIHelperExtension.cs

using System;
using IdentityModel.AspNetCore.OAuth2Introspection;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using xCommons.Authorization;
using xCommons.Extensions;
using xIdentityService.Configuration;
using xIdentityService.Constants;
using xIdentityService.Interfaces;
using xIdentityService.Providers;
using xIdentityService.Security;

namespace xIdentityService.DI {
    public static partial class XDIHelperExtension {
        /// <summary>
        /// Extract Module Configuration Structure from IConfiguration interface 
        /// </summary>
        /// <param name="config"></param>
        /// <returns></returns>
        public static XIdentityServiceConfiguration GetXIdentityServiceConfiguration (this IConfiguration config) {
            //
            var xIdentityServiceConfigSection = config.GetSection (ConfigurationNodeNames.IDENTITY_SERVICE_NODE_NAME);
            return xIdentityServiceConfigSection.Get<XIdentityServiceConfiguration> ();
        }

        /// <summary>
        /// Register Service and All it's Requirements
        /// </summary>
        /// <param name="services"></param>
        /// <param name="configuration"></param>
        public static void AddXIdentityService (
            this IServiceCollection services,
            IConfiguration configuration,
            ServiceLifetime lifeTime = ServiceLifetime.Singleton
        ) {
            //
            var identityConfiguration = configuration.GetXIdentityServiceConfiguration ();
            AddIdentityService (
                services,
                identityConfiguration,
                lifeTime
            );
        }

        /// <summary>
        /// Register Service and All it's Requirements
        /// </summary>
        /// <param name="services"></param>
        /// <param name="configuration"></param>
        public static void AddXIdentityService (
            this IServiceCollection services,
            XIdentityServiceConfiguration configuration,
            ServiceLifetime lifeTime = ServiceLifetime.Singleton
        ) {
            AddIdentityService (services, configuration, lifeTime);
        }

        /// <summary>
        /// Register Custome Token Provider
        /// </summary>
        /// <param name="services"></param>
        /// <typeparam name="T"></typeparam>
        public static void AddXTokenProvider<T> (
            this IServiceCollection services,
            ServiceLifetime lifetime = ServiceLifetime.Singleton)
        where T : IXTokenProvider {
            //
            Console.WriteLine ("IdentityService: Add Custom Token Provider ...");
            services.Add (new ServiceDescriptor (typeof (IXTokenProvider), typeof (T), lifetime));
        }

        /// <summary>
        /// Use Authentication
        /// </summary>
        /// <param name="app"></param>
        public static void UseXIdentityService (this IApplicationBuilder app) {
            app.UseAuthentication ();
        }

        //
        #region Private ...
        private static void AddIdentityService (
            this IServiceCollection services,
            XIdentityServiceConfiguration config,
            ServiceLifetime lifeTime = ServiceLifetime.Singleton
        ) {
            //
            services.AddSingleton<XIdentityServiceConfiguration> (config);

            //
            var builder = services
                .AddAuthentication (XAuthenticationScheme.XToken.GetStringValue ());

            //
            // Add JWT Handler ...
            builder.AddJwtBearer (
                XAuthenticationScheme.XToken.GetStringValue (), options => {
                    //
                    options.Authority = config.Authority;
                    options.TokenValidationParameters.ValidateAudience = false;
                    options.TokenValidationParameters.ValidTypes = new [] { "at+jwt" };

                    //
                    options.ForwardDefaultSelector = context => {
                        //
                        var path = context.Request.Path.Value;

                        //
                        var fromHeader = TokenRetrieval.FromAuthorizationHeader ();
                        var fromQuery = TokenRetrieval.FromQueryString ();
                        var bearerToken = fromHeader (context.Request) ?? fromQuery (context.Request);

                        //
                        var result = XAuthenticationScheme.XToken.GetStringValue ();
                        if (!bearerToken.IsNull () && !bearerToken.Contains (".")) {
                            result = XAuthenticationScheme.XIntrospection.GetStringValue ();
                        }

                        //
                        return result;
                    };
                });

            //
            // Add OAuthIntrospect ...
            builder.AddOAuth2Introspection (
                XAuthenticationScheme.XIntrospection.GetStringValue (), options => {
                    //
                    options.Authority = config.Authority;
                    options.ClientId = config.ApiName;
                    options.ClientSecret = config.ClientSecret;

                    //
                    options.TokenRetriever = new Func<HttpRequest, string> (req => {
                        //
                        var fromHeader = TokenRetrieval.FromAuthorizationHeader ();
                        var fromQuery = TokenRetrieval.FromQueryString ();

                        //
                        var bearerToken = fromHeader (req) ?? fromQuery (req);

                        //
                        return bearerToken;
                    });
                });

            //
            // Register Authorization Handler ...
            services.AddSingleton<IAuthorizationHandler, RequiredRolesHandler> ();
            Console.WriteLine ("IdentityService: register Authorization Handlers  ...");

            //
            // Register Identity Provider ...
            services.Add (new ServiceDescriptor (typeof (IXIdentityProvider), typeof (XIdentityProvider), lifeTime));
            Console.WriteLine ("IdentityService: Register IdentityProvider ...");

            //
            // Try To Register InMemoryTokenProvier if it's not Provided ...
            IXTokenProvider xTokenProvider = null;
            try {
                xTokenProvider = services.GetRegisteredService<IXTokenProvider> ();
            } catch { }
            if (xTokenProvider.IsNull ()) {
                //
                Console.WriteLine ("IdentityService: there is no Custom Token Provider, Adding InMemoryTokenProvider instead ...");
                services.Add (new ServiceDescriptor (typeof (IXTokenProvider), typeof (XInMemoryTokenProvider), lifeTime));
            }

            //
            // Adding Security Provider ...
            services.Add (new ServiceDescriptor (typeof (IXSecurityProvider), typeof (XSecurityProvider), lifeTime));
            Console.WriteLine ("IdentityService: Register Security Provider ...");
        }
        #endregion
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xIdentityService\Extensions\AuthorizationPolicyBuilderExtensions.cs

using IdentityModel;
using Microsoft.AspNetCore.Authorization;

namespace xIdentityService.Extensions {
    public static class AuthorizationPolicyBuilderExtensions {
        /// <summary>
        /// Adds a policy to check for required scopes.
        /// </summary>
        /// <param name="builder"></param>
        /// <param name="scope">List of any required scopes. The token must contain at least one of the listed scopes.</param>
        /// <returns></returns>
        public static AuthorizationPolicyBuilder RequireScope (this AuthorizationPolicyBuilder builder, params string[] scope) {
            return builder.RequireClaim (JwtClaimTypes.Scope, scope);
        }
    }

    /// <summary>
    /// Helper for creating scope-related policies
    /// </summary>
    public static class ScopePolicy {
        /// <summary>
        /// Creates a policy to check for required scopes.
        /// </summary>
        /// <param name="scopes">List of any required scopes. The token must contain at least one of the listed scopes.</param>
        /// <returns></returns>
        public static AuthorizationPolicy Create (params string[] scopes) {
            return new AuthorizationPolicyBuilder ()
                .RequireScope (scopes)
                .Build ();
        }
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xIdentityService\Extensions\HttpContextExtensions.cs

using System.Threading.Tasks;
using Microsoft.AspNetCore.Authentication;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.DependencyInjection;
using xCommons.Constants;
using xCommons.Extensions;
using xIdentityModels.Models;
using xIdentityService.Constants;

namespace xIdentityService.Extensions {
    public static class HttpContextExtensions {
        /// <summary>
        /// Retrieve Authentication Service ...
        /// </summary>
        /// <param name="context"></param>
        /// <returns></returns>
        public static IAuthenticationService GetAuthenticationService (this HttpContext context) {
            //
            var result = context.RequestServices
                .GetRequiredService<IAuthenticationService> ();

            //
            return result;
        }

        /// <summary>
        /// Retrieve Specific Token from HttpContext ...
        /// </summary>
        /// <param name="context"></param>
        /// <param name="tokenName"></param>
        /// <param name="scheme"></param>
        /// <returns></returns>
        public static async Task<string> GetXTokenAsync (
            this HttpContext context,
            string tokenName,
            XAuthenticationScheme scheme = XAuthenticationScheme.XToken
        ) {
            //
            // Validate Args ...
            if (tokenName.IsNullOrEmpty ()) {
                return null;
            }

            //
            var authService = context.GetAuthenticationService ();
            if (authService.IsNull ()) {
                return null;
            }

            //
            var authResult = await authService
                .AuthenticateAsync (
                    context,
                    scheme
                    .GetStringValue ()
                );

            //
            var result = authResult?.Properties?
                .GetTokenValue (tokenName);
            return result;
        }

        /// <summary>
        /// Retrieve Access Token
        /// </summary>
        /// <returns></returns>
        public static async Task<string> GetAccessToken (this HttpContext context) {
            //
            var accessToken = context.Request.Headers[XAuthorization.Header]
                .ToString ();
            if (accessToken.IsNullOrEmpty ()) {
                accessToken = await context
                    .GetTokenAsync (XAuthorization.AccessToken);
            }

            //
            if (accessToken
                .ToNormalString ()
                .Contains (XAuthorization.TokenIdentifier
                    .ToNormalString ())) {
                accessToken = accessToken
                    .Remove (0, XAuthorization.TokenIdentifier.Length);
            }

            //
            return accessToken;
        }

        /// <summary>
        /// Retrieve Refresh Token
        /// </summary>
        /// <returns></returns>
        public static async Task<string> GetRefreshToken (this HttpContext context) {
            //
            var refreshToken = context.Request.Headers[XAuthorization.RefreshToken]
                .ToString ();
            if (refreshToken.IsNullOrEmpty ()) {
                refreshToken = await context
                    .GetTokenAsync (XAuthorization.RefreshToken);
            }

            //
            return refreshToken;
        }

        /// <summary>
        /// Retrieve Access Token Expiration Date
        /// </summary>
        /// <returns></returns>
        public static async Task<long> GetTokenExpiresAt (this HttpContext context) {
            //
            var expiresAtStr = context.Request.Headers[XAuthorization.ExpiresAt]
                .ToString ();
            if (expiresAtStr.IsNullOrEmpty ()) {
                expiresAtStr = await context
                    .GetTokenAsync (XAuthorization.ExpiresAt);
            }

            //
            var expiresAt = expiresAtStr.ConvertTo<long> ();

            //
            return expiresAt;
        }

        /// <summary>
        /// Retrieve All Required Tokens
        /// </summary>
        /// <returns></returns>
        public static async Task<XTokenResponse> RetrieveTokensAsXTokenResponse (HttpContext context) {
            //
            var accessToken = await GetAccessToken (context);
            var refreshToken = await GetRefreshToken (context);
            var expiresAt = await GetTokenExpiresAt (context);

            //
            return new XTokenResponse {
                AccessToken = accessToken,
                    RefreshToken = refreshToken,
                    ExpiresAt = expiresAt
            };
        }
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xIdentityService\Extensions\StreamExtensions.cs

using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Threading;
using xCommons.Extensions;

namespace xIdentityService.Extensions
{
    public static partial class StreamExtensions
    {
        /// <summary>
        /// Converts an Stream to Async Enumerable ...
        /// </summary>
        /// <param name="stream"></param>
        /// <param name="bufferSize"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public static async IAsyncEnumerable<byte[]> ToAsyncEnumerable(
            this Stream stream,
            int bufferSize = 8192,
            [System.Runtime.CompilerServices.EnumeratorCancellation]
            CancellationToken cancellationToken = default
        )
        {
            //
            var buffer = new byte[bufferSize];
            while (true)
            {
                //
                int read = await stream
                    .ReadAsync(
                        buffer,
                        0,
                        buffer.Length,
                        cancellationToken
                );

                //
                if (read == 0)
                {
                    yield break;
                }

                //
                yield return buffer.Take(read).ToArray();
            }
        }

        /// <summary>
        /// Converts an Stream to Async Enumerable ...
        /// </summary>
        /// <param name="stream"></param>
        /// <param name="bufferSize"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public static async IAsyncEnumerable<T> ToAsyncEnumerable<T>(
            this Stream stream,
            int bufferSize = 8192,
            [System.Runtime.CompilerServices.EnumeratorCancellation]
            CancellationToken cancellationToken = default
        )
        {
            //
            var buffer = new byte[bufferSize];
            while (true)
            {
                //
                int read = await stream
                    .ReadAsync(
                        buffer,
                        0,
                        buffer.Length,
                        cancellationToken
                );
                if (read == 0)
                {
                    yield break;
                }

                //
                T chunk = default(T);
                var readedBuffer = buffer.Take(read).ToArray();
                var str = readedBuffer.FromBytes();
                if (str.IsNullOrEmpty())
                {
                    yield return chunk;
                }
                try
                {
                    chunk = str.FromJSON<T>();
                }
                catch
                { }

                //
                yield return chunk;
            }
        }
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xIdentityService\Extensions\XModelExtensions.cs

using xIdentityModels.Dtos;
using xModels.Dtos;

namespace xIdentityService.Extensions
{
    public static class XModelExtensions
    {
        public static XPersonDto ToXPersonDto(this XOpenActionUserInfoDto source)
        {
            //
            var result = new XPersonDto
            {
                Avatar = source.Avatar,
                Lastname = source.Lastname,
                Username = source.Username,
                Firstname = source.Firstname,
            };

            //
            return result;
        }
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xIdentityService\Extensions\XTokenExtensions.cs

using System;
using System.Collections.Generic;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Threading.Tasks;
using IdentityModel.Client;
using Microsoft.AspNetCore.Authentication;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc.Filters;
using xCommons.Constants;
using xCommons.Extensions;
using xExceptions.Constants;
using xExceptions.Models;
using xIdentityModels.Models;
using xIdentityService.Interfaces;

public static partial class XTokenExtensions {
    /// <summary>
    /// Retrieve Tokens From Headers
    /// </summary>
    /// <param name="source"></param>
    /// <returns></returns>
    public static XLoginResponse RetrieveTokens (this HttpRequest source) {
        //
        var accessToken = source.Headers[XAuthorization.Header].ToString ();
        var refreshToken = source.Headers[XAuthorization.RefreshToken].ToString ();

        //
        var expiresAtStr = source.Headers[XAuthorization.ExpiresAt].ToString ();
        long expiresAt = expiresAtStr.ConvertTo<long> ();

        //
        if (accessToken
            .ToNormalString ()
            .Contains (XAuthorization.TokenIdentifier.ToNormalString ())) {
            accessToken = accessToken.Remove (0, XAuthorization.TokenIdentifier.Length);
        }

        //
        return new XLoginResponse {
            AccessToken = accessToken,
                RefreshToken = refreshToken,
                ExpiresAt = expiresAt
        };
    }

    /// <summary>
    /// Retrieve Tokens From HttpContext
    /// </summary>
    /// <param name="source"></param>
    /// <returns></returns>
    public static async Task<XLoginResponse> RetrieveTokens (this HttpContext source) {
        //
        var accessToken = await source.GetTokenAsync (XAuthorization.AccessToken);
        if (accessToken
            .ToNormalString ()
            .Contains (XAuthorization.TokenIdentifier.ToNormalString ())) {
            accessToken = accessToken.Remove (0, XAuthorization.TokenIdentifier.Length);
        }

        var refreshToken = await source.GetTokenAsync (XAuthorization.RefreshToken);
        var expiresAtStr = await source.GetTokenAsync (XAuthorization.ExpiresAt);
        long expiresAt = expiresAtStr.ConvertTo<long> ();

        //
        var headerRequestTokens = source.Request.RetrieveTokens ();

        //
        var result = new XLoginResponse {
            AccessToken = accessToken ?? headerRequestTokens.AccessToken,
            RefreshToken = refreshToken ?? headerRequestTokens.RefreshToken,
            ExpiresAt = expiresAt != 0 ? expiresAt : headerRequestTokens.ExpiresAt
        };

        //
        return result;
    }

    /// <summary>
    /// Retrieve Tokens From ActionExecutingContext
    /// </summary>
    /// <param name="source"></param>
    /// <returns></returns>
    public static async Task<XLoginResponse> RetrieveTokens (this ActionExecutingContext source) {
        //
        var result = await source.HttpContext.RetrieveTokens ();
        return result;
    }

    /// <summary>
    /// Retrieve Tokens From XUserInfo instance
    /// </summary>
    /// <param name="source"></param>
    /// <returns></returns>
    public static XTokenResponse RetrieveTokens (this XUserClaimsInfoDto source) {
        //
        var result = new XLoginResponse {
            AccessToken = source.AccessToken,
            RefreshToken = source.RefreshToken,
            ExpiresAt = source.ExpiresAt
        };

        //
        return result;
    }

    /// <summary>
    /// Retrieve Tokens From IHeader Dictionary 
    /// </summary>
    /// <param name="source"></param>
    /// <returns></returns>
    public static XLoginResponse RetrieveTokens (this IHeaderDictionary source) {
        //
        var accessToken = source[XAuthorization.Header].ToString () ?? "";
        if (accessToken
            .ToNormalString ()
            .Contains (XAuthorization.TokenIdentifier.ToNormalString ())) {
            accessToken = accessToken.Remove (0, XAuthorization.TokenIdentifier.Length);
        }

        //
        var refreshToken = source[XAuthorization.RefreshToken].ToString () ?? "";

        //
        var expiresAtStr = source[XAuthorization.ExpiresAt].ToString () ?? "";
        var expiresAt = expiresAtStr.ConvertTo<long> ();

        //
        var result = new XLoginResponse {
            AccessToken = accessToken,
            RefreshToken = refreshToken,
            ExpiresAt = expiresAt
        };

        //
        return result;
    }

    /// <summary>
    /// Retrieve IXIdentityProvider from HttpContext
    /// </summary>
    /// <param name="source"></param>
    /// <returns></returns>
    public static IXIdentityProvider GetXApiIdentityProvider (this FilterContext source) {
        //
        var services = source.HttpContext.RequestServices;
        return (IXIdentityProvider) services
            .GetService (typeof (IXIdentityProvider));
    }

    /// <summary>
    /// Generate XLoginResponse instance based on TokenResponse
    /// </summary>
    /// <param name="source"></param>
    /// <returns></returns>
    public static XLoginResponse CreateXLoginResponse (this TokenResponse source) {
        //
        if (source.IsNull () ||
            source.IsError) {
            XException.InvalidToken.Throw ();
        }

        //
        var expiresAt = new DateTimeOffset (DateTime.UtcNow)
            .ToUnixTimeSeconds () +
            source.ExpiresIn;

        //
        var result = new XLoginResponse {
            AccessToken = source.AccessToken,
            RefreshToken = source.RefreshToken,
            ExpiresAt = expiresAt
        };

        //
        return result;
    }

    /// <summary>
    /// Add Authorization Tokens in Headers of
    /// Specific IHeaderDictionary instance
    /// </summary>
    /// <param name="source"></param>
    /// <param name="model"></param>
    public static void SetXAuthenticationTokens (this IHeaderDictionary source, XLoginResponse model, string secret = null) {
        //
        source.Remove (XAuthorization.Header);
        source.Remove (XAuthorization.RefreshToken);
        source.Remove (XAuthorization.ExpiresAt);
        source.Remove (XAuthorization.RevisionChecksum);

        //
        source.Add (XAuthorization.Header, $"{XAuthorization.TokenIdentifier}{model.AccessToken}");
        source.Add (XAuthorization.RefreshToken, $"{model.RefreshToken}");
        source.Add (XAuthorization.ExpiresAt, $"{model.ExpiresAt}");

        //
        if (!secret.IsNullOrEmpty ()) {
            var revisionChecksum = model.GetRevisionChecksum (secret);
            source.Add (XAuthorization.RevisionChecksum, revisionChecksum);
        }
    }

    /// <summary>
    /// Add Authorization Tokens in Headers of
    /// Specific IHeaderDictionary instance
    /// </summary>
    /// <param name="source"></param>
    /// <param name="model"></param>
    public static void SetXAuthenticationTokens (this HttpRequestHeaders source, XLoginResponse model) {
        //
        source.Remove (XAuthorization.Header);
        source.Remove (XAuthorization.RefreshToken);
        source.Remove (XAuthorization.ExpiresAt);
        source.Remove (XAuthorization.RevisionChecksum);

        //
        source.Add (XAuthorization.Header, $"{XAuthorization.TokenIdentifier}{model.AccessToken}");
        source.Add (XAuthorization.RefreshToken, $"{model.RefreshToken}");
        source.Add (XAuthorization.ExpiresAt, $"{model.ExpiresAt}");
    }

    /// <summary>
    /// Add Authorization Tokens in Headers of
    /// Specific HttpRequest instance
    /// </summary>
    /// <param name="source"></param>
    /// <param name="model"></param>
    public static void SetXAuthenticationTokens (this HttpRequest source, XLoginResponse model) {
        source.Headers.SetXAuthenticationTokens (model);
    }

    /// <summary>
    /// Add Authorization Tokens in Headers of
    /// Specific HttpRequest instance
    /// </summary>
    /// <param name="source"></param>
    /// <param name="model"></param>
    public static void SetXAuthenticationTokens (this HttpRequestMessage source, XLoginResponse model) {
        source.Headers.SetXAuthenticationTokens (model);
    }

    /// <summary>
    /// Add ReNewed Authorization Tokens in Headers of 
    /// Specific Response.
    /// Later in HttpInterceptors we can Look for AccessToken-ReNewed
    /// header Value and Renew User Tokens based on it
    /// </summary>
    /// <param name="source"></param>
    /// <param name="model"></param>
    public static void SetXAuthenticationTokens (this HttpResponse source, XLoginResponse model, string secret) {
        source.Headers.SetXAuthenticationTokens (model, secret);
    }

    /// <summary>
    /// Determines a Token Can Refrsh or not
    /// </summary>
    /// <param name="source"></param>
    /// <returns></returns>
    public static bool IsRefreshable (this XLoginResponse source) {
        //
        var containsTokenData = !source.IsNull () &&
            !source.AccessToken.IsNullOrEmpty () &&
            !source.RefreshToken.IsNullOrEmpty ();
        if (!containsTokenData) {
            return false;
        }

        //
        var current = new DateTimeOffset (DateTime.UtcNow)
            .ToUnixTimeSeconds ();

        //
        // var result = current > source.ExpiresAt || current > source.ExpiresAt - XAuthorization.ThresholdBeforeTokenExpiration;
        var result = current > source.ExpiresAt - XAuthorization.ThresholdBeforeTokenExpiration;

        //
        return result;
    }

    /// <summary>
    /// Generate a Revision Checksum for new Tokens
    /// </summary>
    /// <param name="source"></param>
    /// <param name="secret"></param>
    /// <returns></returns>
    public static string GetRevisionChecksum (this XLoginResponse source, string secret) {
        return (source.AccessToken +
                secret +
                source.RefreshToken +
                secret +
                source.ExpiresAt.ToString ()
            )
            .ToMd5String ();
    }

    /// <summary>
    /// Generate a Revision Checksum for new Tokens
    /// </summary>
    /// <param name="source"></param>
    /// <param name="secret"></param>
    /// <returns></returns>
    public static string GetRevisionChecksum (this XTokenResponse source, string secret) {
        return (source.AccessToken +
                secret +
                source.RefreshToken +
                secret +
                source.ExpiresAt.ToString ()
            )
            .ToMd5String ();
    }

    /// <summary>
    /// Check an XLoginResponse instance is Valid with it's revision
    /// </summary>
    /// <param name="source"></param>
    /// <param name="checksum"></param>
    /// <param name="secret"></param>
    /// <returns></returns>
    public static bool ValidateRevisionChecksum (this XLoginResponse source, string checksum, string secret) {
        //
        var xChecksum = source.GetRevisionChecksum (secret);
        return checksum == xChecksum;
    }

    /// <summary>
    /// Check an XTokenResponse instance is Valid with it's revision
    /// </summary>
    /// <param name="source"></param>
    /// <param name="checksum"></param>
    /// <param name="secret"></param>
    /// <returns></returns>
    public static bool ValidateRevisionChecksum (this XTokenResponse source, string checksum, string secret) {
        //
        var xChecksum = source.GetRevisionChecksum (secret);
        return checksum == xChecksum;
    }

    /// <summary>
    /// Retrieve Exception Details if Fails
    /// </summary>
    /// <param name="source"></param>
    /// <returns></returns>
    public static Exception GetException (this TokenResponse source) {
        //
        // Validate Args ...
        if (source.IsNull () || !source.IsError) {
            return XException.ActionFailed.ToException ();
        }

        //
        XError error = source.ErrorDescription.FromJSON<XError> ();
        return error.ToException ();
    }

    /// <summary>
    /// Convert XTokenResponse to Header Dictionary
    /// </summary>
    /// <param name="source"></param>
    /// <returns></returns>
    public static IDictionary<string, string> ToHeaderDictionary (this XTokenResponse source) {
        //
        var result = new Dictionary<string, string> { { XAuthorization.RefreshToken, source.RefreshToken },
                { XAuthorization.ExpiresAt, source.ExpiresAt.ToString () }
            };

        //
        return result;
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xIdentityService\Extensions\XUserClaimsInfoDtoExtensions.cs

using xCommons.Extensions;
using xIdentityModels.Constants;
using xIdentityModels.Models;

namespace xIdentityService.Extensions {
    public static class XUserClaimsInfoDtoExtensions {
        public static string GetUserSelectByParam (
            this XUserClaimsInfoDto source,
            XUserSelectBy userSelectBy = XUserSelectBy.Username
        ) {
            //
            var result = "";

            //
            switch (userSelectBy) {
                //
                case XUserSelectBy.ID:
                    result = source.UserId;
                    break;

                    //
                case XUserSelectBy.Username:
                    result = source.UserName;
                    break;

                    //
                case XUserSelectBy.Email:
                    result = source.Email;
                    break;

                    //
                case XUserSelectBy.MobileNumber:
                    result = source.PhoneNumber;
                    break;
            }

            //
            if (result.IsNullOrEmpty ()) {
                //
                if (!source.UserId.IsNullOrEmpty ()) {
                    result = source.UserId;
                } else if (!source.UserName.IsNullOrEmpty ()) {
                    result = source.UserName;
                } else if (!source.Email.IsNullOrEmpty ()) {
                    result = source.Email;
                } else if (!source.PhoneNumber.IsNullOrEmpty ()) {
                    result = source.PhoneNumber;
                }
            }

            //
            return result;
        }
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xIdentityService\Interfaces\IXBaseIdentityHttpProvider.cs

using System;
using System.IO;
using System.Collections.Generic;
using System.Net.Http;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.Extensions.Logging;
using RestSharp;
using xCommons.Providers;
using xHttpService.Constants;
using xIdentityModels.Constants;
using xIdentityModels.Models;
using xIdentityService.Models;

namespace xIdentityService.Interfaces
{
    /// <summary>
    /// an interface for Identity Provided Http Based Services ...
    /// </summary>
    public interface IXBaseIdentityHttpProvider
    {
        /// <summary>
        /// Client Base Url ...
        /// </summary>
        /// <value></value>
        string BaseUrl { get; }

        /// <summary>
        /// Logger ...
        /// </summary>
        /// <value></value>
        ILogger Logger { get; }

        /// <summary>
        /// Powered Value ...
        /// </summary>
        /// <value></value>
        string XPoweredValue { get; }

        /// <summary>
        /// Default Client Timeout ...
        /// </summary>
        /// <value></value>
        int DefaultClientTimeout { get; }

        /// <summary>
        /// Default Buffering Chunk Size ...
        /// </summary>
        /// <value></value>
        int DefaultBufferingChunckSize { get; }

        /// <summary>
        /// Validation Provider ...
        /// </summary>
        /// <value></value>
        XValidationProvider ValidationProvider { get; }

        /// <summary>
        /// Get an Instance of Http Client 
        /// </summary>
        /// <returns></returns>
        HttpClient GetHttpClient(XTokenResponse tokens = null);
        HttpClient GetHttpClient(XUserClaimsInfoDto userInfo = null);

        /// <summary>
        /// Get an Instance of RestClient
        /// </summary>
        /// <returns></returns>
        RestClient GetRestClient(XTokenResponse tokens = null);
        RestClient GetRestClient(XUserClaimsInfoDto userInfo = null);

        /// <summary>
        /// Get an Instance of RestRequest 
        /// </summary>
        /// <param name="endpoint"></param>
        /// <param name="addXPoweredValue"></param>
        /// <param name=""></param>
        /// <param name="headers"></param>
        /// <param name="queryStrings"></param>
        /// <returns></returns>
        RestRequest GetRestRequet(
            Enum endpoint,
            bool addXPoweredValue = true,
            IDictionary<string, string> @params = null,
            IDictionary<string, string> headers = null,
            IDictionary<string, string> queryStrings = null
        );

        /// <summary>
        /// Handle Call Specific Request and retrieve Response
        /// </summary>
        /// <param name="client"></param>
        /// <param name="request"></param>
        /// <param name="method"></param>
        /// <param name="supportRefreshingTokens"></param>
        /// <param name="cancellationToken"></param>
        /// <typeparam name="T"></typeparam>
        /// <returns></returns>
        Task<T> RunRestRequest<T>(
            RestClient client,
            RestRequest request,
            XHttpMethod method,
            bool supportRefreshingTokens = true,
            CancellationToken cancellationToken = default
        );

        /// <summary>
        /// Access a Get Request Stream as AsyncEnumerable ... 
        /// </summary>
        /// <param name="endpoint"></param>
        /// <param name="bufferLength"></param>
        /// <param name="addXPoweredValue"></param>
        /// <param name="tokens"></param>
        /// <param name="@params"></param>
        /// <param name="headers"></param>
        /// <param name="queryStrings"></param>
        /// <param name="cancellationToken"></param>
        /// <typeparam name="T"></typeparam>
        /// <returns></returns>
        Task<Stream> StreamData(
            Enum endpoint,
            int bufferLength = 8194,
            bool addXPoweredValue = true,
            XTokenResponse tokens = null,
            IDictionary<string, string> @params = null,
            IDictionary<string, string> headers = null,
            IDictionary<string, string> queryStrings = null,
            CancellationToken cancellationToken = default
        );

        /// <summary>
        /// Handle Call Specified Request and Retrieve XBaseRestResponse<T> ...
        /// </summary>
        /// <param name="client"></param>
        /// <param name="request"></param>
        /// <param name="method"></param>
        /// <param name="supportRefreshingTokens"></param>
        /// <param name="cancellationToken"></param>
        /// <typeparam name="T"></typeparam>
        /// <returns>an instance of XBaseRestResponse<T></returns>
        Task<XBaseRestResponse<T>> RunRestRequestByResponse<T>(
            RestClient client,
            RestRequest request,
            XHttpMethod method,
            bool supportRefreshingTokens = true,
            CancellationToken cancellationToken = default
        );

        /// <summary>
        /// Get User SelectBy Param 
        /// </summary>
        /// <param name="model"></param>
        /// <param name="forceNotNull"></param>
        /// <param name="excludes"></param>
        /// <returns></returns>
        string GetUserSelectByParam(
            XActionRequest model,
            bool forceNotNull = true,
            ICollection<XUserSelectBy> excludes = null
        );

        /// <summary>
        /// Converts UserInfo to TokenResponse model ...
        /// </summary>
        /// <param name="userInfo"></param>
        /// <returns></returns>
        XTokenResponse ToTokenResponse(XUserClaimsInfoDto userInfo = null);

        /// <summary>
        /// Prepare Url Address of Specified Enum by Filling Params
        /// and Query Strings Attach ...
        /// </summary>
        /// <param name="endpoint"></param>
        /// <param name="attachBaseUrl"></param>
        /// <param name="@params"></param>
        /// <param name="queryStrings"></param>
        /// <returns></returns>
        string PrepareUrl(
            Enum endpoint,
            bool attachBaseUrl = false,
            IDictionary<string, string> @params = null,
            IDictionary<string, string> queryStrings = null
        );

        /// <summary>
        /// Prepare Url Address by Filling Params
        /// and Query Strings Attach ...
        /// </summary>
        /// <param name="url"></param>
        /// <param name="attachBaseUrl"></param>
        /// <param name="@params"></param>
        /// <param name="queryStrings"></param>
        /// <returns></returns>
        string PrepareUrl(
            string url,
            bool attachBaseUrl = false,
            IDictionary<string, string> @params = null,
            IDictionary<string, string> queryStrings = null
        );
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xIdentityService\Interfaces\IXBaseReferenced.cs

using System;
using System.Collections;
using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;
using xDataService.Models;
using xIdentityModels.Models;
using xModels.Base;

namespace xIdentityService.Interfaces
{
    /// <summary>
    /// a Referenced Service is a Service which can Referenced to other Items ...
    /// </summary>
    public interface IXBaseReferenced<TEntity, TKey>
    where TEntity : XBaseEntity<TKey>
    {
        /// <summary>
        /// Get Reference Identifier for Specified Provider and Specified Item ...
        /// </summary>
        /// <param name="providedFor"></param>
        /// <param name="forProvidedId"></param>
        /// <returns></returns>
        string GetIdentifier<TReferenceKey>(
            string providedFor,
            TReferenceKey forProvidedId
        );

        /// <summary>
        /// Check Specified Item has Refernce to Provider ...
        /// </summary>
        /// <param name="providedFor"></param>
        /// <param name="forProvidedId"></param>
        /// <param name="id"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        Task<bool> IsProvidedFor<TReferenceKey>(
            string providedFor,
            TReferenceKey forProvidedId,
            TKey id,
            CancellationToken cancellationToken = default
        );

        /// <summary>
        /// Add Specified Reference to Specified Item ...
        /// </summary>
        /// <param name="providedFor"></param>
        /// <param name="forProvidedId"></param>
        /// <param name="id"></param>
        /// <param name="forIndex"></param>
        /// <param name="userInfo"></param>
        /// <param name="connectionId"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        Task AddReference<TReferenceKey>(
            string providedFor,
            TReferenceKey forProvidedId,
            TKey id,
            int forIndex = 0,
            XUserClaimsInfoDto userInfo = null,
            string connectionId = null,
            CancellationToken cancellationToken = default
        );

        /// <summary>
        /// Remove Specified Reference from Specified Item ...
        /// </summary>
        /// <param name="providedFor"></param>
        /// <param name="forProvidedId"></param>
        /// <param name="id"></param>
        /// <param name="forIndex"></param>
        /// <param name="userInfo"></param>
        /// <param name="connectionId"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        Task RemoveReference<TReferenceKey>(
            string providedFor,
            TReferenceKey forProvidedId,
            TKey id,
            int forIndex = 0,
            XUserClaimsInfoDto userInfo = null,
            string connectionId = null,
            CancellationToken cancellationToken = default
        );

        /// <summary>
        /// Get Specified References ...
        /// </summary>
        /// <param name="providedFor"></param>
        /// <param name="id"></param>
        /// <param name="cancellationToken"></param>
        /// <typeparam name="TReferenceKey"></typeparam>
        /// <returns></returns>
        Task<IEnumerable<XReference<string>>> GetReferences(
            string providedFor,
            TKey id,
            CancellationToken cancellationToken = default
        );
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xIdentityService\Interfaces\IXBaseReferencedController.cs

using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
using xDataService.Models;
using xModels.Base;

namespace xIdentityService.Interfaces
{
    public interface IXBaseReferencedController<TEntity, TKey>
    where TEntity : XBaseEntity<TKey>
    {
        /// <summary>
        /// Check an Item Has Reference to Specified ProvideFor and Specified forProvidedId ...
        /// </summary>
        /// <param name="id"></param>
        /// <param name="providedFor"></param>
        /// <param name="forProvidedId"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        [HttpGet("{id}/Reference/IsProvidedFor")]
        Task<ActionResult<bool>> IsProvidedFor(
            [FromRoute] TKey id,
            [FromQuery] string providedFor,
            [FromQuery] object forProvidedId,
            CancellationToken cancellationToken = default
        );

        /// <summary>
        /// Add a Reference to Item for Specified ProvideFor and Specified forProvidedId ...
        /// </summary>
        /// <param name="id"></param>
        /// <param name="providedFor"></param>
        /// <param name="forProvidedId"></param>
        /// <param name="forIndex"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        [HttpPost("{id}/Reference")]
        Task<ActionResult> AddReference(
            [FromRoute] TKey id,
            [FromQuery] string providedFor,
            [FromQuery] object forProvidedId,
            [FromQuery] int forIndex = 0,
            CancellationToken cancellationToken = default
        );

        /// <summary>
        /// Remove a Reference from Item for Specified ProvideFor and Specified forProvidedId ...
        /// </summary>
        /// <param name="id"></param>
        /// <param name="providedFor"></param>
        /// <param name="forProvidedId"></param>
        /// <param name="forIndex"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        [HttpDelete("{id}/Reference")]
        Task<ActionResult> RemoveReference(
            [FromRoute] TKey id,
            [FromQuery] string providedFor,
            [FromQuery] object forProvidedId,
            [FromQuery] int forIndex = 0,
            CancellationToken cancellationToken = default
        );

        /// <summary>
        /// Retrieve References of Specified Itemfor providedFor ...
        /// </summary>
        /// <param name="id"></param>
        /// <param name="providedFor"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        [HttpGet("{id}/References")]
        Task<ActionResult<IEnumerable<XReference<string>>>> GetReferences(
            [FromRoute] TKey id,
            [FromQuery] string providedFor,
            CancellationToken cancellationToken = default
        );
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xIdentityService\Interfaces\IXIdentityBaseReferencedProvider.cs

using System.Collections.Generic;
using System.Threading.Tasks;
using xDataService.Models;
using xIdentityModels.Models;
using xModels.Dtos;

namespace xIdentityService.Interfaces
{
    /// <summary>
    /// in Some Cases we have Entities Which Can Referenced for Specified 
    /// Provider and Types ...
    /// this interface Globaly introduce all available Actions for those ...
    /// 
    /// TKey: type of Provider Models Keys ...
    /// TModel: type of Dto which Referenced ...
    /// </summary>
    public interface IXIdentityBaseReferencedProvider<TModel, TKey>
    {
        //
        #region Props ...
        /// <summary>
        /// Provider Identifier ...
        /// </summary>
        string Provider { get; }
        #endregion

        //
        #region Referenced Actions ...
        /// <summary>
        /// Get Specified Indexed Reference for Specific Provided ID ...
        /// </summary>
        /// <param name="providedForId"></param>
        /// <param name="forIndex"></param>
        /// <returns></returns>
        Task<TModel> GetReference(
            TKey providedForId,
            int forIndex = 0
        );

        /// <summary>
        /// Retrieve all Exists References of Specific Provided ID ...
        /// </summary>
        /// <param name="providedForId"></param>
        /// <returns></returns>
        Task<IEnumerable<TModel>> GetAllReferences(TKey providedForId);

        /// <summary>
        /// Extract all Referencing Models for Specified Key ...
        /// </summary>
        /// <param name="providedForId"></param>
        /// <returns></returns> 
        Task<IEnumerable<XReference<TKey>>> GetAllReferencings(TKey providedForId);

        /// <summary>
        /// Count References ...
        /// </summary>
        /// <param name="providedForId"></param>
        /// <returns></returns>
        Task<int> CountReferences(TKey providedForId);

        /// <summary>
        /// Retrieve References of Specific Provided ID as Query ...
        /// </summary>
        /// <param name="providedForId"></param>
        /// <returns></returns>
        Task<XQueryResult<TModel>> QueryReferences(
            XQuery query,
            TKey providedForId
        );

        /// <summary>
        /// Add Reference a Model to Specific Provided ID ...
        /// </summary>
        /// <param name="model"></param>
        /// <param name="providedForId"></param>
        /// <param name="connectionId"></param>
        /// <param name="userInfo"></param>
        /// <returns></returns>
        Task<bool> AddReference(
            TModel model,
            TKey providedForId,
            string connectionId = null,
            XUserClaimsInfoDto userInfo = null
        );

        /// <summary>
        /// Add Reference a Model to Specific XRefence<TKey> ...
        /// </summary>
        /// <param name="model"></param>
        /// <param name="reference"></param>
        /// <param name="connectionId"></param>
        /// <param name="userInfo"></param>
        /// <returns></returns>
        Task<bool> AddReference(
            TModel model,
            XReference<TKey> reference,
            string connectionId = null,
            XUserClaimsInfoDto userInfo = null
        );

        /// <summary>
        /// Remove Reference a Model for Specific Provided ID ...
        /// </summary>
        /// <param name="model"></param>
        /// <param name="providedForId"></param>
        /// <param name="connectionId"></param>
        /// <param name="userInfo"></param>
        /// <returns></returns>
        Task<bool> RemoveReference(
            TModel model,
            TKey providedForId,
            string connectionId = null,
            XUserClaimsInfoDto userInfo = null
        );

        /// <summary>
        /// Remove Reference a Model for Specific XRefence<TKey> ...
        /// </summary>
        /// <param name="model"></param>
        /// <param name="providedForId"></param>
        /// <param name="connectionId"></param>
        /// <param name="userInfo"></param>
        /// <returns></returns>
        Task<bool> RemoveReference(
            TModel model,
            XReference<TKey> reference,
            string connectionId = null,
            XUserClaimsInfoDto userInfo = null
        );

        /// <summary>
        /// Remove All References to Specified Key ...
        /// </summary>
        /// <param name="providedForId"></param>
        /// <param name="connectionId"></param>
        /// <param name="userInfo"></param>
        /// <returns></returns>
        Task<bool> RemoveReferences(
            TKey providedForId,
            string connectionId = null,
            XUserClaimsInfoDto userInfo = null
        );
        #endregion
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xIdentityService\Interfaces\IXIdentityProvider.cs

using System.Collections.Generic;
using System.Threading.Tasks;
using IdentityModel.Client;
using Microsoft.AspNetCore.Http;
using RestSharp;
using xHttpService.Constants;
using xIdentityModels.Constants;
using xIdentityModels.Dtos;
using xIdentityModels.Models;
using xIdentityModels.Navigations;
using xModels.Dtos;

namespace xIdentityService.Interfaces
{
    public partial interface IXIdentityProvider
    {
        //
        string BaseUrl { get; }
        string RevisionSecretKey { get; }
        IXSecurityProvider SecurityProvider { get; }

        //
        #region Tools ...
        string GetUserSelectByParam(
            XActionRequest model,
            bool forceNotNull = true,
            ICollection<XUserSelectBy> excludes = null
        );
        #endregion

        //
        #region Tools ...
        Task<T> RunRestRequest<T>(
            RestClient client,
            RestRequest request,
            XHttpMethod method,
            bool supportRefreshingTokens = false
        );
        #endregion

        //
        #region Authentication ...
        Task<DiscoveryDocumentResponse> RequestDiscoveryDocument();
        Task<XTokenResponse> RequestScopeAccessToken(string scope);
        Task<TokenIntrospectionResponse> Introspection(XTokenResponse model);
        Task<XLoginResponse> Login(XLoginRequest model);
        Task Logout(XTokenResponse model);
        Task<XTokenResponse> Authenticate(XLoginRequest model);
        Task<XTokenResponse> RefreshTokens(XTokenResponse model);

        Task ChangePassword(
            XTokenResponse tokens,
            XActionRequest model
        );
        #endregion

        //
        #region Profile ...
        Task<IEnumerable<string>> GetUserNames(
            XTokenResponse tokens,
            string userIds
        );

        Task<IEnumerable<XUserNameIdResponse>> GetUserNameIds(
            XTokenResponse tokens,
            XUserNameIdRequest model
        );

        Task<XUserProfileDto> GetUserProfile(
            XTokenResponse tokens,
            string userSelectByParam
        );

        Task<XQueryResult<XUserProfileDto>> QueryUsers(
            XTokenResponse tokens,
            XQuery query
        );

        Task<XQueryResult<XUserProfileDto>> QueryInRoleUsers(
            XTokenResponse tokens,
            string role,
            XQuery query,
            bool forceRole = false
        );

        Task<XQueryResult<XProfileImage>> QueryAvatars(
            XTokenResponse tokens,
            string userSelectByParam,
            XQuery query
        );

        Task<XUserProfileDto> ProfileUpdateAsync(
            XTokenResponse tokens,
            string userSelectByParam,
            XProfileUpdateRequest model
        );

        Task<XUserProfileDto> FullProfileUpdateAsync(
            XTokenResponse tokens,
            string userSelectByParam,
            XProfileUpdateRequest request
        );

        Task<XUserProfileDto> AddAvatar(
            XTokenResponse tokens,
            IFormFile file
        );

        Task<XUserProfileDto> AddAvatars(
            XTokenResponse tokens,
            IFormFileCollection files
        );

        Task<XUserProfileDto> SetAvatar(
            XTokenResponse tokens,
            int avatarId
        );

        Task<XUserProfileDto> RemoveAvatars(
            XTokenResponse tokens,
            string avatarIds
        );
        #endregion

        //
        #region Search ...
        /// <summary>
        /// Query Open To Search User Profiles ...
        /// </summary>
        /// <param name="tokens">requested user's identifiers</param>
        /// <param name="query">how to filter results based on <see>XQuery</see> structure</param>
        /// <returns>an instance of <see>XQueryResult</see> of <see>XUserProfileDto</see></returns>
        Task<XQueryResult<XUserProfileDto>> QueryOpenToSearchUsers(
            XTokenResponse tokens,
            XQuery query
        );
        #endregion

        //
        #region Registration ...
        Task<bool> CanRegister(string userSelectByParam);

        Task<XActionResponse> InviteUser(
            XTokenResponse tokens,
            XActionRequest model
        );

        Task<XActionResponse> RequestRegistration(
            XActionRequest model
        );

        Task<XActionResponse> AddAccountInfo(
            XActionRequest model
        );

        Task<XActionResponse> AttachProfileImage(
            string actionToken,
            IFormFile file
        );

        Task FinishRegistration(XActionRequest model);

        Task<bool> IsConfirmedEmail(
            XTokenResponse tokens,
            string userSelectByParam
        );

        Task<bool> IsConfirmedMobile(
            XTokenResponse tokens,
            string userSelectByParam
        );

        Task RequestConfirmRegistration(XActionRequest model);

        Task ConfirmRegistration(
            XActionRequest model
        );

        Task<XActionResponse> RequestConfirmMobile(XActionRequest model);

        Task<XActionResponse> ConfirmMobileNumber(XActionRequest model);

        Task<XActionResponse> RequestConfirmEmail(XActionRequest model);

        Task<XActionResponse> ConfirmEmailAddress(XActionRequest model);

        Task<XActionResponse> RequestResetPassword(XActionRequest model);

        Task ResetPassword(XActionRequest model);
        #endregion

        //
        #region Friendship ...
        Task<XFriendshipFollowing> Follow(
            XTokenResponse tokens,
            string destUser
        );

        Task<bool> Cancel(
            XTokenResponse tokens,
            string destUser
        );

        Task UnFollowFollower(
            XTokenResponse tokens,
            string destUser
        );

        Task UnFollowFollowing(
            XTokenResponse tokens,
            string destUser
        );

        Task<XFriendshipFollowing> Block(
            XTokenResponse tokens,
            string destUser
        );

        Task<XFriendshipFollowing> UnBlock(
            XTokenResponse tokens,
            string destUser
        );

        Task<XFriendshipFollower> AcceptRequest(
            XTokenResponse tokens,
            string destUser
        );

        Task<XFriendshipFollower> RejectRequest(
            XTokenResponse tokens,
            string destUser
        );

        Task<XFriendshipInfoDto> GetFriendshipInfo(
            XTokenResponse tokens,
            string destUser
        );

        Task<bool> IsFollower(
            XTokenResponse tokens,
            string destUser
        );

        Task<XFriendshipFollower> GetFollower(
            XTokenResponse tokens,
            string destUser
        );

        Task<XFriendshipState> GetFollowerState(
            XTokenResponse tokens,
            string destUser
        );

        Task<IEnumerable<XFriendshipFollower>> GetFollowers(XTokenResponse tokens);

        Task<IEnumerable<XFriendshipFollower>> GetAllFollowers(XTokenResponse tokens);

        Task<IEnumerable<string>> GetFollowingList(XTokenResponse tokens);

        Task<XQueryResult<XFriendDto>> QueryFollowers(
            XQuery query,
            string destUser,
            XTokenResponse tokens
        );

        Task<bool> IsFollowing(
            XTokenResponse tokens,
            string destUser
        );

        Task<XFriendshipFollowing> GetFollowing(
            XTokenResponse tokens,
            string destUser
        );

        Task<XFriendshipState> GetFollowingState(
            XTokenResponse tokens,
            string destUser
        );

        Task<IEnumerable<XFriendshipFollowing>> GetFollowings(XTokenResponse tokens);

        Task<IEnumerable<XFriendshipFollowing>> GetAllFollowings(XTokenResponse tokens);

        Task<IEnumerable<string>> GetFollowersList(XTokenResponse tokens);

        Task<XQueryResult<XFriendDto>> QueryFollowings(
            XQuery query,
            string destUser,
            XTokenResponse tokens
        );
        #endregion

        //
        #region Admin ...
        Task<IEnumerable<string>> Ban(
            XTokenResponse tokens,
            XUserNameIdRequest model
        );

        Task<IEnumerable<string>> UnBan(
            XTokenResponse tokens,
            XUserNameIdRequest model
        );

        Task<bool> IsBanned(
            XTokenResponse tokens,
            string userSelectByParam
        );
        #endregion

        //
        #region Open Actions ...
        //
        XDeviceDto GetDevice();
        
        //
        Task<XOpenActionInnerDto> OpenGet(
            XOpenActionInnerDto model
        );

        //
        Task<XOpenActionUserInfoDto> GetUserInfo(
            XDeviceDto device,
            string userSelectByParam
        );
        Task<XOpenActionUserInfoDto> GetUserInfo(
            XOpenActionInnerDto dto
        );
        Task<XOpenActionUserInfoDto> GetUserInfo(
            string token,
            string request
        );

        //
        Task<IEnumerable<XOpenActionUserInfoDto>> GetUserInfos(
            XDeviceDto device,
            string ids
        );
        Task<IEnumerable<XOpenActionUserInfoDto>> GetUserInfos(
            XOpenActionInnerDto dto
        );
        Task<IEnumerable<XOpenActionUserInfoDto>> GetUserInfos(
            string token,
            string request
        );
        #endregion
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xIdentityService\Interfaces\IXProxyHelper.cs

using System;
using System.Collections.Generic;
using System.Linq.Expressions;
using xIdentityService.Configuration;

namespace xIdentityService.Interfaces {
    public interface IXProxyHelper {
        /// <summary>
        /// Proxy Configuration ...
        /// </summary>
        /// <value></value>
        XProxyConfiguration Configuration { get; }
        
        /// <summary>
        /// retrie Normalize Host ...
        /// </summary>
        /// <returns></returns>
        string NormalizeHost ();

        /// <summary>
        /// Validate XProxy Configuration for Client ...
        /// </summary>
        /// <returns></returns>
        bool ValidateConfiguration ();

        /// <summary>
        /// Retrieve all Prepared url of Routes ...
        /// </summary>
        /// <returns></returns>
        IEnumerable<string> GetRouteUrls ();

        /// <summary>
        /// retrieve all registred Routes ...
        /// </summary>
        /// <returns></returns>
        IEnumerable<XProxyRouteDescriptor> GetRoutes ();

        /// <summary>
        /// Prepare a request url for a Proxy Route ...
        /// </summary>
        /// <param name="url"></param>
        /// <param name="descriptor"></param>
        /// <returns></returns>
        string PrepareActionUrlForXProxyRoute (
            string url,
            XProxyRouteDescriptor descriptor
        );

        /// <summary>
        /// Prepare a request url for a Selected Proxy Route ...
        /// </summary>
        /// <param name="url"></param>
        /// <param name="whereClause"></param>
        /// <returns></returns>
        string PrepareActionUrlForXProxyRoute (
            string url,
            Expression<Func<XProxyRouteDescriptor, bool>> whereClause
        );

        /// <summary>
        /// Find an Specific Route ...
        /// </summary>
        /// <param name="whereClause"></param>
        /// <returns></returns>
        XProxyRouteDescriptor FindRoute (Expression<Func<XProxyRouteDescriptor, bool>> whereClause);
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xIdentityService\Interfaces\IXSecurityProvider.cs

namespace xIdentityService.Interfaces
{
    public partial interface IXSecurityProvider
    {
        string Encrypt(string plainText);
        string Decrypt(string cipherText);
        string EncryptFromBytes(byte[] textBytes);
        string DecryptFromBytes(byte[] cipherBytes);
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xIdentityService\Interfaces\IXTokenProvider.cs

using System.Threading.Tasks;
using xIdentityModels.Models;

namespace xIdentityService.Interfaces {
    public partial interface IXTokenProvider {
        Task<bool> IsTokenExists (string accessToken);
        Task<bool> IsTokenExists (XTokenResponse tokens);
        Task<bool> RemoveToken (string accessToken);
        Task<bool> RemoveToken (XTokenResponse tokens);
        Task<XTokenResponse> RetrieveToken (string accessToken);
        Task<bool> AddToken (XTokenResponse tokens);
        Task<bool> UpdateToken (XTokenResponse tokens);
        Task<bool> AddOrUpdateToken (XTokenResponse tokens);
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xIdentityService\Middlewares\XIdentityTokenRefresher.cs

using System;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.Logging;
using xCommons.Constants;
using xCommons.Extensions;
using xIdentityModels.Extensions;
using xIdentityService.Interfaces;

namespace xIdentityService.Middlewares {
    public partial class XIdentityTokenRefresherMiddleware {
        //
        #region Properties ...
        private readonly ILogger logger;
        private readonly RequestDelegate next;
        private readonly IXTokenProvider tokenProvider;
        private readonly IXIdentityProvider identityProvider;
        #endregion

        //
        #region Constructor ...
        public XIdentityTokenRefresherMiddleware (
            RequestDelegate next,
            ILoggerFactory loggerFactory,
            IXTokenProvider tokenProvider,
            IXIdentityProvider identityProvider
        ) {
            //
            this.next = next;
            this.tokenProvider = tokenProvider;
            this.identityProvider = identityProvider;
            this.logger = loggerFactory
                .CreateLogger<XIdentityTokenRefresherMiddleware> ();
        }
        #endregion

        //
        #region Actions ...
        public async Task Invoke (HttpContext context) {
            //
            // Handle Request ...
            await HandleRequest (context);

            //
            // Do Main Task ...
            try {
                await next.Invoke (context);
            } catch (Exception ex) {
                logger.LogError ($"Error: {ex.Message}");
            }

            //
            // Handle Response ...
            await HandleResponse (context);
        }
        #endregion

        //
        #region Private ...
        private async Task HandleRequest (HttpContext context) {
            //
            // Log ...
            logger.LogInformation ($"Start Process Request ...");

            //
            // Check Access Token ...
            var hasAccessToken = HasAccessToken (context);
            if (!hasAccessToken) {
                return;
            }

            //
            // Check Access Token ...
            var accessToken = GetAccessToken (context);
            var isExists = await tokenProvider
                .IsTokenExists (accessToken);
            if (!isExists) {
                return;
            }

            //
            // Try Check is Refreshable ...
            var tokens = await tokenProvider
                .RetrieveToken (accessToken);
            if (tokens.IsNull ()) {
                return;
            }

            //
            // Check is Expired or Refreshable ...
            var isRefreshable = tokens.IsRefreshable ();
            if (!isRefreshable) {
                return;
            }

            //
            // Refresh Token ...
            var refreshedTokens = await identityProvider
                .RefreshTokens (tokens);
            if (refreshedTokens.IsNull ()) {
                return;
            }

            //
            // Set Refreshed AccessToken to Request ...
            context
                .Request
                .Headers[XAuthorization.Header] =
                $"{XAuthorization.TokenIdentifier}{refreshedTokens.AccessToken}";
        }

        private async Task HandleResponse (HttpContext context) {
            //
            // Log ...
            logger.LogInformation ($"Start Process Response ...");

            //
            await Task.Run (() => { });
        }

        private bool HasAccessToken (HttpContext context) {
            //
            // Check Headers ...
            if (context.IsNull () ||
                context.Request.IsNull () ||
                context.Request.Headers.IsNull ()) {
                return false;
            }

            //
            var result = context
                .Request
                .Headers
                .ContainsKey (
                    XAuthorization.Header
                );

            //
            return result;
        }

        private string GetAccessToken (HttpContext context) {
            //
            var hasAccessToken = HasAccessToken (context);
            if (!hasAccessToken) {
                return string.Empty;
            }

            //
            // Get Result ...
            var result = context
                .Request
                .Headers[
                    XAuthorization.Header
                ];
            result = result
                .ToString ()
                .Replace (
                    XAuthorization.TokenIdentifier,
                    ""
                );

            //
            return result;
        }
        #endregion
    }

    /// <summary>
    /// Provide all DI Requirements for XIdentityTokenRefresher Middleware
    /// </summary>
    public static class XIdentityTokenRefresherDIHelper {
        /// <summary>
        /// Use XTokenValidator Middleware
        /// </summary>
        /// <param name="app"></param>
        public static void UseXIdentityTokenRefresher (this IApplicationBuilder app) {
            app.UseMiddleware<XIdentityTokenRefresherMiddleware> ();
        }
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xIdentityService\Middlewares\XProxyMiddleware.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Text;
using System.Threading.Tasks;
using System.Web;
using IdentityModel;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.WebUtilities;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using xCommons.Extensions;
using xExceptions.Constants;
using xIdentityService.Configuration;
using xIdentityService.Constants;
using xIdentityService.Interfaces;
using xIdentityService.Providers;
using xModels.Base;

namespace xIdentityService.Middlewares {
    /// <summary>
    /// Proxy Server Middleware ...
    /// </summary>
    public class XProxyMiddleware : XBaseClass {
        //
        #region Pros ...
        private readonly HttpClient HTTP_CLIENT;
        private readonly RequestDelegate NEXT_MIDDLEWARE;
        private readonly XProxyConfiguration CONFIGURATION;
        #endregion

        //
        #region Constructor ...
        public XProxyMiddleware (
            ILoggerFactory loggerFactory,
            RequestDelegate nextMiddleware,
            XProxyConfiguration configuration,
            IHttpClientFactory httpClientFactory
        ) : base (loggerFactory) {
            //
            this.CONFIGURATION = configuration;
            this.NEXT_MIDDLEWARE = nextMiddleware;

            //
            // Create Http Client ...
            this.HTTP_CLIENT = httpClientFactory
                .CreateClient (XProxyConstants.XPROXY_HTTP_CLIENT);

            //
            // Logging Server Configuration ...
            LogXProxyServerConfig ();
        }
        #endregion

        //
        #region Public ...
        public async Task InvokeAsync (HttpContext context) {
            //
            #region Bussiness Logic ...
            //
            var routeDescriptor = GetRouteDescriptor (context.Request);
            if (!routeDescriptor.IsNull ()) {
                //
                #region Handle Authorization ...
                //
                try {
                    //
                    // Handle XPowered ...
                    if (routeDescriptor.EnableXPoweredByAthorization) {
                        //
                        var isPoweredByPass = context.Request.Headers
                            .Any (h => h.Key
                                .ToNormalString () == xCommons.Constants.XAuthorization.XPoweredBy
                                .ToNormalString () &&
                                h.Value
                                .ToString ()
                                .ToNormalString () == CONFIGURATION.XPoweredValue
                                .ToNormalString ()
                            );

                        //
                        if (!isPoweredByPass) {
                            ThrowNotAuthorizedException ();
                        }
                    }

                    //
                    // Handle EndableAuthorization ...
                    if (routeDescriptor.EnableAuthorization) {
                        //
                        // Retrieve User Info for Authentication ...
                        var userName = context.User.Identity.Name;
                        var isUserAuthenticated = !userName.IsNull () &&
                            context.User.Identity.IsAuthenticated;
                        if (!isUserAuthenticated &&
                            !routeDescriptor.AllowedScopes.HasChild ()
                        ) {
                            ThrowNotAuthorizedException ();
                        }

                        //
                        // Check Allowed Scopes Authorization ...
                        if (routeDescriptor.AllowedScopes.HasChild ()) {
                            //
                            var scopeClaims = context.User.Claims
                                .Where (c => c.Type == JwtClaimTypes.Scope)
                                .Select (c => c.Value);
                            var isScopePassed = scopeClaims.HasChild () &&
                                scopeClaims.Any (c => routeDescriptor.AllowedScopes
                                    .Any (allowedScope => allowedScope
                                        .ToNormalString () == c
                                        .ToNormalString ()
                                    )
                                );
                            if (!isScopePassed) {
                                ThrowNotAuthorizedException ();
                            }
                        }

                        //
                        // Check Allowed Roles  Authorization ...
                        if (
                            isUserAuthenticated &&
                            routeDescriptor.AllowedRoles.HasChild ()
                        ) {
                            //
                            var roleClaim = context.User.Claims
                                .FirstOrDefault (c => c.Type == JwtClaimTypes.Role);
                            var isRolePassed = !roleClaim.IsNull () &&
                                routeDescriptor.AllowedRoles
                                .Any (role => role
                                    .ToNormalString () == roleClaim.Value
                                    .ToNormalString ());
                            if (!isRolePassed) {
                                ThrowNotAuthorizedException ();
                            }
                        }
                    }
                } catch {
                    context.Response.StatusCode = (int) HttpStatusCode.Unauthorized;
                    return;
                }
                #endregion

                //
                // Extract Request Uri from Received Request ...
                var requestUri = GetUri (context.Request);
                if (!requestUri.IsNull ()) {
                    //
                    // Retrieve Request based on current ...
                    var request = GetRequestMessage (
                        uri: requestUri,
                        context: context
                    );

                    //
                    SendLog ($"Send Request to Recieve Response ...", LogLevel.Information);

                    //
                    // Send Request and Retrieve Response ...
                    try {
                        //
                        var response = await HTTP_CLIENT.SendAsync (
                            request,
                            HttpCompletionOption.ResponseContentRead
                        );

                        //
                        // Set Current Response Status Code ...
                        context.Response.StatusCode = (int) response.StatusCode;

                        //
                        // Retrieve Response Headers and Set To Current Response ...
                        HandleResponseHeaders (context, response);

                        //
                        // Processing Response Content ...
                        await ProcessResponseContent (context, response);
                    } catch (Exception ex) {
                        //
                        LogMessage ($"Exception: {ex.Message}", LogLevel.Error);

                        //
                        context.Response.StatusCode = (int) HttpStatusCode.BadRequest;
                    }

                    //
                    return;
                }
            }
            #endregion

            //
            await NEXT_MIDDLEWARE (context);
        }
        #endregion

        //
        #region Private ...
        /// <summary>
        /// Throw Required Exception ...
        /// </summary>
        private void ThrowNotAuthorizedException () {
            throw XException.NotAuthorized.ToException ();
        }

        /// <summary>
        /// Show propper logs if Enabled ...
        /// </summary>
        /// <param name="message"></param>
        /// <param name="logLevel"></param>
        private void SendLog (string message, LogLevel logLevel = LogLevel.Information) {
            //
            if (!CONFIGURATION.EnableLogging) {
                return;
            }

            //
            LogMessage (
                message: message,
                logLevel: logLevel
            );
        }

        /// <summary>
        /// Log Proxy Server Configuration ...
        /// </summary>
        private void LogXProxyServerConfig () {
            //
            // Retrieve XProxyConfiguration class from Configurations and Validate them ...
            if (CONFIGURATION.IsNull ()) {
                throw XException.InvalidConfiguration.ToException ();
            }

            //
            // Try to Log Proxy Configuration ...
            ConsoleMessage ("===============================");
            ConsoleMessage ("= Proxy Server Configurations: ");
            ConsoleMessage ("===============================");

            //
            ConsoleMessage ($"Host: {CONFIGURATION.Host}");
            ConsoleMessage ($"XPoweredValue: {CONFIGURATION.XPoweredValue}");
            ConsoleMessage ($"EnableLogging: {CONFIGURATION.EnableLogging}");
            ConsoleMessage ($"DisableSSLCheck: {CONFIGURATION.DisableSSLCheck}");
            ConsoleMessage ($"AllowAutoRedirect: {CONFIGURATION.AllowAutoRedirect}");
            ConsoleMessage ($" ");
            ConsoleMessage ($"Routes: ");
            ConsoleMessage ($" ");

            //
            CONFIGURATION.Routes
                .ToList ()
                .ForEach (routeDescriptor => {
                    ConsoleMessage ("===============================");
                    ConsoleMessage ($"= Rote => {routeDescriptor.Route}");
                    ConsoleMessage ("===============================");
                    ConsoleMessage ($"AllowedRoles: {routeDescriptor.AllowedRoles.ToJSON()}");
                    ConsoleMessage ($"AllowedScopes: {routeDescriptor.AllowedScopes.ToJSON()}");
                    ConsoleMessage ($"EnableAuthorization: {routeDescriptor.EnableAuthorization}");
                    ConsoleMessage ($"EnableXPoweredByAthorization: {routeDescriptor.EnableXPoweredByAthorization}");
                    ConsoleMessage ($" ");
                });
        }

        /// <summary>
        /// Retrieve Destination Request Path based on Current Request ...
        /// </summary>
        /// <param name="request"></param>
        /// <returns></returns>
        private Uri GetUri (HttpRequest request) {
            //
            // Create temp result ...
            Uri result = null;
            var requestPath = "";

            //
            SendLog ($"Receive Request: {request.Path} ...", LogLevel.Information);

            //
            // Try to Findout Route Descriptor ...
            var routeDescriptor = GetRouteDescriptor (request);

            //
            // Route Descriptor Exists && Path for Delegating ...
            if (!routeDescriptor.IsNull () &&
                request.Path
                .StartsWithSegments (routeDescriptor.Route)
            ) {
                //
                // Prepare Request Path by Cleaning Starter Path Segment ...
                requestPath = request.Path
                    .ToString ()
                    .Replace (routeDescriptor.Route, "");
                if (requestPath.StartsWith ("/")) {
                    requestPath = requestPath.Substring (1);
                }

                //
                // Decoding URL ...
                requestPath = HttpUtility.UrlDecode (requestPath);

                //
                var colonIndex = requestPath.IndexOf (":");
                if (colonIndex > -1) {
                    //
                    var doubleSlash = requestPath.Substring (colonIndex + 1, 2);
                    var isDoubleSlash = doubleSlash == "//";

                    //
                    if (!isDoubleSlash) {
                        //
                        var protocol = requestPath
                            .Substring (0, colonIndex);
                        var section = requestPath
                            .Substring (colonIndex + 2, requestPath.Length - colonIndex - 2);

                        //
                        requestPath = $"{protocol}://{section}";
                    }
                }
            }

            //
            // Validate Request Path ...
            if (!requestPath.IsNullOrEmpty ()) {
                //
                result = new Uri (requestPath);

                //
                SendLog ($"Process Request: {requestPath} ...", LogLevel.Information);
            }

            //
            return result;
        }

        /// <summary>
        /// Retrieve Propper Request Message based on HttpContext and uri ...F
        /// </summary>
        /// <param name="context"></param>
        /// <param name="uri"></param>
        /// <returns></returns>
        private HttpRequestMessage GetRequestMessage (
            HttpContext context,
            Uri uri
        ) {
            //
            var result = new HttpRequestMessage ();
            FillRequest (context, result);

            //
            // Handle Queries ...
            SendLog ($"Start Processing Queries: ");
            foreach (var query in context.Request.Query) {
                //
                var key = query.Key;
                var value = HttpUtility.UrlDecode (query.Value);

                //
                uri = new Uri (
                    QueryHelpers.AddQueryString (
                        uri.OriginalString,
                        new Dictionary<string, string> {
                            [key] = value
                        }
                    )
                );

                //
                SendLog ($"Query : {key}:{value} was Processed ...");
            }

            //
            result.RequestUri = uri;
            result.Headers.Host = uri.Host;

            //
            // Retrieve Request Method ...
            result.Method = GetMethod (context.Request.Method);

            //
            return result;
        }

        /// <summary>
        /// Fill Request Message by provide HttpContext ...
        /// </summary>
        /// <param name="context"></param>
        /// <param name="message"></param>
        private void FillRequest (
            HttpContext context,
            HttpRequestMessage message
        ) {
            //
            var requestMethod = context.Request.Method;

            //
            if (!HttpMethods.IsGet (requestMethod) &&
                !HttpMethods.IsHead (requestMethod) &&
                !HttpMethods.IsTrace (requestMethod) &&
                !HttpMethods.IsDelete (requestMethod)
            ) {
                //
                var streamContent = new StreamContent (context.Request.Body);
                message.Content = streamContent;
            }

            //
            // Handle Base Headers ...
            var regularHeaders = context.Request.Headers
                .Where (hr => hr.Key != XProxyConstants.XPROXY_ACCEPTED_HEADERS &&
                    !hr.Key
                    .Contains (
                        XProxyConstants.XPROXY_FORWARD_HEADER
                    )
                );

            //
            // Handle Aceepted Headers ...
            IEnumerable<string> acceptedHeaders = null;
            var acceptedHeadersKeyValue = context.Request.Headers
                .FirstOrDefault (hr =>
                    hr.Key == XProxyConstants.XPROXY_ACCEPTED_HEADERS
                );
            if (!acceptedHeadersKeyValue.IsNull ()) {
                //
                acceptedHeaders = acceptedHeadersKeyValue.Value
                    .ToString ()
                    .ParseListString<string> ();

                //
                // Filter Regular Headers ...
                if (
                    regularHeaders.HasChild () &&
                    acceptedHeaders.HasChild ()
                ) {
                    //
                    regularHeaders = regularHeaders
                        .Where (rhr => acceptedHeaders
                            .Contains (rhr.Key)
                        );
                }
            }
            foreach (var header in regularHeaders) {
                //
                SendLog ($"Adding Header: {header.Key}:{header.Value} ...");

                //
                message.Headers.Add (
                    header.Key,
                    header.Value
                    .ToString ()
                );
            }

            //
            // Handle ForWarded Headers ...
            // Since Forward Headers is Custom kind, this means user actually need this
            // Header, so there is no need to put them on AcceptedHeaders ...
            var forwardHeaders = context.Request.Headers
                .Where (hr => hr.Key
                    .Contains (
                        XProxyConstants.XPROXY_FORWARD_HEADER
                    )
                );
            foreach (var header in forwardHeaders) {
                //
                var key = header.Key
                    .Replace (
                        XProxyConstants.XPROXY_FORWARD_HEADER,
                        string.Empty
                    );

                //
                SendLog ($"Forwarding Header: {header.Key} to {key} ...");

                //
                message.Headers
                    .Add (
                        key,
                        header.Value
                        .ToString ()
                    );
            }
        }

        /// <summary>
        /// Retreive and Extract Method Type of HttpRequest ...
        /// </summary>
        /// <param name="method"></param>
        /// <returns></returns>
        private static HttpMethod GetMethod (string method) {
            //
            if (HttpMethods.IsDelete (method)) {
                return HttpMethod.Delete;
            } else if (HttpMethods.IsGet (method)) {
                return HttpMethod.Get;
            } else if (HttpMethods.IsHead (method)) {
                return HttpMethod.Head;
            } else if (HttpMethods.IsOptions (method)) {
                return HttpMethod.Options;
            } else if (HttpMethods.IsPost (method)) {
                return HttpMethod.Post;
            } else if (HttpMethods.IsPut (method)) {
                return HttpMethod.Put;
            } else if (HttpMethods.IsTrace (method)) {
                return HttpMethod.Trace;
            }

            //
            return new HttpMethod (method);
        }

        /// <summary>
        /// add all headers exists in HttpResponse MEssage to Current Context Response Headers ...
        /// </summary>
        /// <param name="context"></param>
        /// <param name="message"></param>
        private void HandleResponseHeaders (
            HttpContext context,
            HttpResponseMessage message
        ) {
            //
            // Handle Message Headers ...
            foreach (var header in message.Headers) {
                context.Response.Headers[header.Key] = header.Value
                    .ToArray ();
            }

            //
            // Handle Message Content Headers ...
            foreach (var header in message.Content.Headers) {
                context.Response.Headers[header.Key] = header.Value
                    .ToArray ();
            }

            //
            context.Response.Headers.Remove ("transfer-encoding");
        }

        /// <summary>
        /// Processing Response Content and Handle it on HttpContextResponse ...
        /// </summary>
        /// <param name="context"></param>
        /// <param name="response"></param>
        /// <returns></returns>
        private async Task ProcessResponseContent (
            HttpContext context,
            HttpResponseMessage message
        ) {
            //
            // Reading Content as Byte Array ...
            var contentBytes = await message.Content
                .ReadAsByteArrayAsync ();

            //
            // Check ContentType of Response ...
            if (
                IsContentOfType (message, XResponseContentTypes.HTML) ||
                IsContentOfType (message, XResponseContentTypes.JSON) ||
                IsContentOfType (message, XResponseContentTypes.JavaScript)
            ) {
                //
                // If their String Content ...
                var stringContent = Encoding.UTF8.GetString (contentBytes);

                //
                // TODO: here we can change String Contents ...

                //
                // Writing new Content to Response ...
                await context.Response
                    .WriteAsync (
                        stringContent,
                        Encoding.UTF8
                    );
            } else {
                //
                // if they have non string content ...
                await context.Response.Body
                    .WriteAsync (
                        buffer: contentBytes,
                        offset: 0,
                        count: contentBytes.Length
                    );
            }

            //
            SendLog ($"Response Content Processed ...", LogLevel.Information);
        }

        /// <summary>
        /// Check Content Type of Specific Response ...
        /// </summary>
        /// <param name="response"></param>
        /// <param name="type"></param>
        /// <returns></returns>
        private bool IsContentOfType (
            HttpResponseMessage response,
            string type
        ) {
            //
            // Create EMpty Result ...
            var result = false;

            //
            // Retrieve and Check Content Type of Response ...
            if (response.Content?.Headers?.ContentType != null) {
                result = response.Content.Headers.ContentType.MediaType == type;
            }

            //
            return result;
        }

        /// <summary>
        /// Retrieve and Extract Route Descriptor ...
        /// </summary>
        /// <param name="request"></param>
        /// <returns></returns>
        private XProxyRouteDescriptor GetRouteDescriptor (HttpRequest request) {
            //
            // Validate Args ...
            if (
                CONFIGURATION.IsNull () ||
                !CONFIGURATION.Routes.HasChild ()
            ) {
                return null;
            }

            //
            var result = CONFIGURATION.Routes
                .FirstOrDefault (rd => !rd.Route.IsNullOrEmpty () &&
                    request.Path
                    .StartsWithSegments (rd.Route
                        .ToNormalString ()
                    )
                );

            //
            return result;
        }
        #endregion 
    }

    /// <summary>
    /// Provide all requirements for Dependency Injection Handler ...
    /// </summary>
    public static class XDIHelperExtension {
        /// <summary>
        /// Retrieve XProxy Middelware Configuration from Configuration ...
        /// </summary>
        /// <param name="config"></param>
        /// <returns></returns>
        public static XProxyConfiguration GetXProxyConfiguration (this IConfiguration config) {
            //
            var xProxyConfiguration = config.GetSection (ConfigurationNodeNames.XPROXY_CONFIGURATION_NODE_NAME);
            return xProxyConfiguration.Get<XProxyConfiguration> ();
        }

        /// <summary>
        /// Register HTTP Handler for XProxy Server ...
        /// </summary>
        /// <param name="services"></param>
        /// <param name="configuration"></param>
        /// <param name="httpHandler"></param>
        public static void AddXProxyHttpHandler (
            this IServiceCollection services,
            IConfiguration configuration,
            HttpClientHandler httpHandler = null
        ) {
            //
            var proxyConfig = configuration.GetXProxyConfiguration ();
            if (proxyConfig.IsNull ()) {
                throw XException.InvalidConfiguration.ToException ();
            }

            //
            services.AddXProxyHttpHandler (
                httpHandler: httpHandler,
                configuration: proxyConfig
            );
        }

        /// <summary>
        /// Register HTTP Handler for XProxy Server ...
        /// </summary>
        /// <param name="services"></param>
        /// <param name="configuration"></param>
        /// <param name="httpHandler"></param>
        public static void AddXProxyHttpHandler (
            this IServiceCollection services,
            XProxyConfiguration configuration,
            HttpClientHandler httpHandler = null
        ) {
            //
            if (configuration.IsNull ()) {
                throw XException.InvalidConfiguration.ToException ();
            }

            //
            if (httpHandler.IsNull ()) {
                httpHandler = new HttpClientHandler ();
            }

            //
            httpHandler.AllowAutoRedirect = configuration.AllowAutoRedirect;

            //
            if (configuration.DisableSSLCheck) {
                httpHandler.ServerCertificateCustomValidationCallback = (sender, certificate, chain, sslPolicyErrors) => true;
            }

            //
            services
                .AddHttpClient (XProxyConstants.XPROXY_HTTP_CLIENT)
                .ConfigurePrimaryHttpMessageHandler (() => {
                    return httpHandler;
                });
        }

        /// <summary>
        /// Register XProxy On Server ...
        /// </summary>
        /// <param name="services"></param>
        /// <param name="configuration"></param>
        /// <param name="httpHandler"></param>
        public static void AddXProxyServer (
            this IServiceCollection services,
            IConfiguration configuration,
            HttpClientHandler httpHandler = null
        ) {
            //
            var proxyConfig = configuration.GetXProxyConfiguration ();

            //
            services.AddXProxyServer (
                httpHandler: httpHandler,
                configuration: proxyConfig
            );
        }

        /// <summary>
        /// Register XProxy On Server ...
        /// </summary>
        /// <param name="services"></param>
        /// <param name="configuration"></param>
        /// <param name="httpHandler"></param>
        public static void AddXProxyServer (
            this IServiceCollection services,
            XProxyConfiguration configuration,
            HttpClientHandler httpHandler = null
        ) {
            //
            // Validate Args ...
            if (configuration.IsNull ()) {
                throw XException.InvalidConfiguration.ToException ();
            }

            //
            // Register Proxy Configuration ...
            services.AddSingleton<XProxyConfiguration> (configuration);

            //
            // Regiter Proxy Handler ...
            services.AddXProxyHttpHandler (
                httpHandler: httpHandler,
                configuration: configuration
            );
        }

        /// <summary>
        /// Register XProxy On Server ...
        /// </summary>
        /// <param name="services"></param>
        /// <param name="configuration"></param>
        public static void AddXProxyClient (
            this IServiceCollection services,
            IConfiguration configuration
        ) {
            //
            var proxyConfig = configuration.GetXProxyConfiguration ();

            //
            services.AddXProxyClient (
                configuration: proxyConfig
            );
        }

        /// <summary>
        /// Register XProxy On Client ...
        /// </summary>
        /// <param name="services"></param>
        /// <param name="configuration"></param>
        public static void AddXProxyClient (
            this IServiceCollection services,
            XProxyConfiguration configuration
        ) {
            //
            // Validate Args ...
            if (configuration.IsNull ()) {
                throw XException.InvalidConfiguration.ToException ();
            }

            //
            // Register Proxy Configuration ...
            services.AddSingleton<XProxyConfiguration> (configuration);

            //
            // Register IXProxyHelper ...
            services.AddSingleton<IXProxyHelper, XProxyHelper> ();
        }

        /// <summary>
        /// Adding XProxy Middleware to Applications ...
        /// </summary>
        /// <param name="app"></param>
        public static void UseXProxy (this IApplicationBuilder app) {
            app.UseMiddleware<XProxyMiddleware> ();
        }
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xIdentityService\Models\XBaseRestResponse.cs

using RestSharp;

namespace xIdentityService.Models
{
    public class XBaseRestResponse<T>
    {
        public T Model { get; set; }
        public IRestResponse Response { get; set; }
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xIdentityService\Partial\XIdentityProvider+Admin.cs

using System.Collections.Generic;
using System.Threading.Tasks;
using xCommons.Extensions;
using xHttpService.Constants;
using xIdentityModels.Dtos;
using xIdentityModels.Models;
using xIdentityService.Constants;

namespace xIdentityService.Providers {
    public partial class XIdentityProvider {
        //
        #region Admin ...
        /// <summary>
        /// Ban Specific Users
        /// </summary>
        /// <param name="tokens">Authentication Tokens</param>
        /// <param name="model">an instance of <see>XUserNameIdRequest</see> which represents user identifier list to Ban</param>
        /// <returns>a list of banned users identifiers</returns>
        public async Task<IEnumerable<string>> Ban (
            XTokenResponse tokens,
            XUserNameIdRequest model
        ) {
            //
            // Validate Args ...
            await validationProvider
                .GroupValidationBuilder ()
                .AddNotNull (
                    tokens,
                    model
                )
                .AddNotEmpty (tokens.AccessToken)
                .AddNotZeroChilds (model.Ids)
                .ValidateGroupAsync ();

            //
            var client = GetRestClient (tokens);

            //
            var request = GetRestRequet (XApiAccountEndpoint.Ban);
            request.AddJsonBody (model);

            //
            var response = await RunRestRequest<IEnumerable<string>> (
                client,
                request,
                XHttpMethod.POST
            );
            return response;
        }

        /// <summary>
        /// UnBann Specific Users 
        /// </summary>
        /// <param name="tokens">Authentication Tokens</param>
        /// <param name="model">an instance of <see>XUserNameIdRequest</see> which represents user identifier list to Ban</param>
        /// <returns>a list of unbanned users identifiers</returns>
        public async Task<IEnumerable<string>> UnBan (
            XTokenResponse tokens,
            XUserNameIdRequest model
        ) {
            //
            // Validate Args ...
            await validationProvider
                .GroupValidationBuilder ()
                .AddNotNull (
                    tokens,
                    model
                )
                .AddNotEmpty (tokens.AccessToken)
                .AddNotZeroChilds (model.Ids)
                .ValidateGroupAsync ();

            //
            var client = GetRestClient (tokens);

            //
            var request = GetRestRequet (XApiAccountEndpoint.UnBan);
            request.AddJsonBody (model);

            //
            var response = await RunRestRequest<IEnumerable<string>> (
                client,
                request,
                XHttpMethod.POST
            );
            return response;
        }

        /// <summary>
        /// Check Specific User is Banned or not
        /// </summary>
        /// <param name="tokens">Authentication Tokens</param>
        /// <param name="userSelectByParam">specified user's identifier</param>
        /// <returns>a boolean value which represent user banned or not</returns>
        public async Task<bool> IsBanned (
            XTokenResponse tokens,
            string userSelectByParam
        ) {
            //
            // Validate Args ...
            await validationProvider
                .GroupValidationBuilder ()
                .AddNotNull (tokens)
                .AddNotEmpty (
                    userSelectByParam,
                    tokens.AccessToken
                )
                .ValidateGroupAsync ();

            //
            var client = GetRestClient (tokens);

            //
            var request = GetRestRequet (
                XApiAccountEndpoint.IsBanned,
                @params : new Dictionary<string, string> { { XParam.XUserSelectByParam.GetStringValue (), userSelectByParam } }
            );

            //
            var response = await RunRestRequest<bool> (
                client,
                request,
                XHttpMethod.GET
            );
            return response;
        }
        #endregion
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xIdentityService\Partial\XIdentityProvider+Authentication.cs

using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using IdentityModel.Client;
using xCommons.Extensions;
using xExceptions.Constants;
using xHttpService.Constants;
using xIdentityModels.Extensions;
using xIdentityModels.Models;
using xIdentityService.Constants;

namespace xIdentityService.Providers {
    public partial class XIdentityProvider {
        //
        #region Authentication Handlers ...
        /// <summary>
        /// Request for Discovery Document 
        /// </summary>
        /// <returns>an instance of DiscoveryDocumentResponse</returns>
        public async Task<DiscoveryDocumentResponse> RequestDiscoveryDocument () {
            //
            var httpClient = GetHttpClient ();

            //
            try {
                //
                var result = httpClient
                    .GetDiscoveryDocumentAsync (identityConfiguration.Authority)
                    .ContinueWith (docTask => {
                        //
                        httpClient.Dispose ();
                        return docTask.Result;
                    });

                //
                return await result;
            } catch {
                throw XException.ActionFailed.ToException ();
            }
        }

        /// <summary>
        /// Request AccessToken for Specific XApiScope
        /// </summary>
        /// <param name="scope">a member of <see>XApiScope</see></param>
        /// <returns>an instance of <see>XTokenResponse</see></returns>
        public async Task<XTokenResponse> RequestScopeAccessToken (string scope) {
            //
            // Validate Args ...
            var scopeName = string.Empty;
            try {
                scopeName = scope; // scope.GetStringValue ();
            } catch { }
            if (scopeName.IsNullOrEmpty ()) {
                XException.InvalidArgs.Throw ();
            }

            //
            var client = GetRestClient ();
            var request = GetRestRequet (
                XApiAccountEndpoint.RequestScopeAccessToken,
                headers : new Dictionary<string, string> { { XParam.XScope.GetStringValue (), scope.ToString () } });

            //
            var response = await RunRestRequest<XTokenResponse> (
                client,
                request,
                XHttpMethod.POST
            );

            //
            // Save Token ...
            if (!response.IsNull ()) {
                await tokenProvider.AddOrUpdateToken (response);
            }

            //
            return response;
        }

        /// <summary>
        /// Validate a token
        /// </summary>
        /// <param name="model">Authentication Tokens</param>
        /// <returns>an instance of TokenIntrospectionResponse</returns>
        public async Task<TokenIntrospectionResponse> Introspection (XTokenResponse model) {
            //
            // Validate Args ...
            await validationProvider
                .GroupValidationBuilder ()
                .AddNotNull (model)
                .AddNotEmpty (model.AccessToken)
                .ValidateGroupAsync ();

            //
            var httpClient = GetHttpClient ();

            //
            try {
                //
                var discoDoc = await RequestDiscoveryDocument ();
                if (discoDoc.IsError) {
                    XException.ActionFailed.Throw ();
                }

                //
                var response = await httpClient.IntrospectTokenAsync (new TokenIntrospectionRequest {
                    //
                    Address = discoDoc.IntrospectionEndpoint,
                        ClientId = identityConfiguration.ClientId,
                        ClientSecret = identityConfiguration.ClientSecret,

                        //
                        Token = model.AccessToken
                });
                if (response.IsError) {
                    throw new Exception (response.Error);
                }

                //
                return response;
            } catch {
                throw XException.ActionFailed.ToException ();
            }
        }

        /// <summary>
        /// Authenticate a User
        /// </summary>
        /// <param name="model">User Login Required Info, an instance of <see>XLoginRequest</see></param>
        /// <returns>an instance of <see>XTokenResponse</see></returns>
        public async Task<XTokenResponse> Authenticate (XLoginRequest model) {
            //
            // Validate Args ...
            validationProvider
                .GroupValidationBuilder ()
                .AddNotNull (model)
                .AddNotEmpty (
                    model.UserSelectBy,
                    model.Password
                )
                .ValidateGroup ();

            //
            var client = GetRestClient ();
            var request = GetRestRequet (XApiAccountEndpoint.Authenticate);
            request.AddJsonBody (model);

            //
            var response = await RunRestRequest<XTokenResponse> (
                client,
                request,
                XHttpMethod.POST
            );

            //
            // Save Token ...
            if (!response.IsNull ()) {
                await tokenProvider.AddOrUpdateToken (response);
            }

            //
            return response;
        }

        /// <summary>
        /// Do Login based on XLoginRequest
        /// </summary>
        /// <param name="model">User Login Required Info, an instance of <see>XLoginRequest</see></param>
        /// <returns>an instance of <see>XTokenResponse</see></returns>
        public async Task<XLoginResponse> Login (XLoginRequest model) {
            //
            // Validate Args ...
            validationProvider
                .GroupValidationBuilder ()
                .AddNotNull (model, model.Device)
                .AddNotEmpty (
                    model.UserSelectBy,
                    model.Password
                )
                .ValidateGroup ();

            //
            var client = GetRestClient ();
            var request = GetRestRequet (XApiAccountEndpoint.Login);
            request.AddJsonBody (model);

            //
            var response = await RunRestRequest<XLoginResponse> (
                client,
                request,
                XHttpMethod.POST
            );

            //
            if (!response.IsNull ()) {
                //
                var tokens = response.ToXTokenResponse ();
                await tokenProvider.AddOrUpdateToken (tokens);
            }

            //
            return response;
        }

        /// <summary>
        /// Logout from System
        /// </summary>
        /// <param name="model"></param>
        /// <returns></returns>
        public async Task Logout (XTokenResponse model) {
            //
            await validationProvider
                .GroupValidationBuilder ()
                .AddNotNull (model)
                .AddNotEmpty (model.AccessToken)
                .ValidateGroupAsync ();

            //
            var isExists = await tokenProvider
                .IsTokenExists (model.AccessToken);
            if (isExists) {
                await tokenProvider
                    .RemoveToken (model.AccessToken);
            }
        }

        /// <summary>
        /// Refresh Tokens 
        /// </summary>
        /// <param name="model">Authentication Tokens</param>
        /// <returns>an instance of <see>XTokenResponse</see></returns>
        public async Task<XTokenResponse> RefreshTokens (XTokenResponse model) {
            //
            // Validate Args ...
            validationProvider
                .GroupValidationBuilder ()
                .AddNotNull (model)
                .AddNotEmpty (
                    model.AccessToken,
                    model.RefreshToken
                )
                .ValidateGroup ();

            //
            var client = GetRestClient (model);

            //
            var request = GetRestRequet (
                XApiAccountEndpoint.RefreshTokens,
                headers : model.ToHeaderDictionary ());
            request.AddJsonBody (model);

            //
            var response = await RunRestRequest<XTokenResponse> (
                client,
                request,
                XHttpMethod.POST
            );
            if (!response.IsNull ()) {
                await tokenProvider.UpdateToken (response);
            }

            //
            return response;
        }
        #endregion

        //
        #region Password Actions Handlers ...
        /// <summary>
        /// Change Password
        /// </summary>
        /// <param name="tokens">Authentication Tokens</param>
        /// <param name="model">an instance of <see>XActionRequest</see> class which provider requirement for action</param>
        /// <returns></returns>
        public async Task ChangePassword (
            XTokenResponse tokens,
            XActionRequest model
        ) {
            //
            // Validate Args ...
            await validationProvider
                .GroupValidationBuilder ()
                .AddNotNull (tokens, model)
                .AddNotEmpty (
                    model.Lang,
                    model.Password,
                    model.NewPassword,
                    model.ReturnUrl)
                .AddNotNull (model.Device)
                .ValidateGroupAsync ();

            //
            // Validate User Select By Param ...
            var userSelectByParam = GetUserSelectByParam (
                model,
                forceNotNull : true,
                excludes : null);

            //
            var client = GetRestClient (tokens);
            var request = GetRestRequet (
                XApiAccountEndpoint.ChangePassword,
                headers : tokens.ToHeaderDictionary ());
            request.AddJsonBody (model);

            //
            var response = await RunRestRequest<Object> (
                client,
                request,
                XHttpMethod.POST
            );
        }
        #endregion
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xIdentityService\Partial\XIdentityProvider+Friendship.cs

using System.Collections.Generic;
using System.Threading.Tasks;
using xCommons.Extensions;
using xHttpService.Constants;
using xHttpService.Extensions;
using xIdentityModels.Constants;
using xIdentityModels.Dtos;
using xIdentityModels.Models;
using xIdentityModels.Navigations;
using xIdentityService.Constants;
using xModels.Dtos;

namespace xIdentityService.Providers
{
    public partial class XIdentityProvider
    {
        //
        #region Friendship ...
        /// <summary>
        /// Follow a User
        /// </summary>
        /// <param name="tokens">Authentication Tokens</param>
        /// <param name="destUser">a user identifier which represent destination user</param>
        /// <returns>an instance of <see>XFriendshipFollowing</see></returns>
        public async Task<XFriendshipFollowing> Follow(
            XTokenResponse tokens,
            string destUser
        )
        {
            //
            // Validate Args ...
            await validationProvider
                .GroupValidationBuilder()
                .AddNotNull(tokens)
                .AddNotEmpty(
                    destUser,
                    tokens.AccessToken
                )
                .ValidateGroupAsync();

            //
            var client = GetRestClient(tokens);

            //
            var request = GetRestRequet(
                XApiAccountEndpoint.Follow,
                @params: new Dictionary<string, string> { { XParam.XDestUser.GetStringValue (), destUser }
                }
            );

            //
            var response = await RunRestRequest<XFriendshipFollowing>(
                client,
                request,
                XHttpMethod.POST
            );
            return response;
        }

        /// <summary>
        /// Cancel Following Request 
        /// </summary>
        /// <param name="tokens">Authentication Tokens</param>
        /// <param name="destUser">a user identifier which represent destination user</param>
        /// <returns>a boolean value</returns>
        public async Task<bool> Cancel(
            XTokenResponse tokens,
            string destUser
        )
        {
            //
            // Validate Args ...
            await validationProvider
                .GroupValidationBuilder()
                .AddNotNull(tokens)
                .AddNotEmpty(
                    destUser,
                    tokens.AccessToken
                )
                .ValidateGroupAsync();

            //
            var client = GetRestClient(tokens);

            //
            var request = GetRestRequet(
                XApiAccountEndpoint.Cancel,
                @params: new Dictionary<string, string> { { XParam.XDestUser.GetStringValue (), destUser }
                }
            );

            //
            var response = await RunRestRequest<bool>(
                client,
                request,
                XHttpMethod.POST
            );
            return response;
        }

        /// <summary>
        /// Unfollow a Follower
        /// </summary>
        /// <param name="tokens">Authentication Tokens</param>
        /// <param name="destUser">a user identifier which represent destination user</param>
        /// <returns></returns>
        public async Task UnFollowFollower(
            XTokenResponse tokens,
            string destUser
        )
        {
            //
            // Validate Args ...
            await validationProvider
                .GroupValidationBuilder()
                .AddNotNull(tokens)
                .AddNotEmpty(
                    destUser,
                    tokens.AccessToken
                )
                .ValidateGroupAsync();

            //
            var client = GetRestClient(tokens);

            //
            var request = GetRestRequet(
                XApiAccountEndpoint.UnFollowFollower,
                @params: new Dictionary<string, string> { { XParam.XDestUser.GetStringValue (), destUser }
                }
            );

            //
            var response = await RunRestRequest<object>(
                client,
                request,
                XHttpMethod.POST
            );
        }

        /// <summary>
        /// Unfollow Following
        /// </summary>
        /// <param name="tokens">Authentication Tokens</param>
        /// <param name="destUser">a user identifier which represent destination user</param>
        /// <returns></returns>
        public async Task UnFollowFollowing(
            XTokenResponse tokens,
            string destUser
        )
        {
            //
            // Validate Args ...
            await validationProvider
                .GroupValidationBuilder()
                .AddNotNull(tokens)
                .AddNotEmpty(
                    destUser,
                    tokens.AccessToken
                )
                .ValidateGroupAsync();

            //
            var client = GetRestClient(tokens);

            //
            var request = GetRestRequet(
                XApiAccountEndpoint.UnFollowFollowing,
                @params: new Dictionary<string, string> { { XParam.XDestUser.GetStringValue (), destUser }
                }
            );

            //
            var response = await RunRestRequest<object>(
                client,
                request,
                XHttpMethod.POST
            );
        }

        /// <summary>
        /// Block a Follower
        /// </summary>
        /// <param name="tokens">Authentication Tokens</param>
        /// <param name="destUser">a user identifier which represent destination user</param>
        /// <returns>an instance of <see>XFriendshipFollowing</see></returns>
        public async Task<XFriendshipFollowing> Block(
            XTokenResponse tokens,
            string destUser
        )
        {
            //
            // Validate Args ...
            await validationProvider
                .GroupValidationBuilder()
                .AddNotNull(tokens)
                .AddNotEmpty(
                    destUser,
                    tokens.AccessToken
                )
                .ValidateGroupAsync();

            //
            var client = GetRestClient(tokens);

            //
            var request = GetRestRequet(
                XApiAccountEndpoint.Block,
                @params: new Dictionary<string, string> { { XParam.XDestUser.GetStringValue (), destUser }
                }
            );

            //
            var response = await RunRestRequest<XFriendshipFollowing>(
                client,
                request,
                XHttpMethod.POST
            );
            return response;
        }

        /// <summary>
        /// Unblock a Blocked User
        /// </summary>
        /// <param name="tokens">Authentication Tokens</param>
        /// <param name="destUser">a user identifier which represent destination user</param>
        /// <returns>an instance of <see>XFriendshipFollowing</see></returns>
        public async Task<XFriendshipFollowing> UnBlock(
            XTokenResponse tokens,
            string destUser
        )
        {
            //
            // Validate Args ...
            await validationProvider
                .GroupValidationBuilder()
                .AddNotNull(tokens)
                .AddNotEmpty(
                    destUser,
                    tokens.AccessToken
                )
                .ValidateGroupAsync();

            //
            var client = GetRestClient(tokens);

            //
            var request = GetRestRequet(
                XApiAccountEndpoint.UnBlock,
                @params: new Dictionary<string, string> { { XParam.XDestUser.GetStringValue (), destUser }
                }
            );

            //
            var response = await RunRestRequest<XFriendshipFollowing>(
                client,
                request,
                XHttpMethod.POST
            );
            return response;
        }

        /// <summary>
        /// Accept a Following Request 
        /// </summary>
        /// <param name="tokens">Authentication Tokens</param>
        /// <param name="destUser">a user identifier which represent destination user</param>
        /// <returns>an instance of <see>XFriendshipFollower</see></returns>
        public async Task<XFriendshipFollower> AcceptRequest(
            XTokenResponse tokens,
            string destUser
        )
        {
            //
            // Validate Args ...
            await validationProvider
                .GroupValidationBuilder()
                .AddNotNull(tokens)
                .AddNotEmpty(
                    destUser,
                    tokens.AccessToken
                )
                .ValidateGroupAsync();

            //
            var client = GetRestClient(tokens);

            //
            var request = GetRestRequet(
                XApiAccountEndpoint.AcceptRequest,
                @params: new Dictionary<string, string> { { XParam.XDestUser.GetStringValue (), destUser }
                }
            );

            //
            var response = await RunRestRequest<XFriendshipFollower>(
                client,
                request,
                XHttpMethod.POST
            );
            return response;
        }

        /// <summary>
        /// Reject a Following Request
        /// </summary>
        /// <param name="tokens">Authentication Tokens</param>
        /// <param name="destUser">a user identifier which represent destination user</param>
        /// <returns>an instance of <see>XFriendshipFollower</see></returns>
        public async Task<XFriendshipFollower> RejectRequest(
            XTokenResponse tokens,
            string destUser
        )
        {
            //
            // Validate Args ...
            await validationProvider
                .GroupValidationBuilder()
                .AddNotNull(tokens)
                .AddNotEmpty(
                    destUser,
                    tokens.AccessToken
                )
                .ValidateGroupAsync();

            //
            var client = GetRestClient(tokens);

            //
            var request = GetRestRequet(
                XApiAccountEndpoint.RejectRequest,
                @params: new Dictionary<string, string> { { XParam.XDestUser.GetStringValue (), destUser }
                }
            );

            //
            var response = await RunRestRequest<XFriendshipFollower>(
                client,
                request,
                XHttpMethod.POST
            );
            return response;
        }

        /// <summary>
        /// Get Friendship Info Model between Specific User and Current User
        /// </summary>
        /// <param name="tokens">Authentication Tokens</param>
        /// <param name="destUser">a user identifier which represent destination user</param>
        /// <returns>an instance of <see>XFriendshipInfoDto</see></returns>
        public async Task<XFriendshipInfoDto> GetFriendshipInfo(
            XTokenResponse tokens,
            string destUser
        )
        {
            //
            // Validate Args ...
            await validationProvider
                .GroupValidationBuilder()
                .AddNotNull(tokens)
                .AddNotEmpty(
                    destUser,
                    tokens.AccessToken
                )
                .ValidateGroupAsync();

            //
            var client = GetRestClient(tokens);

            //
            var request = GetRestRequet(
                XApiAccountEndpoint.FriendshipInfo,
                @params: new Dictionary<string, string> { { XParam.XDestUser.GetStringValue (), destUser }
                }
            );

            //
            var response = await RunRestRequest<XFriendshipInfoDto>(
                client,
                request,
                XHttpMethod.GET
            );
            return response;
        }

        /// <summary>
        /// Check a User IsFollower of Requested User 
        /// </summary>
        /// <param name="tokens">Authentication Tokens</param>
        /// <param name="destUser">a user identifier which represent destination user</param>
        /// <returns>a boolean value</returns>
        public async Task<bool> IsFollower(
            XTokenResponse tokens,
            string destUser
        )
        {
            //
            // Validate Args ...
            await validationProvider
                .GroupValidationBuilder()
                .AddNotNull(tokens)
                .AddNotEmpty(
                    destUser,
                    tokens.AccessToken
                )
                .ValidateGroupAsync();

            //
            var client = GetRestClient(tokens);

            //
            var request = GetRestRequet(
                XApiAccountEndpoint.IsFollower,
                @params: new Dictionary<string, string> { { XParam.XDestUser.GetStringValue (), destUser }
                }
            );

            //
            var response = await RunRestRequest<bool>(
                client,
                request,
                XHttpMethod.GET
            );
            return response;
        }

        /// <summary>
        /// Get Specific Follower 
        /// </summary>
        /// <param name="tokens">Authentication Tokens</param>
        /// <param name="destUser">a user identifier which represent destination user</param>
        /// <returns>an instance of <see>XFriendshipFollower</see></returns>
        public async Task<XFriendshipFollower> GetFollower(
            XTokenResponse tokens,
            string destUser
        )
        {
            //
            // Validate Args ...
            await validationProvider
                .GroupValidationBuilder()
                .AddNotNull(tokens)
                .AddNotEmpty(
                    destUser,
                    tokens.AccessToken
                )
                .ValidateGroupAsync();

            //
            var client = GetRestClient(tokens);

            //
            var request = GetRestRequet(
                XApiAccountEndpoint.Follower,
                @params: new Dictionary<string, string> { { XParam.XDestUser.GetStringValue (), destUser }
                }
            );

            //
            var response = await RunRestRequest<XFriendshipFollower>(
                client,
                request,
                XHttpMethod.GET
            );
            return response;
        }

        /// <summary>
        /// Get Follower State of a User
        /// </summary>
        /// <param name="tokens">Authentication Tokens</param>
        /// <param name="destUser">a user identifier which represent destination user</param>
        /// <returns>an instance of <see>XFriendshipState</see></returns>
        public async Task<XFriendshipState> GetFollowerState(
            XTokenResponse tokens,
            string destUser
        )
        {
            //
            // Validate Args ...
            await validationProvider
                .GroupValidationBuilder()
                .AddNotNull(tokens)
                .AddNotEmpty(
                    destUser,
                    tokens.AccessToken
                )
                .ValidateGroupAsync();

            //
            var client = GetRestClient(tokens);

            //
            var request = GetRestRequet(
                XApiAccountEndpoint.FollowerState,
                @params: new Dictionary<string, string> { { XParam.XDestUser.GetStringValue (), destUser }
                }
            );

            //
            var response = await RunRestRequest<XFriendshipState>(
                client,
                request,
                XHttpMethod.GET
            );
            return response;
        }

        /// <summary>
        /// Get Followers List Of Current User 
        /// </summary>
        /// <param name="tokens">Authentication Tokens</param>
        /// <returns>a collection of <see>XFriendshipFollower</see></returns>
        public async Task<IEnumerable<XFriendshipFollower>> GetFollowers(
            XTokenResponse tokens
        )
        {
            //
            // Validate Args ...
            await validationProvider
                .GroupValidationBuilder()
                .AddNotNull(tokens)
                .AddNotEmpty(tokens.AccessToken)
                .ValidateGroupAsync();

            //
            var client = GetRestClient(tokens);

            //
            var request = GetRestRequet(XApiAccountEndpoint.Followers);

            //
            var response = await RunRestRequest<IEnumerable<XFriendshipFollower>>(
                client,
                request,
                XHttpMethod.GET
            );
            return response;
        }

        /// <summary>
        /// Get All Followers List Includes Blocked, Requested and etc 
        /// of Current User
        /// </summary>
        /// <param name="tokens">Authentication Tokens</param>
        /// <returns>a collection of <see>XFriendshipFollower</see></returns>
        public async Task<IEnumerable<XFriendshipFollower>> GetAllFollowers(
            XTokenResponse tokens
        )
        {
            //
            // Validate Args ...
            await validationProvider
                .GroupValidationBuilder()
                .AddNotNull(tokens)
                .AddNotEmpty(tokens.AccessToken)
                .ValidateGroupAsync();

            //
            var client = GetRestClient(tokens);

            //
            var request = GetRestRequet(XApiAccountEndpoint.AllFollowers);

            //
            var response = await RunRestRequest<IEnumerable<XFriendshipFollower>>(
                client,
                request,
                XHttpMethod.GET
            );
            return response;
        }

        /// <summary>
        /// Return Followers UserName's List of Current User 
        /// </summary>
        /// <param name="tokens">Authentication Tokens</param>
        /// <returns>a collection of UserNames</returns>
        public async Task<IEnumerable<string>> GetFollowersList(
            XTokenResponse tokens
        )
        {
            //
            // Validate Args ...
            await validationProvider
                .GroupValidationBuilder()
                .AddNotNull(tokens)
                .AddNotEmpty(tokens.AccessToken)
                .ValidateGroupAsync();

            //
            var client = GetRestClient(tokens);

            //
            var request = GetRestRequet(XApiAccountEndpoint.FollowersList);

            //
            var response = await RunRestRequest<IEnumerable<string>>(
                client,
                request,
                XHttpMethod.GET
            );
            return response;
        }

        /// <summary>
        /// Retrieve All User's Followers based on Query Model ...
        /// </summary>
        /// <param name="query">Query Model Descriptor</param>
        /// <param name="destUser">Dest User for Reading Followers</param>
        /// <param name="tokens">Requester User's Descriptor</param>
        /// <returns></returns>
        public async Task<XQueryResult<XFriendDto>> QueryFollowers(
            XQuery query,
            string destUser,
            XTokenResponse tokens
        )
        {
            //
            // Validate Args ...
            await validationProvider
                .GroupValidationBuilder()
                .AddNotNull(tokens)
                .AddNotEmpty(destUser)
                .AddNotEmpty(tokens.AccessToken)
                .ValidateGroupAsync();

            //
            var client = GetRestClient(tokens);

            //
            var request = GetRestRequet(XApiAccountEndpoint.QueryFollowers);

            //
            // Attach XQuery to Request ...
            request = request.AttachXQuery(query);
            request = request.AttachDestUser(destUser);

            //
            var response = await RunRestRequest<XQueryResult<XFriendDto>>(
                client,
                request,
                XHttpMethod.GET
            );
            return response;
        }

        /// <summary>
        /// Check a User is in Followings of Current User
        /// </summary>
        /// <param name="tokens">Authentication Tokens</param>
        /// <param name="destUser">a user identifier which represent destination user</param>
        /// <returns>a boolean value</returns>
        public async Task<bool> IsFollowing(
            XTokenResponse tokens,
            string destUser
        )
        {
            //
            // Validate Args ...
            await validationProvider
                .GroupValidationBuilder()
                .AddNotNull(tokens)
                .AddNotEmpty(
                    destUser,
                    tokens.AccessToken
                )
                .ValidateGroupAsync();

            //
            var client = GetRestClient(tokens);

            //
            var request = GetRestRequet(
                XApiAccountEndpoint.IsFollowing,
                @params: new Dictionary<string, string> { { XParam.XDestUser.GetStringValue (), destUser }
                }
            );

            //
            var response = await RunRestRequest<bool>(
                client,
                request,
                XHttpMethod.GET
            );
            return response;
        }

        /// <summary>
        /// Get Specific Following Model
        /// </summary>
        /// <param name="tokens">Authentication Tokens</param>
        /// <param name="destUser">a user identifier which represent destination user</param>
        /// <returns>an instance of <see>XFriendshipFollowing</see></returns>
        public async Task<XFriendshipFollowing> GetFollowing(
            XTokenResponse tokens,
            string destUser
        )
        {
            //
            // Validate Args ...
            await validationProvider
                .GroupValidationBuilder()
                .AddNotNull(tokens)
                .AddNotEmpty(
                    destUser,
                    tokens.AccessToken
                )
                .ValidateGroupAsync();

            //
            var client = GetRestClient(tokens);

            //
            var request = GetRestRequet(
                XApiAccountEndpoint.Following,
                @params: new Dictionary<string, string> { { XParam.XDestUser.GetStringValue (), destUser }
                }
            );

            //
            var response = await RunRestRequest<XFriendshipFollowing>(
                client,
                request,
                XHttpMethod.GET
            );
            return response;
        }

        /// <summary>
        /// Get Following State Relation between Specific User 
        /// and Current User
        /// </summary>
        /// <param name="tokens">Authentication Tokens</param>
        /// <param name="destUser">a user identifier which represent destination user</param>
        /// <returns>an instance of <see>XFriendshipState</see></returns>
        public async Task<XFriendshipState> GetFollowingState(
            XTokenResponse tokens,
            string destUser
        )
        {
            //
            // Validate Args ...
            await validationProvider
                .GroupValidationBuilder()
                .AddNotNull(tokens)
                .AddNotEmpty(
                    destUser,
                    tokens.AccessToken
                )
                .ValidateGroupAsync();

            //
            var client = GetRestClient(tokens);

            //
            var request = GetRestRequet(
                XApiAccountEndpoint.FollowingState,
                @params: new Dictionary<string, string> { { XParam.XDestUser.GetStringValue (), destUser }
                }
            );

            //
            var response = await RunRestRequest<XFriendshipState>(
                client,
                request,
                XHttpMethod.GET
            );
            return response;
        }

        /// <summary>
        /// Get Followings of Current User
        /// </summary>
        /// <param name="tokens">Authentication Tokens</param>
        /// <returns>a collection of <see>XFriendshipFollowing</see></returns>
        public async Task<IEnumerable<XFriendshipFollowing>> GetFollowings(
            XTokenResponse tokens
        )
        {
            //
            // Validate Args ...
            await validationProvider
                .GroupValidationBuilder()
                .AddNotNull(tokens)
                .AddNotEmpty(tokens.AccessToken)
                .ValidateGroupAsync();

            //
            var client = GetRestClient(tokens);

            //
            var request = GetRestRequet(XApiAccountEndpoint.Followings);

            //
            var response = await RunRestRequest<IEnumerable<XFriendshipFollowing>>(
                client,
                request,
                XHttpMethod.GET
            );
            return response;
        }

        /// <summary>
        /// Get All Following List Includes Blocked, Requested and etc 
        /// of Current User
        /// </summary>
        /// <param name="tokens">Authentication Tokens</param>
        /// <returns>a collection of <see>XFriendshipFollowing</see></returns>
        public async Task<IEnumerable<XFriendshipFollowing>> GetAllFollowings(
            XTokenResponse tokens
        )
        {
            //
            // Validate Args ...
            await validationProvider
                .GroupValidationBuilder()
                .AddNotNull(tokens)
                .AddNotEmpty(tokens.AccessToken)
                .ValidateGroupAsync();

            //
            var client = GetRestClient(tokens);

            //
            var request = GetRestRequet(XApiAccountEndpoint.AllFollowings);

            //
            var response = await RunRestRequest<IEnumerable<XFriendshipFollowing>>(
                client,
                request,
                XHttpMethod.GET
            );
            return response;
        }

        /// <summary>
        /// Return Following UserName's List of Current User 
        /// </summary>
        /// <param name="tokens">Authentication Tokens</param>
        /// <returns>a collection of UserNames</returns>
        public async Task<IEnumerable<string>> GetFollowingList(
            XTokenResponse tokens
        )
        {
            //
            // Validate Args ...
            await validationProvider
                .GroupValidationBuilder()
                .AddNotNull(tokens)
                .AddNotEmpty(tokens.AccessToken)
                .ValidateGroupAsync();

            //
            var client = GetRestClient(tokens);

            //
            var request = GetRestRequet(XApiAccountEndpoint.FollowingsList);

            //
            var response = await RunRestRequest<IEnumerable<string>>(
                client,
                request,
                XHttpMethod.GET
            );
            return response;
        }

        /// <summary>
        /// Retrieve All User's Followings based on Query Model ...
        /// </summary>
        /// <param name="query">Query Model Descriptor</param>
        /// <param name="destUser">Dest User for Reading Followers</param>
        /// <param name="tokens">Requester User's Descriptor</param>
        /// <returns></returns>
        public async Task<XQueryResult<XFriendDto>> QueryFollowings(
            XQuery query,
            string destUser,
            XTokenResponse tokens
        )
        {
            //
            // Validate Args ...
            await validationProvider
                .GroupValidationBuilder()
                .AddNotNull(tokens)
                .AddNotEmpty(destUser)
                .AddNotEmpty(tokens.AccessToken)
                .ValidateGroupAsync();

            //
            var client = GetRestClient(tokens);

            //
            var request = GetRestRequet(XApiAccountEndpoint.QueryFollowings);

            //
            // Attach XQuery to Request ...
            request = request.AttachXQuery(query);
            request = request.AttachDestUser(destUser);

            //
            var response = await RunRestRequest<XQueryResult<XFriendDto>>(
                client,
                request,
                XHttpMethod.GET
            );
            return response;
        }
        #endregion
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xIdentityService\Partial\XIdentityProvider+Open.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.InteropServices;
using System.Threading.Tasks;
using MongoDB.Bson;
using xCommons.Constants;
using xCommons.Extensions;
using xExceptions.Constants;
using xHttpService.Constants;
using xIdentityModels.Dtos;
using xIdentityService.Constants;
using xModels.Dtos;

namespace xIdentityService.Providers
{
    public partial class XIdentityProvider
    {
        /// <summary>
        /// Prepare API Based Device to Open Actions ...
        /// </summary>
        /// <returns></returns>
        public  XDeviceDto GetDevice()
        {
            //
            var os = "XSaherElmOS";
            bool isOSX = RuntimeInformation.IsOSPlatform(OSPlatform.OSX);
            bool isLinux = RuntimeInformation.IsOSPlatform(OSPlatform.Linux);
            bool isWindows = RuntimeInformation.IsOSPlatform(OSPlatform.Windows);
            if (isOSX)
            {
                os = "MacOs";
            }
            else if (isLinux)
            {
                os = "Linux";
            }
            else if (isWindows)
            {
                os = "Windows";
            }
            var agent = RuntimeInformation.FrameworkDescription;
            if (agent.IsNullOrEmpty())
            {
                agent = "XSaherElmOSAgent";
            }
            var version = RuntimeInformation.OSArchitecture + ", " + RuntimeInformation.OSDescription;
            if (version.IsNullOrEmpty())
            {
                version = "XSaherElmOSVersion";
            }
            var browser = "XSaherElmBrowser_" + RevisionSecretKey.ToMd5String();

            //
            var result = new XDeviceDto
            {
                Os = os,
                Browser = browser,
                UserAgent = agent,
                OsVersion = version,
                DeviceType = XDeviceType.Desktop,
            };

            //
            return result;
        }

        //
        #region OpenGet ...
        public async Task<XOpenActionInnerDto> OpenGet(
            XOpenActionInnerDto model
        )
        {
            //
            // Validate Args ...
            await validationProvider
                .GroupValidationBuilder()
                .AddNotNull(model)
                .AddNotEmpty(model.Token)
                .AddNotEmpty(model.Payload)
                .ValidateGroupAsync();

            //
            var result = await OpenGet(
                token: model.Token,
                actionRequest: model.Payload
            );

            //
            return result;
        }
        public async Task<XOpenActionInnerDto> OpenGet(
            string token,
            string actionRequest
        )
        {
            //
            // Validate Args ...
            await validationProvider
                .GroupValidationBuilder()
                .AddNotEmpty(token)
                .AddNotEmpty(actionRequest)
                .ValidateGroupAsync();

            //
            // Retrieve Rest Client ...
            var client = GetRestClient();

            //
            // Prepare Rest Request ...
            var request = GetRestRequet(
                XApiAccountEndpoint.Open,
                headers: new Dictionary<string, string>
                {
                    { XAuthentication.TOKEN, token}
                },
                queryStrings: new Dictionary<string, string>
                {
                    { XParam.XRequest.GetStringValue(), actionRequest }
                }
            );

            //
            // Run Request and Retrieve Response ...
            var response = await RunRestRequestByResponse<string>(
                client,
                request,
                XHttpMethod.GET
            );

            //
            // Now we Have to Validate the recieved response ...

            //
            // Read token from Headers ...
            var responseToken = response.Response.Headers
                .First(h => h.Name == XAuthentication.TOKEN).Value.ToString();
            if (responseToken.IsNullOrEmpty())
            {
                XException.ActionFailed.Throw();
            }

            //
            // Decript Recieve Response ...
            var responseJson = response.Model; // SecurityProvider.Decrypt(response.Model);
            if (responseJson.IsNullOrEmpty())
            {
                XException.ActionFailed.Throw();
            }

            //
            var result = new XOpenActionInnerDto
            {
                Token = responseToken,
                Payload = responseJson
            };

            //
            // Retrieve Model and Validate it ...
            var responseModel = responseJson.FromJSON<XOpenActionRequestDto>();
            if (responseModel.IsNull() ||
                responseModel.Payload.IsNullOrEmpty() ||
                responseToken != responseModel.Checksum ||
                responseModel.Timestamp.FromTimestamp().IsExPired())
            {
                XException.ActionFailed.Throw();
            }

            //
            return result;
        }
        #endregion

        //
        #region GetUserInfo ...
        public async Task<XOpenActionUserInfoDto> GetUserInfo(
            XDeviceDto device,
            string userSelectByParam
        )
        {
            //
            // Validate Args ...
            validationProvider.NotNull(device);
            validationProvider.NotEmpty(userSelectByParam);

            //
            // Prepare Open Action Model ...
            var opaModel = new XOpenActionRequestDto
            {
                Device = device,
                Payload = userSelectByParam,
                Action = XOpenActions.GetUserInfo,
                Timestamp = DateTime.UtcNow.AddMinutes(5).ToTimestamp().ToString()
            };
            if (!opaModel.Validate())
            {
                XException.InvalidArgs.Throw();
            }

            //
            // Fill Checksum Filed ...
            var token = opaModel.ToOpenActionToken();
            opaModel.Checksum = token;

            //
            // Prepare Request ...
            var opaJson = opaModel.ToJson();
            var requestString = SecurityProvider.Encrypt(opaJson);

            //
            return await GetUserInfo(
                token: token,
                request: requestString
            );
        }

        public async Task<XOpenActionUserInfoDto> GetUserInfo(
            XOpenActionInnerDto dto
        )
        {
            //
            return await GetUserInfo(
                token: dto.Token,
                request: dto.Payload
            );
        }

        public async Task<XOpenActionUserInfoDto> GetUserInfo(
            string token,
            string request
        )
        {
            //
            // Validate Args ...
            validationProvider.NotEmpty(token);
            validationProvider.NotEmpty(request);

            //
            // Retrieve and Validate Response ...
            var response = await OpenGet(
                token: token,
                actionRequest: request
            );
            if (response.IsNull() ||
                response.Token.IsNullOrEmpty() ||
                response.Payload.IsNullOrEmpty())
            {
                XException.ActionFailed.Throw();
            }

            //
            // Now we Have to Converts Repose Payload to Result Model ...
            // Note that the respose Model's payload here is Decrypted and
            // actually is Json Representation of Result Model ...
            var requestModel = response.Payload.FromJSON<XOpenActionRequestDto>();
            if (requestModel.IsNull())
            {
                XException.ActionFailed.Throw();
            }

            //
            var resultJson = SecurityProvider.Decrypt(requestModel.Payload);
            var result = resultJson.FromJSON<XOpenActionUserInfoDto>();
            if (result.IsNull())
            {
                XException.NotFound.Throw();
            }

            //
            return result;
        }
        #endregion

        //
        #region GetUserInfos ...
        public async Task<IEnumerable<XOpenActionUserInfoDto>> GetUserInfos(
            XDeviceDto device,
            string ids
        )
        {
            //
            // Validate Args ...
            validationProvider.NotNull(device);
            validationProvider.NotEmpty(ids);

            //
            // Prepare Open Action Model ...
            var opaModel = new XOpenActionRequestDto
            {
                Payload = ids,
                Device = device,
                Action = XOpenActions.GetUserInfos,
                Timestamp = DateTime.UtcNow.AddMinutes(5).ToTimestamp().ToString()
            };
            if (!opaModel.Validate())
            {
                XException.InvalidArgs.Throw();
            }

            //
            // Fill Checksum Filed ...
            var token = opaModel.ToOpenActionToken();
            opaModel.Checksum = token;

            //
            // Prepare Request ...
            var opaJson = opaModel.ToJson();
            var requestString = SecurityProvider.Encrypt(opaJson);

            //
            return await GetUserInfos(
                token: token,
                request: requestString
            );
        }

        public async Task<IEnumerable<XOpenActionUserInfoDto>> GetUserInfos(
            XOpenActionInnerDto dto
        )
        {
            //
            return await GetUserInfos(
                token: dto.Token,
                request: dto.Payload
            );
        }

        public async Task<IEnumerable<XOpenActionUserInfoDto>> GetUserInfos(
            string token,
            string request
        )
        {
            //
            // Validate Args ...
            validationProvider.NotEmpty(token);
            validationProvider.NotEmpty(request);

            //
            // Retrieve and Validate Response ...
            var response = await OpenGet(
                token: token,
                actionRequest: request
            );
            if (response.IsNull() ||
                response.Token.IsNullOrEmpty() ||
                response.Payload.IsNullOrEmpty())
            {
                XException.ActionFailed.Throw();
            }

            //
            // Now we Have to Converts Repose Payload to Result Model ...
            // Note that the respose Model's payload here is Decrypted and
            // actually is Json Representation of Result Model ...
            var requestModel = response.Payload.FromJSON<XOpenActionRequestDto>();
            if (requestModel.IsNull())
            {
                XException.ActionFailed.Throw();
            }

            //
            var resultJson = SecurityProvider.Decrypt(requestModel.Payload);
            var result = resultJson.FromJSON<IEnumerable<XOpenActionUserInfoDto>>();
            if (result.IsNull())
            {
                XException.NotFound.Throw();
            }

            //
            return result;
        }
        #endregion
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xIdentityService\Partial\XIdentityProvider+Profile.cs

using System.Collections.Generic;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Http;
using xCommons.Extensions;
using xHttpService.Constants;
using xHttpService.Extensions;
using xIdentityModels.Dtos;
using xIdentityModels.Models;
using xIdentityModels.Navigations;
using xIdentityService.Constants;
using xModels.Dtos;

namespace xIdentityService.Providers {
    public partial class XIdentityProvider {
        //
        #region User Actions ...
        /// <summary>
        /// Retrieve User Names based on UserIds
        /// </summary>
        /// <param name="tokens">Authentication Tokens</param>
        /// <param name="ids">a comma seperated list of UserIds</param>
        /// <returns>a collection of UserNames</returns>
        public async Task<IEnumerable<string>> GetUserNames (
            XTokenResponse tokens,
            string ids
        ) {
            //
            // Validate Args ...
            await validationProvider
                .GroupValidationBuilder ()
                .AddNotNull (tokens)
                .AddNotEmpty (ids, tokens.AccessToken)
                .ValidateGroupAsync ();

            //
            var client = GetRestClient (tokens);
            var request = GetRestRequet (
                XApiAccountEndpoint.GetNames,
                @params : new Dictionary<string, string> { { XParam.XIds.GetStringValue (), ids } }
            );

            //
            var response = await RunRestRequest<IEnumerable<string>> (
                client,
                request,
                XHttpMethod.GET
            );
            return response;
        }

        /// <summary>
        /// get user ids and retrieve corresponding user names
        /// </summary>
        /// <param name="tokens">Authentication Tokens</param>
        /// <param name="model">an instance of <see>XUserNameIdRequest</see> which represent required UserIds collection</param>
        /// <returns>a collection of <see>XUserNameIdResponse</see> instance</returns>
        public async Task<IEnumerable<XUserNameIdResponse>> GetUserNameIds (
            XTokenResponse tokens,
            XUserNameIdRequest model
        ) {
            //
            // Validate Args ...
            await validationProvider
                .GroupValidationBuilder ()
                .AddNotNull (model, tokens)
                .AddNotZeroChilds (model.Ids)
                .AddNotEmpty (tokens.AccessToken)
                .ValidateGroupAsync ();

            //
            var client = GetRestClient (tokens);
            var request = GetRestRequet (XApiAccountEndpoint.GetNameIds);
            request.AddJsonBody (model);

            //
            var response = await RunRestRequest<IEnumerable<XUserNameIdResponse>> (
                client,
                request,
                XHttpMethod.POST
            );
            return response;
        }
        #endregion

        //
        #region Profile Actions ...
        /// <summary>
        /// Get Profile Object of Specific User 
        /// </summary>
        /// <param name="tokens">Authentication Tokens</param>
        /// <param name="userSelectByParam">determine's which user profile must be retrieved</param>
        /// <returns>an instance of <see>XUserProfileDto</see></returns>
        public async Task<XUserProfileDto> GetUserProfile (
            XTokenResponse tokens,
            string userSelectByParam
        ) {
            //
            // Validate Args ...
            await validationProvider
                .GroupValidationBuilder ()
                .AddNotNull (tokens)
                .AddNotEmpty (userSelectByParam, tokens.AccessToken)
                .ValidateGroupAsync ();

            //
            var client = GetRestClient (tokens);

            //
            var request = GetRestRequet (
                XApiAccountEndpoint.GetProfile,
                @params : new Dictionary<string, string> { { XParam.XUserSelectByParam.GetStringValue (), userSelectByParam } }
            );

            //
            var response = await RunRestRequest<XUserProfileDto> (
                client,
                request,
                XHttpMethod.GET
            );
            return response;
        }

        /// <summary>
        /// Retrieve Users Based On Query
        /// </summary>
        /// <param name="tokens">Authentication Tokens</param>
        /// <param name="query">how to filter results based on <see>XQuery</see> structure</param>
        /// <returns>an instance of <see>XQueryResult</see> of <see>XUserProfileDto</see></returns>
        public async Task<XQueryResult<XUserProfileDto>> QueryUsers (
            XTokenResponse tokens,
            XQuery query
        ) {
            //
            // Validate Args ...
            await validationProvider
                .GroupValidationBuilder ()
                .AddNotNull (tokens, query)
                .AddNotEmpty (tokens.AccessToken)
                .ValidateGroupAsync ();

            //
            var client = GetRestClient (tokens);

            //
            var request = GetRestRequet (XApiAccountEndpoint.QueryProfiles);

            //
            // Attach XQuery to Request ...
            request = request.AttachXQuery (query);

            //
            var response = await RunRestRequest<XQueryResult<XUserProfileDto>> (
                client,
                request,
                XHttpMethod.GET
            );
            return response;
        }

        /// <summary>
        /// Retrieve Users Based On Query and Specified role
        /// </summary>
        /// <param name="tokens">Authentication Tokens</param>
        /// <param name="role">an string which represent user role</param>
        /// <param name="query">how to filter results based on <see>XQuery</see> structure</param>
        /// <param name="forceRole">if it's true the user must has exact role, otherwise top level users also listed</param>
        /// <returns>an instance of <see>XQueryResult</see> of <see>XUserProfileDto</see></returns>
        public async Task<XQueryResult<XUserProfileDto>> QueryInRoleUsers (
            XTokenResponse tokens,
            string role,
            XQuery query,
            bool forceRole = false
        ) {
            //
            // Validate Args ...
            await validationProvider
                .GroupValidationBuilder ()
                .AddNotNull (tokens, query)
                .AddNotEmpty (tokens.AccessToken, role)
                .ValidateGroupAsync ();

            //
            var client = GetRestClient (tokens);

            //
            var request = GetRestRequet (
                XApiAccountEndpoint.QueryProfiles,
                headers : new Dictionary<string, string> { { XParam.XRole.GetStringValue (), role },
                    { XParam.XForceRole.GetStringValue (), forceRole.AsHttpParamString () }
                }
            );

            //
            // Attach XQuery to Request ...
            request = request.AttachXQuery (query);

            //
            var response = await RunRestRequest<XQueryResult<XUserProfileDto>> (
                client,
                request,
                XHttpMethod.GET
            );
            return response;
        }

        /// <summary>
        /// Query Specified User's Profile Images
        /// </summary>
        /// <param name="tokens">Authentication Tokens</param>
        /// <param name="userSelectByParam">determine's which user profile must be retrieved</param>
        /// <param name="query">how to filter results based on <see>XQuery</see> structure</param>
        /// <returns>an instance of <see>XQueryResult</see> of <see>XProfileImage</see></returns>
        public async Task<XQueryResult<XProfileImage>> QueryAvatars (
            XTokenResponse tokens,
            string userSelectByParam,
            XQuery query
        ) {
            //
            // Validate Args ...
            await validationProvider
                .GroupValidationBuilder ()
                .AddNotNull (tokens, query)
                .AddNotEmpty (tokens.AccessToken, userSelectByParam)
                .ValidateGroupAsync ();

            //
            var client = GetRestClient (tokens);

            //
            var request = GetRestRequet (
                XApiAccountEndpoint.QueryAvatars,
                @params : new Dictionary<string, string> { { XParam.XUserSelectByParam.GetStringValue (), userSelectByParam }
                }
            );

            //
            // Attach XQuery to Request ...
            request = request.AttachXQuery (query);

            //
            var response = await RunRestRequest<XQueryResult<XProfileImage>> (
                client,
                request,
                XHttpMethod.GET
            );
            return response;
        }

        /// <summary>
        /// Update User Profile based on <see>XProfileUpdateRequest</see> (FirstName/LastName/DateOfBirth)
        /// </summary>
        /// <param name="tokens">Authentication Tokens</param>
        /// <param name="userSelectByParam">determine's which user profile must be retrieved</param>
        /// <param name="model">user update info, an instance of <see>XProfileUpdateRequest</see></param>
        /// <returns>an instance of <see>XUserProfileDto</see></returns>
        public async Task<XUserProfileDto> ProfileUpdateAsync (
            XTokenResponse tokens,
            string userSelectByParam,
            XProfileUpdateRequest model
        ) {
            //
            // Validate Args ...
            await validationProvider
                .GroupValidationBuilder ()
                .AddNotNull (tokens, model)
                .AddNotEmpty (tokens.AccessToken, userSelectByParam)
                .ValidateGroupAsync ();

            //
            var client = GetRestClient (tokens);

            //
            var request = GetRestRequet (
                XApiAccountEndpoint.UpdateProfile,
                @params : new Dictionary<string, string> { { XParam.XUserSelectByParam.GetStringValue (), userSelectByParam }
                }
            );
            request.AddJsonBody (model);

            //
            var response = await RunRestRequest<XUserProfileDto> (
                client,
                request,
                XHttpMethod.POST
            );
            return response;
        }

        /// <summary>
        /// Update a User Profile based on <see>XProfileUpdateRequest</see> Full
        /// </summary>
        /// <param name="tokens">Authentication Tokens</param>
        /// <param name="userSelectByParam">determine's which user profile must be retrieved</param>
        /// <param name="model">user update info, an instance of <see>XProfileUpdateRequest</see></param>
        /// <returns>an instance of <see>XUserProfileDto</see></returns>
        public async Task<XUserProfileDto> FullProfileUpdateAsync (
            XTokenResponse tokens,
            string userSelectByParam,
            XProfileUpdateRequest model
        ) {
            //
            // Validate Args ...
            await validationProvider
                .GroupValidationBuilder ()
                .AddNotNull (tokens, model)
                .AddNotEmpty (tokens.AccessToken, userSelectByParam)
                .ValidateGroupAsync ();

            //
            var client = GetRestClient (tokens);

            //
            var request = GetRestRequet (
                XApiAccountEndpoint.FullUpdateProfile,
                @params : new Dictionary<string, string> { { XParam.XUserSelectByParam.GetStringValue (), userSelectByParam }
                }
            );
            request.AddJsonBody (model);

            //
            var response = await RunRestRequest<XUserProfileDto> (
                client,
                request,
                XHttpMethod.POST
            );
            return response;
        }

        /// <summary>
        /// Add a New Profile Image
        /// </summary>
        /// <param name="tokens">Authentication Tokens</param>
        /// <param name="file">an specific File to upload, <see>IFormFile</see></param>
        /// <returns>an instance of <see>XUserProfileDto</see></returns>
        public async Task<XUserProfileDto> AddAvatar (
            XTokenResponse tokens,
            IFormFile file
        ) {
            //
            // Validate Args ...
            await validationProvider
                .GroupValidationBuilder ()
                .AddNotNull (tokens, file)
                .AddNotEmpty (tokens.AccessToken)
                .ValidateGroupAsync ();

            //
            var client = GetRestClient (tokens);

            //
            var request = GetRestRequet (XApiAccountEndpoint.AddAvatar);
            request.AlwaysMultipartFormData = true;
            request.AddFileBytes (
                XParam.XFile.GetStringValue (),
                file.ToByteArray (),
                file.FileName,
                file.ContentType
            );

            //
            var response = await RunRestRequest<XUserProfileDto> (
                client,
                request,
                XHttpMethod.POST
            );
            return response;
        }

        /// <summary>
        /// Add a New Collection of Profile Images
        /// </summary>
        /// <param name="tokens">Authentication Tokens</param>
        /// <param name="files">a collection of Files to upload, <see>IFormFileCollection</see></param>
        /// <returns>an instance of <see>XUserProfileDto</see></returns>
        public async Task<XUserProfileDto> AddAvatars (
            XTokenResponse tokens,
            IFormFileCollection files
        ) {
            //
            // Validate Args ...
            await validationProvider
                .GroupValidationBuilder ()
                .AddNotNull (tokens)
                .AddNotZeroChilds (files)
                .AddNotEmpty (tokens.AccessToken)
                .ValidateGroupAsync ();

            //
            var client = GetRestClient (tokens);

            //
            var request = GetRestRequet (XApiAccountEndpoint.AddAvatars);
            request.AlwaysMultipartFormData = true;

            //
            // Add Files ...
            foreach (var file in files) {
                //
                // Add Single file ...
                request.AddFileBytes (
                    XParam.XFiles.GetStringValue (),
                    file.ToByteArray (),
                    file.FileName,
                    file.ContentType
                );
            }

            //
            var response = await RunRestRequest<XUserProfileDto> (
                client,
                request,
                XHttpMethod.POST
            );
            return response;
        }

        /// <summary>
        /// set Specified Profile Image as Avatar
        /// </summary>
        /// <param name="tokens">Authentication Tokens</param>
        /// <param name="id">an integer which reperesent AvatarId to set as current Avatar</param>
        /// <returns>an instance of <see>XUserProfileDto</see></returns>
        public async Task<XUserProfileDto> SetAvatar (
            XTokenResponse tokens,
            int id
        ) {
            //
            // Validate Args ...
            id.ValidateIntId ();

            //
            // Validate Args ...
            await validationProvider
                .GroupValidationBuilder ()
                .AddNotNull (tokens)
                .AddNotEmpty (tokens.AccessToken)
                .ValidateGroupAsync ();

            //
            var client = GetRestClient (tokens);

            //
            var request = GetRestRequet (
                XApiAccountEndpoint.SetAvatar,
                @params : new Dictionary<string, string> { { XParam.XId.GetStringValue (), id.ToString () }
                }
            );

            //
            var response = await RunRestRequest<XUserProfileDto> (
                client,
                request,
                XHttpMethod.POST
            );
            return response;
        }

        /// <summary>
        /// Remove Profile Images
        /// </summary>
        /// <param name="tokens">Authentication Tokens</param>
        /// <param name="avatarIds">a comma seperated list of avatarIds to remove</param>
        /// <returns>an instance of <see>XUserProfileDto</see></returns>
        public async Task<XUserProfileDto> RemoveAvatars (
            XTokenResponse tokens,
            string avatarIds
        ) {
            //
            // Validate Args ...
            await validationProvider
                .GroupValidationBuilder ()
                .AddNotNull (tokens)
                .AddNotEmpty (avatarIds, tokens.AccessToken)
                .ValidateGroupAsync ();

            //
            var client = GetRestClient (tokens);

            //
            var request = GetRestRequet (
                XApiAccountEndpoint.RemoveAvatars,
                @params : new Dictionary<string, string> { { XParam.XIds.GetStringValue (), avatarIds }
                }
            );

            //
            var response = await RunRestRequest<XUserProfileDto> (
                client,
                request,
                XHttpMethod.DELETE
            );
            return response;
        }
        #endregion
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xIdentityService\Partial\XIdentityProvider+Registration.cs

using System.Collections.Generic;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Http;
using xCommons.Extensions;
using xExceptions.Constants;
using xHttpService.Constants;
using xIdentityModels.Constants;
using xIdentityModels.Extensions;
using xIdentityModels.Models;
using xIdentityService.Constants;

namespace xIdentityService.Providers {
    public partial class XIdentityProvider {
        //
        #region Registration ...
        /// <summary>
        /// Check a User Selector is Available for Registration or Not
        /// </summary>
        /// <param name="userSelectByParam">an string value which reperesent a user</param>
        /// <returns>a boolean value</returns>
        public async Task<bool> CanRegister (string userSelectByParam) {
            //
            // Validate ARgs ...
            validationProvider.NotEmpty (userSelectByParam);

            //
            var client = GetRestClient ();

            //
            // Check Endpoint ...
            var endpoint = XApiAccountEndpoint.CanRegisterUserName;
            var @params = new Dictionary<string, string> { { XParam.XUserName.GetStringValue (), userSelectByParam } };

            //
            // Check UserSelectByType ...
            var type = userSelectByParam.GetUserSelectByType ();
            switch (type) {
                //
                case XUserSelectBy.Username:
                    break;

                    //
                case XUserSelectBy.MobileNumber:
                    //
                    endpoint = XApiAccountEndpoint.CanRegisterMobileNumber;
                    @params = new Dictionary<string, string> { { XParam.XMobileNumber.GetStringValue (), userSelectByParam } };
                    break;

                    //
                case XUserSelectBy.Email:
                    //
                    endpoint = XApiAccountEndpoint.CanRegisterEmail;
                    @params = new Dictionary<string, string> { { XParam.XEmail.GetStringValue (), userSelectByParam } };
                    break;

                    //
                default:
                    throw XException.InvalidData.ToException ();
            }

            //
            var request = GetRestRequet (
                endpoint,
                @params: @params
            );

            //
            var response = await RunRestRequest<bool> (
                client,
                request,
                XHttpMethod.GET
            );
            return response;
        }

        /// <summary>
        /// Invite a User to Register on Dashboard
        /// </summary>
        /// <param name="tokens">Authentication Tokens</param>
        /// <param name="model">an instance of <see>XActionRequest</see> class which provider requirement for action</param>
        /// <returns>an instance of <see>XActionResponse</see></returns>
        public async Task<XActionResponse> InviteUser (
            XTokenResponse tokens,
            XActionRequest model
        ) {
            //
            // Validate Args ...
            await validationProvider
                .GroupValidationBuilder ()
                .AddNotNull (
                    tokens,
                    model,
                    model.Device)
                .AddNotEmpty (
                    tokens.AccessToken,
                    model.Lang,
                    model.Email,
                    model.ReturnUrl)
                .AddEmailAddress (model.Email)
                .ValidateGroupAsync ();

            //
            var client = GetRestClient (tokens);

            //
            var request = GetRestRequet (XApiAccountEndpoint.InviteUser);
            request.AddJsonBody (model);

            //
            var response = await RunRestRequest<XActionResponse> (
                client,
                request,
                XHttpMethod.POST
            );
            return response;
        }

        /// <summary>
        /// Recieve some Basic Informations and Start Registration Proccess
        /// if they Valid 
        /// 
        /// Registration Proccess Starts with Invoking this Action
        /// </summary>
        /// <param name="model">an instance of <see>XActionRequest</see> class which provider requirement for action</param>
        /// <returns>an instance of <see>XActionResponse</see></returns>
        public async Task<XActionResponse> RequestRegistration (
            XActionRequest model
        ) {
            //
            // Validate Args ...
            await validationProvider
                .GroupValidationBuilder ()
                .AddNotNull (
                    model,
                    model.Device,
                    model.DateOfBirth)
                .AddNotEmpty (
                    model.Lang,
                    model.FirstName,
                    model.LastName)
                .ValidateGroupAsync ();

            //
            var client = GetRestClient ();

            //
            var request = GetRestRequet (XApiAccountEndpoint.RequestRegistration);
            request.AddJsonBody (model);

            //
            var response = await RunRestRequest<XActionResponse> (
                client,
                request,
                XHttpMethod.POST
            );
            return response;
        }

        /// <summary>
        /// Add User Account Informations
        /// </summary>
        /// <param name="model">an instance of <see>XActionRequest</see> class which provider requirement for action</param>
        /// <returns>an instance of <see>XActionResponse</see></returns>
        public async Task<XActionResponse> AddAccountInfo (
            XActionRequest model
        ) {
            //
            // Validate Args ...
            await validationProvider
                .GroupValidationBuilder ()
                .AddNotNull (
                    model,
                    model.Device)
                .AddNotEmpty (
                    model.Lang,
                    model.UserName,
                    model.Password,
                    model.ActionToken)
                .ValidateGroupAsync ();

            //
            var client = GetRestClient ();

            //
            var request = GetRestRequet (XApiAccountEndpoint.AddAccountInfo);
            request.AddJsonBody (model);

            //
            var response = await RunRestRequest<XActionResponse> (
                client,
                request,
                XHttpMethod.POST
            );
            return response;
        }

        /// <summary>
        /// Upload and Attach a Profile Image for User. this is an Optional Step
        /// </summary>
        /// <param name="actionToken">user's requested action token</param>
        /// <param name="file">an instance of <see>IFormFile</see> for user's Avatar</param>
        /// <returns>an instance of <see>XActionResponse</see></returns>
        public async Task<XActionResponse> AttachProfileImage (
            string actionToken,
            IFormFile file
        ) {
            //
            // Validate Args ...
            await validationProvider
                .GroupValidationBuilder ()
                .AddNotNull (file)
                .AddNotEmpty (actionToken)
                .ValidateGroupAsync ();

            //
            var client = GetRestClient ();

            //
            var request = GetRestRequet (XApiAccountEndpoint.AttachProfileImage);

            //
            // Prepare Request Data ...
            request.AddParameter (XParam.XActionToken.GetStringValue (), actionToken);
            request.AddFileBytes (
                XParam.XFile.GetStringValue (),
                file.ToByteArray (),
                file.FileName,
                file.ContentType
            );

            //
            var response = await RunRestRequest<XActionResponse> (
                client,
                request,
                XHttpMethod.POST
            );
            return response;
        }

        /// <summary>
        /// Finish Registrationn Proccess 
        /// </summary>
        /// <param name="model">an instance of <see>XActionRequest</see> class which provider requirement for action</param>
        /// <returns></returns>
        public async Task FinishRegistration (XActionRequest model) {
            //
            // Validate Args ...
            await validationProvider
                .GroupValidationBuilder ()
                .AddNotEmpty (
                    model.Lang,
                    model.Password,
                    model.ReturnUrl)
                .AddNotNull (model.Device)
                .AddUrl (model.ReturnUrl)
                .ValidateGroupAsync ();

            //
            // Create Http Client ...
            var client = GetRestClient ();

            //
            // Create Request ...
            var request = GetRestRequet (XApiAccountEndpoint.FinishRegistration);

            //
            // Prepare Request Data ...
            request.AddJsonBody (model);

            //
            var response = await RunRestRequest<object> (
                client,
                request,
                XHttpMethod.POST
            );
        }

        /// <summary>
        /// Check User is Confirmed Email or not
        /// </summary>
        /// <param name="tokens">Authentication Tokens</param>
        /// <param name="userSelectByParam">an string value which reperesent a user</param>
        /// <returns>a boolean value</returns>
        public async Task<bool> IsConfirmedEmail (
            XTokenResponse tokens,
            string userSelectByParam
        ) {
            //
            // Validate Args ...
            await validationProvider
                .GroupValidationBuilder ()
                .AddNotNull (tokens)
                .AddNotEmpty (
                    tokens.AccessToken,
                    userSelectByParam)
                .ValidateGroupAsync ();

            //
            var client = GetRestClient (tokens);

            //
            var request = GetRestRequet (XApiAccountEndpoint.IsConfirmedEmail);

            //
            var response = await RunRestRequest<bool> (
                client,
                request,
                XHttpMethod.GET
            );
            return response;
        }

        /// <summary>
        /// Check User is Confirmed Mobile or not
        /// </summary>
        /// <param name="tokens">Authentication Tokens</param>
        /// <param name="userSelectByParam">an string value which reperesent a user</param>
        /// <returns>a boolean value</returns>
        public async Task<bool> IsConfirmedMobile (
            XTokenResponse tokens,
            string userSelectByParam
        ) {
            //
            // Validate Args ...
            await validationProvider
                .GroupValidationBuilder ()
                .AddNotNull (tokens)
                .AddNotEmpty (
                    tokens.AccessToken,
                    userSelectByParam)
                .ValidateGroupAsync ();

            //
            var client = GetRestClient (tokens);

            //
            var request = GetRestRequet (XApiAccountEndpoint.IsConfirmedMobile);

            //
            var response = await RunRestRequest<bool> (
                client,
                request,
                XHttpMethod.GET
            );
            return response;
        }

        /// <summary>
        /// Request Registration Confirm
        /// </summary>
        /// <param name="model">an instance of <see>XActionRequest</see> class which provider requirement for action</param>
        /// <returns></returns>
        public async Task RequestConfirmRegistration (XActionRequest model) {
            //
            // Validate Args ...
            await validationProvider
                .GroupValidationBuilder ()
                .AddNotEmpty (
                    model.Lang,
                    model.Password,
                    model.ReturnUrl)
                .AddNotNull (model.Device)
                .AddUrl (model.ReturnUrl)
                .ValidateGroupAsync ();

            //
            // Get UserSelect By Param ...
            var userSelectByParam = model.GetUserSelectByParam ();
            validationProvider.NotEmpty (userSelectByParam);

            //
            var client = GetRestClient ();

            //
            var request = GetRestRequet (XApiAccountEndpoint.RequestConfirmRegistration);
            request.AddJsonBody (model);

            //
            var response = await RunRestRequest<object> (
                client,
                request,
                XHttpMethod.POST
            );
        }

        /// <summary>
        /// Confirm Registration
        /// </summary>
        /// <param name="model">an instance of <see>XActionRequest</see> class which provider requirement for action</param>
        /// <returns></returns>
        public async Task ConfirmRegistration (
            XActionRequest model
        ) {
            //
            // Validate Args ...
            await validationProvider
                .GroupValidationBuilder ()
                .AddNotEmpty (
                    model.Lang,
                    model.ActionToken,
                    model.ReturnUrl
                )
                .AddNotNull (model.Device)
                .ValidateGroupAsync ();

            //
            var client = GetRestClient ();

            //
            var request = GetRestRequet (XApiAccountEndpoint.ConfirmRegistration);
            request.AddJsonBody (model);

            //
            var response = await RunRestRequest<object> (
                client,
                request,
                XHttpMethod.POST
            );
        }

        /// <summary>
        /// Request For Mobile Number Change/Confirm 
        /// </summary>
        /// <param name="model">an instance of <see>XActionRequest</see> class which provider requirement for action</param>
        /// <returns>an instance of <see>XActionResponse</see></returns>
        public async Task<XActionResponse> RequestConfirmMobile (XActionRequest model) {
            //
            // Validate Args ...
            await validationProvider
                .GroupValidationBuilder ()
                .AddNotEmpty (
                    model.Lang,
                    model.Password,
                    model.MobileNumber
                )
                .AddNotNull (model.Device)
                .AddMobileNumber (model.MobileNumber)
                .ValidateGroupAsync ();

            //
            // Get UserSelect By Param ...
            var userSelectByParam = GetUserSelectByParam (
                model,
                excludes : new List<XUserSelectBy> {
                    XUserSelectBy.Email,
                    XUserSelectBy.MobileNumber
                });

            //
            var client = GetRestClient ();

            //
            var request = GetRestRequet (XApiAccountEndpoint.RequestConfirmMobile);
            request.AddJsonBody (model);

            //
            var response = await RunRestRequest<XActionResponse> (
                client,
                request,
                XHttpMethod.POST
            );
            return response;
        }

        /// <summary>
        /// Confirm Requested Mobile Number
        /// </summary>
        /// <param name="model">an instance of <see>XActionRequest</see> class which provider requirement for action</param>
        /// <returns>an instance of <see>XActionResponse</see></returns>
        public async Task<XActionResponse> ConfirmMobileNumber (XActionRequest model) {
            //
            // Validate Args ...
            await validationProvider
                .GroupValidationBuilder ()
                .AddNotEmpty (
                    model.Lang,
                    model.ActionToken,
                    model.MobileVerificationCode
                )
                .AddNotNull (model.Device)
                .ValidateGroupAsync ();

            //
            var client = GetRestClient ();

            //
            var request = GetRestRequet (XApiAccountEndpoint.ConfirmMobileNumber);
            request.AddJsonBody (model);

            //
            var response = await RunRestRequest<XActionResponse> (
                client,
                request,
                XHttpMethod.POST
            );
            return response;
        }

        /// <summary>
        /// Request For Email Address Change/Confirm 
        /// </summary>
        /// <param name="model">an instance of <see>XActionRequest</see> class which provider requirement for action</param>
        /// <returns>an instance of <see>XActionResponse</see></returns>
        public async Task<XActionResponse> RequestConfirmEmail (XActionRequest model) {
            //
            // Validate Args ...
            await validationProvider
                .GroupValidationBuilder ()
                .AddNotEmpty (
                    model.Lang,
                    model.Email,
                    model.Password)
                .AddNotNull (model.Device)
                .AddEmailAddress (model.Email)
                .ValidateGroupAsync ();

            //
            // Get UserSelect By Param ...
            var userSelectByParam = GetUserSelectByParam (
                model,
                excludes : new List<XUserSelectBy> {
                    XUserSelectBy.Email,
                    XUserSelectBy.MobileNumber
                });

            //
            var client = GetRestClient ();

            //
            var request = GetRestRequet (XApiAccountEndpoint.RequestConfirmEmail);
            request.AddJsonBody (model);

            //
            var response = await RunRestRequest<XActionResponse> (
                client,
                request,
                XHttpMethod.POST
            );
            return response;
        }

        /// <summary>
        /// Confirm Requested Email Address
        /// </summary>
        /// <param name="model">an instance of <see>XActionRequest</see> class which provider requirement for action</param>
        /// <returns>an instance of <see>XActionResponse</see></returns>
        public async Task<XActionResponse> ConfirmEmailAddress (XActionRequest model) {
            //
            // Validate Args ...
            await validationProvider
                .GroupValidationBuilder ()
                .AddNotEmpty (
                    model.Lang,
                    model.ActionToken,
                    model.EmailVerificationCode
                )
                .AddNotNull (model.Device)
                .ValidateGroupAsync ();

            //
            var client = GetRestClient ();

            //
            var request = GetRestRequet (XApiAccountEndpoint.ConfirmEmailAddress);
            request.AddJsonBody (model);

            //
            var response = await RunRestRequest<XActionResponse> (
                client,
                request,
                XHttpMethod.POST
            );
            return response;
        }

        /// <summary>
        /// Request Reset Password Action
        /// </summary>
        /// <param name="model">an instance of <see>XActionRequest</see> class which provider requirement for action</param>
        /// <returns>an instance of <see>XActionResponse</see></returns>
        public async Task<XActionResponse> RequestResetPassword (XActionRequest model) {
            //
            // Validate Args ...
            await validationProvider
                .GroupValidationBuilder ()
                .AddNotEmpty (
                    model.Lang,
                    model.ReturnUrl)
                .AddNotNull (model.Device)
                .AddUrl (model.ReturnUrl)
                .ValidateGroupAsync ();

            //
            // Get UserSelect By Param ...
            var userSelectByParam = GetUserSelectByParam (
                model,
                excludes : new List<XUserSelectBy> {
                    XUserSelectBy.Email,
                    XUserSelectBy.MobileNumber
                });

            //
            var client = GetRestClient ();

            //
            var request = GetRestRequet (XApiAccountEndpoint.RequestResetPassword);
            request.AddJsonBody (model);

            //
            var response = await RunRestRequest<XActionResponse> (
                client,
                request,
                XHttpMethod.POST
            );
            return response;
        }

        /// <summary>
        /// Reset a User's Password
        /// </summary>
        /// <param name="model">an instance of <see>XActionRequest</see> class which provider requirement for action</param>
        /// <returns></returns>
        public async Task ResetPassword (XActionRequest model) {
            //
            // Validate Args ...
            await validationProvider
                .GroupValidationBuilder ()
                .AddNotNull (model)
                .AddNotEmpty (
                    model.Lang,
                    model.ActionToken,
                    model.NewPassword,
                    model.ReturnUrl)
                .AddNotNull (model.Device)
                .ValidateGroupAsync ();

            //
            var client = GetRestClient ();

            //
            var request = GetRestRequet (XApiAccountEndpoint.ResetPassword);
            request.AddJsonBody (model);

            //
            var response = await RunRestRequest<object> (
                client,
                request,
                XHttpMethod.POST
            );
        }
        #endregion
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xIdentityService\Partial\XIdentityProvider+Search.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using xHttpService.Constants;
using xHttpService.Extensions;
using xIdentityModels.Dtos;
using xIdentityModels.Models;
using xIdentityService.Constants;
using xModels.Dtos;

namespace xIdentityService.Providers
{
    public partial class XIdentityProvider
    {
        //
        #region Actions ...
        /// <summary>
        /// Query Open To Search User Profiles ...
        /// </summary>
        /// <param name="tokens">requested user's identifiers</param>
        /// <param name="query">how to filter results based on <see>XQuery</see> structure</param>
        /// <returns>an instance of <see>XQueryResult</see> of <see>XUserProfileDto</see></returns>
        public async Task<XQueryResult<XUserProfileDto>> QueryOpenToSearchUsers(
            XTokenResponse tokens,
            XQuery query
        )
        {
            //
            // Validate Args ...
            await validationProvider
                .GroupValidationBuilder()
                .AddNotNull(tokens, query)
                .AddNotEmpty(tokens.AccessToken)
                .ValidateGroupAsync();

            //
            var client = GetRestClient(tokens);

            //
            var request = GetRestRequet(XApiAccountEndpoint.QueryOpenToSearchProfiles);

            //
            // Attach XQuery to Request ...
            request = request.AttachXQuery(query);

            //
            var response = await RunRestRequest<XQueryResult<XUserProfileDto>>(
                client,
                request,
                XHttpMethod.GET
            );
            return response;
        }
        #endregion
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xIdentityService\Providers\XBaseIdentityHttpProvider.cs

using System;
using System.IO;
using System.Collections.Generic;
using System.Linq;
using System.Net.Http;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.Extensions.Logging;
using RestSharp;
using RestSharp.Authenticators;
using xCommons.Constants;
using xCommons.Extensions;
using xCommons.Providers;
using xExceptions.Constants;
using xHttpService.Constants;
using xIdentityModels.Constants;
using xIdentityModels.Extensions;
using xIdentityModels.Models;
using xIdentityService.Constants;
using xIdentityService.Interfaces;
using xIdentityService.Models;
using xIdentityService.Extensions;
using System.Diagnostics.Tracing;
using MySqlX.XDevAPI.Common;

namespace xIdentityService.Providers
{
    /// <summary>
    /// an abstraction Implementation for Identity Provided Http Based Services ...
    /// </summary>
    public abstract class XBaseIdentityHttpProvider : IXBaseIdentityHttpProvider
    {
        /// <summary>
        /// Client Base Url ...
        /// </summary>
        /// <value></value>
        public string BaseUrl { get; }

        /// <summary>
        /// Logger ...
        /// </summary>
        /// <value></value>
        public ILogger Logger { get; }

        /// <summary>
        /// Powered Value ...
        /// </summary>
        /// <value></value>
        public string XPoweredValue { get; }

        /// <summary>
        /// Default Client Timeout ...
        /// </summary>
        /// <value></value>
        public int DefaultClientTimeout { get; }

        /// <summary>
        /// Default Buffering Chunk Size ...
        /// </summary>
        /// <value></value>
        public int DefaultBufferingChunckSize { get; }

        /// <summary>
        /// Validation Provider ...
        /// </summary>
        /// <value></value>
        public XValidationProvider ValidationProvider { get; }

        /// <summary>
        /// Token Provider ...
        /// </summary>
        private readonly IXTokenProvider tokenProvider;

        /// <summary>
        /// Identity Provider ...
        /// </summary>
        private readonly IXIdentityProvider identityProvider;

        public XBaseIdentityHttpProvider(
            string baseUrl,
            ILogger logger,
            string poweredValue,
            int defaultClientTimeout,
            IXTokenProvider tokenProvider,
            IXIdentityProvider identityProvider,
            XValidationProvider validationProvider,
            int defaultBufferingChunckSize = 8192
        )
        {
            //
            Logger = logger;
            BaseUrl = baseUrl;
            XPoweredValue = poweredValue;
            this.tokenProvider = tokenProvider;
            ValidationProvider = validationProvider;
            this.identityProvider = identityProvider;
            DefaultClientTimeout = defaultClientTimeout;
            DefaultBufferingChunckSize = defaultBufferingChunckSize;
        }

        //
        #region Tools ...
        /// <summary>
        /// Get an Instance of Http Client 
        /// </summary>
        /// <returns></returns>
        public HttpClient GetHttpClient(XTokenResponse tokens = null)
        {
            //
            HttpClient httpClient = null;

            //
            // httpClient = new HttpClient ();
            var httpClientHandler = new HttpClientHandler()
            {
                ServerCertificateCustomValidationCallback = (sender, cert, chain, sslPolicyErrors) =>
                {
                    //
                    Logger.LogInformation(
                        $"XSSL Handler: {Environment.NewLine}, sender: {sender}, {Environment.NewLine} cert: {cert}, {Environment.NewLine} chain: {chain}, {Environment.NewLine} sslPolicyErrors: {sslPolicyErrors}"
                    );

                    //
                    return true;
                },
                ClientCertificateOptions = ClientCertificateOption.Manual,
            };
            httpClient = new HttpClient(httpClientHandler);

            //
            // Set Authenticator ...
            if (!tokens.IsNull() &&
                !tokens.AccessToken.IsNullOrEmpty())
            {
                //
                httpClient.DefaultRequestHeaders
                    .Add(
                        XAuthorization.Header,
                        $"{XAuthentication.BEARER} {tokens.AccessToken}");
            }

            //
            // Refresh Token ...
            if (!tokens.IsNull() &&
                !tokens.RefreshToken.IsNullOrEmpty())
            {
                //
                httpClient.DefaultRequestHeaders
                    .Add(
                        XAuthorization.RefreshToken,
                        tokens.RefreshToken);
            }

            //
            // ExpiresAt ...
            if (!tokens.IsNull() &&
                tokens.ExpiresAt > 0)
            {
                //
                httpClient.DefaultRequestHeaders
                    .Add(
                        XAuthorization.ExpiresAt,
                        tokens.ExpiresAt.AsHttpParamString());
            }

            //
            // Set Default Timeout ...
            httpClient.Timeout = TimeSpan.FromSeconds(DefaultClientTimeout == -1 ? 10000 : DefaultClientTimeout);

            //
            return httpClient;
        }
        public HttpClient GetHttpClient(XUserClaimsInfoDto userInfo = null)
        {
            //
            XTokenResponse tokens = ToTokenResponse(userInfo);

            //
            return GetHttpClient(tokens);
        }

        /// <summary>
        /// Get an Instance of RestClient
        /// </summary>
        /// <returns></returns>
        public RestClient GetRestClient(XTokenResponse tokens = null)
        {
            //
            var client = new RestClient(BaseUrl);

            //
            // Set Authenticator ...
            if (!tokens.IsNull() &&
                !tokens.AccessToken.IsNullOrEmpty())
            {
                client.Authenticator = new JwtAuthenticator(tokens.AccessToken);
            }

            //
            // Refresh Token ...
            if (!tokens.IsNull() &&
                !tokens.RefreshToken.IsNullOrEmpty())
            {
                client.AddDefaultHeader(XAuthorization.RefreshToken, tokens.RefreshToken);
            }

            //
            // ExpiresAt ...
            if (!tokens.IsNull() &&
                tokens.ExpiresAt > 0)
            {
                client.AddDefaultHeader(XAuthorization.ExpiresAt, tokens.ExpiresAt.AsHttpParamString());
            }

            //
            // Set Default Timeout ...
            client.Timeout = DefaultClientTimeout;

            //
            // SSL Validation Handler ...
            client.RemoteCertificateValidationCallback = (sender, cert, chain, sslPolicyErrors) =>
            {
                //
                Logger.LogInformation(
                    $"XSSL Handler: {Environment.NewLine}, sender: {sender}, {Environment.NewLine} cert: {cert}, {Environment.NewLine} chain: {chain}, {Environment.NewLine} sslPolicyErrors: {sslPolicyErrors}"
                );

                //
                return true;
            };

            //
            return client;
        }
        public RestClient GetRestClient(XUserClaimsInfoDto userInfo = null)
        {
            //
            XTokenResponse tokens = ToTokenResponse(userInfo);

            //
            return GetRestClient(tokens);
        }

        /// <summary>
        /// Get an Instance of RestRequest 
        /// </summary>
        /// <param name="endpoint"></param>
        /// <param name="addXPoweredValue"></param>
        /// <param name=""></param>
        /// <param name="headers"></param>
        /// <param name="queryStrings"></param>
        /// <returns></returns>
        public RestRequest GetRestRequet(
            Enum endpoint,
            bool addXPoweredValue = true,
            IDictionary<string, string> @params = null,
            IDictionary<string, string> headers = null,
            IDictionary<string, string> queryStrings = null
        )
        {
            //
            var url = PrepareUrl(
                @params: @params,
                endpoint: endpoint,
                queryStrings: queryStrings
            );

            //
            // Create request ...
            var request = new RestRequest(url, DataFormat.Json);

            //
            if (addXPoweredValue)
            {
                request.AddHeader(XAuthorization.XPoweredBy, XPoweredValue);
            }

            //
            // Add Headers to request ...
            if (!headers.IsNull() && headers.Count > 0)
            {
                //
                var enumerator = headers.GetEnumerator();
                while (enumerator.MoveNext())
                {
                    //
                    var item = enumerator.Current;
                    request.AddHeader(item.Key, item.Value);
                }
            }

            //
            return request;
        }

        /// <summary>
        /// Handle Call Specific Request and retrieve Response
        /// </summary>
        /// <param name="client"></param>
        /// <param name="request"></param>
        /// <param name="method"></param>
        /// <param name="supportRefreshingTokens"></param>
        /// <param name="cancellationToken"></param>
        /// <typeparam name="T"></typeparam>
        /// <returns></returns>
        public async Task<T> RunRestRequest<T>(
            RestClient client,
            RestRequest request,
            XHttpMethod method,
            bool supportRefreshingTokens = true,
            CancellationToken cancellationToken = default
        )
        {
            //
            var response = await Task.Run(async () =>
            {
                //
                IRestResponse resp = null;

                //
                // Call Endpoint Service using Specified Method ...
                switch (method)
                {
                    //
                    // Get ...
                    case XHttpMethod.GET:
                        resp = client.Get(request);
                        break;

                    //
                    // Put ...
                    case XHttpMethod.PUT:
                        resp = client.Put(request);
                        break;

                    //
                    // Post ...
                    case XHttpMethod.POST:
                        resp = client.Post(request);
                        break;

                    //
                    // Delete ...
                    case XHttpMethod.DELETE:
                        resp = client.Delete(request);
                        break;
                }

                //
                if (!resp.IsSuccessful)
                {
                    //
                    // Log Exception ...
                    Logger.LogError($"Error: {resp.ErrorMessage}");
                    Logger.LogError($"Exception: {resp.ErrorException.ToJSON()}");
                    if (!resp.ErrorMessage.IsNullOrEmpty() &&
                        resp.ErrorMessage.Contains("timed out"))
                    {
                        XException.Timeout.Throw();
                    }

                    //
                    // TODO: Check UnAuthorized Status here for
                    // Refresh Tokens or Issue Correct Exception ...
                    if (supportRefreshingTokens &&
                        resp.StatusCode == System.Net.HttpStatusCode.Unauthorized)
                    {
                        //
                        var isRefreshed = request.Parameters.Any(rp =>
                            rp.Name == XParam.XIsRefreshed.GetStringValue() &&
                            rp.Value.ToString().ToNormalString() == true.ToJSON());

                        //
                        Logger.LogInformation($"isRefreshed: {isRefreshed}");

                        //
                        // Get Access Token ...
                        XTokenResponse tokens = null;
                        var accessToken = request.Parameters.FirstOrDefault(rp =>
                            rp.Name.ToNormalString() == XAuthorization.Header.ToNormalString()).Value.ToString();
                        if (!accessToken.IsNullOrEmpty())
                        {
                            //
                            accessToken = accessToken.Replace(XAuthorization.TokenIdentifier, "");

                            //
                            if (!accessToken.IsNullOrEmpty())
                            {
                                tokens = await tokenProvider.RetrieveToken(accessToken);
                            }
                        }

                        //
                        // Refresh Token and then re do request ...
                        if (!isRefreshed &&
                            !accessToken.IsNullOrEmpty() &&
                            !tokens.IsNull() &&
                            tokens.IsRefreshable())
                        {
                            //
                            request.AddHeader(XParam.XIsRefreshed.GetStringValue(), true.ToJSON());

                            //
                            // Refreshe Tokens ...
                            var refreshedTokens = await identityProvider
                                .RefreshTokens(tokens);

                            //
                            // Renew Rest Client with Refreshed Tokens ...
                            var timeout = client.Timeout;
                            client = GetRestClient(refreshedTokens);
                            client.Timeout = Timeout.Infinite;

                            //
                            // Do Request Again using renew Client ...
                            return await RunRestRequest<T>(
                                client: client,
                                request: request,
                                method: method);
                        }
                    }

                    //
                    var ex = resp.Content.ToXError();
                    if (!ex.IsNull())
                    {
                        throw ex.ToException();
                    }

                    //
                    // UnAuthorized ...
                    if (resp.StatusCode == System.Net.HttpStatusCode.Unauthorized)
                    {
                        XException.NotAuthorized.Throw();
                    }

                    //
                    // NotFound ...
                    if (resp.StatusCode == System.Net.HttpStatusCode.NotFound)
                    {
                        XException.NotFound.Throw();
                    }

                    //
                    XException.ActionFailed.Throw();
                }

                //
                var result = resp.Content.FromJSON<T>();
                return result;
            },
            cancellationToken: cancellationToken);

            //
            return response;
        }

        /// <summary>
        /// Access a Get Request Stream as AsyncEnumerable ... 
        /// </summary>
        /// <param name="endpoint"></param>
        /// <param name="bufferLength"></param>
        /// <param name="addXPoweredValue"></param>
        /// <param name="tokens"></param>
        /// <param name="@params"></param>
        /// <param name="headers"></param>
        /// <param name="queryStrings"></param>
        /// <param name="cancellationToken"></param>
        /// <typeparam name="T"></typeparam>
        /// <returns></returns>
        public async Task<Stream> StreamData(
            Enum endpoint,
            int bufferLength = 8194,
            bool addXPoweredValue = true,
            XTokenResponse tokens = null,
            IDictionary<string, string> @params = null,
            IDictionary<string, string> headers = null,
            IDictionary<string, string> queryStrings = null,
            [System.Runtime.CompilerServices.EnumeratorCancellation]
            CancellationToken cancellationToken = default
        )
        {
            //
            var url = PrepareUrl(
                @params: @params,
                endpoint: endpoint,
                attachBaseUrl: true,
                queryStrings: queryStrings
            );
            var client = GetHttpClient(tokens);
            if (addXPoweredValue)
            {
                //
                client.DefaultRequestHeaders
                    .Add(
                        XAuthorization.XPoweredBy,
                        XPoweredValue
                );
            }

            //
            // For SSE, you might want to set the Accept header, though not strictly necessary for just streaming
            client.DefaultRequestHeaders.Accept.Clear();
            client.DefaultRequestHeaders.Accept
                .Add(
                    new System.Net.Http.Headers.MediaTypeWithQualityHeaderValue("text/event-stream"));

            //
            var response = await client.GetAsync(url, HttpCompletionOption.ResponseHeadersRead, cancellationToken);
            response.EnsureSuccessStatusCode();

            //
            var stream = await response.Content.ReadAsStreamAsync();

            //
            return stream;

            // using (var response = await client.GetAsync(url, HttpCompletionOption.ResponseHeadersRead, cancellationToken))
            // {
            //     //
            //     int readedBuffers = 0;
            //     response.EnsureSuccessStatusCode();
            //     var buffer = new byte[bufferLength];
            //     var stream = await response.Content.ReadAsStreamAsync();

            //     //
            //     while ((readedBuffers = await stream.ReadAsync(buffer, 0, buffer.Length)) > 0)
            //     {
            //         //
            //         var content = buffer.FromBytes();
            //         Console.WriteLine(content);
            //     }

            //     // await foreach (var message in stream) {
            //     //     Console.WriteLine(message);
            //     // }

            //     // await foreach (var item in stream.ToAsyncEnumerable<byte[]>(cancellationToken: cancellationToken))
            //     // {
            //     //     //
            //     //     Console.WriteLine(item);

            //     //     // T value = item.IsNull()
            //     //     // ? default(T)
            //     //     // : item.FromBytes().FromJSON<T>();

            //     //     // //
            //     //     // yield return value;
            //     // }
            // }

            ///
            /// 
            /// 
            ///             

            //
            // var eventSource = new EventSource(url);
            // // eventSource.

            // // var client = GetHttpClient(tokens);
            // // if (addXPoweredValue)
            // // {
            // //     //
            // //     client.DefaultRequestHeaders
            // //         .Add(
            // //             XAuthorization.XPoweredBy,
            // //             XPoweredValue);
            // // }

            // // //
            // // // For SSE, you might want to set the Accept header, though not strictly necessary for just streaming
            // // client.DefaultRequestHeaders.Accept.Clear();
            // // client.DefaultRequestHeaders.Accept
            // //     .Add(
            // //         new System.Net.Http.Headers.MediaTypeWithQualityHeaderValue("text/event-stream"));

            // // //
            // // using (var response = await client.GetAsync(url, HttpCompletionOption.ResponseHeadersRead, cancellationToken))
            // // {
            // //     //
            // //     response.EnsureSuccessStatusCode();
            // //     var stream = await response.Content.ReadAsStreamAsync();
            // //     await foreach (var item in stream.ToAsyncEnumerable<byte[]>(cancellationToken: cancellationToken))
            // //     {
            // //         //
            // //         T value = item.IsNull() 
            // //         ? default(T)
            // //         : item.FromBytes().FromJSON<T>();

            // //         //
            // //         yield return value;
            // //     }
            // // }
        }

        /// <summary>
        /// Handle Call Specified Request and Retrieve XBaseRestResponse<T> ...
        /// </summary>
        /// <param name="client"></param>
        /// <param name="request"></param>
        /// <param name="method"></param>
        /// <param name="supportRefreshingTokens"></param>
        /// <param name="cancellationToken"></param>
        /// <typeparam name="T"></typeparam>
        /// <returns>an instance of XBaseRestResponse<T></returns>
        public async Task<XBaseRestResponse<T>> RunRestRequestByResponse<T>(
            RestClient client,
            RestRequest request,
            XHttpMethod method,
            bool supportRefreshingTokens = true,
            CancellationToken cancellationToken = default
        )
        {
            //
            var response = await Task.Run(async () =>
            {
                //
                IRestResponse resp = null;

                //
                // Call Endpoint Service using Specified Method ...
                switch (method)
                {
                    //
                    // Get ...
                    case XHttpMethod.GET:
                        resp = client.Get(request);
                        break;

                    //
                    // Put ...
                    case XHttpMethod.PUT:
                        resp = client.Put(request);
                        break;

                    //
                    // Post ...
                    case XHttpMethod.POST:
                        resp = client.Post(request);
                        break;

                    //
                    // Delete ...
                    case XHttpMethod.DELETE:
                        resp = client.Delete(request);
                        break;
                }

                //
                if (!resp.IsSuccessful)
                {
                    //
                    // Log Exception ...
                    Logger.LogError($"Error: {resp.ErrorMessage}");
                    Logger.LogError($"Exception: {resp.ErrorException.ToJSON()}");
                    if (!resp.ErrorMessage.IsNullOrEmpty() &&
                        resp.ErrorMessage.Contains("timed out"))
                    {
                        XException.Timeout.Throw();
                    }

                    //
                    // TODO: Check UnAuthorized Status here for
                    // Refresh Tokens or Issue Correct Exception ...
                    if (supportRefreshingTokens &&
                        resp.StatusCode == System.Net.HttpStatusCode.Unauthorized)
                    {
                        //
                        var isRefreshed = request.Parameters.Any(rp =>
                            rp.Name == XParam.XIsRefreshed.GetStringValue() &&
                            rp.Value.ToString().ToNormalString() == true.ToJSON());

                        //
                        Logger.LogInformation($"isRefreshed: {isRefreshed}");

                        //
                        // Get Access Token ...
                        XTokenResponse tokens = null;
                        var accessToken = request.Parameters.FirstOrDefault(rp =>
                            rp.Name.ToNormalString() == XAuthorization.Header.ToNormalString()).Value.ToString();
                        if (!accessToken.IsNullOrEmpty())
                        {
                            //
                            accessToken = accessToken.Replace(XAuthorization.TokenIdentifier, "");

                            //
                            if (!accessToken.IsNullOrEmpty())
                            {
                                tokens = await tokenProvider.RetrieveToken(accessToken);
                            }
                        }

                        //
                        // Refresh Token and then re do request ...
                        if (!isRefreshed &&
                            !accessToken.IsNullOrEmpty() &&
                            !tokens.IsNull() &&
                            tokens.IsRefreshable())
                        {
                            //
                            request.AddHeader(XParam.XIsRefreshed.GetStringValue(), true.ToJSON());

                            //
                            // Refreshe Tokens ...
                            var refreshedTokens = await identityProvider
                                .RefreshTokens(tokens);

                            //
                            // Renew Rest Client with Refreshed Tokens ...
                            var timeout = client.Timeout;
                            client = GetRestClient(refreshedTokens);
                            client.Timeout = Timeout.Infinite;

                            //
                            // Do Request Again using renew Client ...
                            return await RunRestRequestByResponse<T>(
                                client: client,
                                request: request,
                                method: method
                            );
                        }
                    }

                    //
                    var ex = resp.Content.ToXError();
                    if (!ex.IsNull())
                    {
                        throw ex.ToException();
                    }

                    //
                    // UnAuthorized ...
                    if (resp.StatusCode == System.Net.HttpStatusCode.Unauthorized)
                    {
                        XException.NotAuthorized.Throw();
                    }

                    //
                    // NotFound ...
                    if (resp.StatusCode == System.Net.HttpStatusCode.NotFound)
                    {
                        XException.NotFound.Throw();
                    }

                    //
                    XException.ActionFailed.Throw();
                }

                //
                var result = new XBaseRestResponse<T>
                {
                    Response = resp,
                    Model = resp.Content.FromJSON<T>()
                };

                //
                return result;
            },
            cancellationToken: cancellationToken);

            //
            return response;
        }

        /// <summary>
        /// Get User SelectBy Param 
        /// </summary>
        /// <param name="model"></param>
        /// <param name="forceNotNull"></param>
        /// <param name="excludes"></param>
        /// <returns></returns>
        public string GetUserSelectByParam(
            XActionRequest model,
            bool forceNotNull = true,
            ICollection<XUserSelectBy> excludes = null
        )
        {
            //
            // Validate Args ...
            ValidationProvider.NotNull(model);

            //
            var id = model.UserId;
            var userName = model.UserName;
            var email = model.Email;
            var phoneNumber = model.MobileNumber;

            //
            if (excludes != null)
            {
                //
                if (excludes.Contains(XUserSelectBy.ID))
                {
                    id = null;
                }
                if (excludes.Contains(XUserSelectBy.Email))
                {
                    email = null;
                }
                if (excludes.Contains(XUserSelectBy.MobileNumber))
                {
                    phoneNumber = null;
                }
                if (excludes.Contains(XUserSelectBy.Username))
                {
                    userName = null;
                }
            }

            var selectByParam =
                id.IsNullOrEmpty() ?
                userName.IsNullOrEmpty() ?
                email.IsNullOrEmpty() ?
                phoneNumber.IsNullOrEmpty() ? null : phoneNumber : email : userName : id;

            //
            // Check result ...
            if (forceNotNull &&
                selectByParam.IsNullOrEmpty())
            {
                XException.InvalidData.Throw();
            }

            //
            return selectByParam;
        }

        /// <summary>
        /// Prepare Url Address of Specified Enum by Filling Params
        /// and Query Strings Attach ...
        /// </summary>
        /// <param name="endpoint"></param>
        /// <param name="attachBaseUrl"></param>
        /// <param name="@params"></param>
        /// <param name="queryStrings"></param>
        /// <returns></returns>
        public string PrepareUrl(
            Enum endpoint,
            bool attachBaseUrl = false,
            IDictionary<string, string> @params = null,
            IDictionary<string, string> queryStrings = null
        )
        {
            //
            // Retrieving Url Template ...
            var url = endpoint.GetStringValue();

            //
            // Filling Parmas and Query Strings of Url ...
            url = PrepareUrl(
                url: url,
                @params: @params,
                queryStrings: queryStrings,
                attachBaseUrl: attachBaseUrl
            );

            //
            return url;
        }

        /// <summary>
        /// Prepare Url Address by Filling Params
        /// and Query Strings Attach ...
        /// </summary>
        /// <param name="url"></param>
        /// <param name="attachBaseUrl"></param>
        /// <param name="@params"></param>
        /// <param name="queryStrings"></param>
        /// <returns></returns>
        public string PrepareUrl(
            string url,
            bool attachBaseUrl = false,
            IDictionary<string, string> @params = null,
            IDictionary<string, string> queryStrings = null
        )
        {
            //
            if (attachBaseUrl)
            {
                //
                var baseUrl = BaseUrl;
                if (!baseUrl.EndsWith("/"))
                {
                    baseUrl = $"{baseUrl}/";
                }

                //
                url = $"{baseUrl}{url}";
            }

            //
            // Add Route Payloads ...
            if (!@params.IsNull() && @params.Count > 0)
            {
                //
                var enumerator = @params.GetEnumerator();
                while (enumerator.MoveNext())
                {
                    //
                    var item = enumerator.Current;

                    //
                    url = url.Replace(item.Key, item.Value.ToUrlEncoded());
                }
            }

            //
            // Add Query Strings ...
            if (!queryStrings.IsNull() && queryStrings.Count > 0)
            {
                //
                url = $"{url}?";
                var enumerator = queryStrings.GetEnumerator();
                while (enumerator.MoveNext())
                {
                    //
                    var item = enumerator.Current;

                    //
                    url += $"{item.Key}={item.Value.ToUrlEncoded()}&";
                }

                //
                // remove lates & ...
                if (url.EndsWith("&"))
                {
                    url = url.Substring(0, url.Length - 1);
                }
            }

            //
            return url;
        }

        /// <summary>
        /// Converts UserInfo to TokenResponse model ...
        /// </summary>
        /// <param name="userInfo"></param>
        /// <returns></returns>
        public XTokenResponse ToTokenResponse(XUserClaimsInfoDto userInfo = null)
        {
            //
            XTokenResponse result = null;

            //
            if (!userInfo.IsNull())
            {
                //
                result = new XTokenResponse
                {
                    AccessToken = userInfo.AccessToken.IsNullOrEmpty()
                        ? ""
                        : userInfo.AccessToken,
                    RefreshToken = userInfo.RefreshToken.IsNullOrEmpty()
                        ? ""
                        : userInfo.RefreshToken,
                    ExpiresAt = userInfo.ExpiresAt,
                };

                //
                if (userInfo.AccessToken.IsNullOrEmpty())
                {
                    result = null;
                }
            }

            //
            return result;
        }
        #endregion
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xIdentityService\Providers\XIdentityProvider.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Net.Http;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Logging;
using Newtonsoft.Json;
using Newtonsoft.Json.Serialization;
using RestSharp;
using RestSharp.Authenticators;
using xCommons.Constants;
using xCommons.Extensions;
using xCommons.Providers;
using xExceptions.Constants;
using xHttpService.Constants;
using xIdentityModels.Constants;
using xIdentityModels.Extensions;
using xIdentityModels.Models;
using xIdentityService.Configuration;
using xIdentityService.Constants;
using xIdentityService.Interfaces;
using xIdentityService.Models;

namespace xIdentityService.Providers {
    public partial class XIdentityProvider : IXIdentityProvider {
        private readonly IXTokenProvider tokenProvider;
        private readonly IHostingEnvironment environment;
        private JsonSerializerSettings jsonSerializerSettings;
        private readonly XValidationProvider validationProvider;
        private readonly XIdentityServiceConfiguration identityConfiguration;

        public ILogger<XIdentityProvider> Logger { get; }
        public IXSecurityProvider SecurityProvider { get; }

        public string BaseUrl { get; }
        public string RevisionSecretKey { get; }
        public bool ReadResponseAsString { get; set; }

        public XIdentityProvider (
            IXTokenProvider tokenProvider,
            IHostingEnvironment environment,
            ILogger<XIdentityProvider> logger,
            IXSecurityProvider securityProvider,
            XIdentityServiceConfiguration identityConfiguration,
            XValidationProvider validationProvider
        ) {
            //
            BaseUrl = identityConfiguration.Authority;
            RevisionSecretKey = identityConfiguration.XRevisionSecretKey;

            //
            this.environment = environment;
            Logger = logger;
            SecurityProvider = securityProvider;

            //
            this.identityConfiguration = identityConfiguration;
            this.validationProvider = validationProvider;
            this.jsonSerializerSettings = new JsonSerializerSettings {
                ContractResolver = new CamelCasePropertyNamesContractResolver ()
            };

            //
            this.tokenProvider = tokenProvider;
        }

        //
        #region Tools ...
        /// <summary>
        /// Get an Instance of Http Client 
        /// </summary>
        /// <returns></returns>
        public HttpClient GetHttpClient () {
            //
            HttpClient httpClient = null;

            //
            // httpClient = new HttpClient ();
            var httpClientHandler = new HttpClientHandler () {
                ServerCertificateCustomValidationCallback = (sender, cert, chain, sslPolicyErrors) => {
                        //
                        Logger.LogInformation (
                            $"XSSL Handler: {Environment.NewLine}, sender: {sender}, {Environment.NewLine} cert: {cert}, {Environment.NewLine} chain: {chain}, {Environment.NewLine} sslPolicyErrors: {sslPolicyErrors}"
                        );

                        //
                        return true;
                    },
                    ClientCertificateOptions = ClientCertificateOption.Manual,
            };
            httpClient = new HttpClient (httpClientHandler);

            //
            // Set Timeout ...
            // TODO: Fix this ...
            // httpClient.Timeout = TimeSpan
            //     .FromSeconds (identityConfiguration.DefaultClientTimeout);

            //
            return httpClient;
        }

        /// <summary>
        /// Get an Instance of RestClient
        /// </summary>
        /// <returns></returns>
        public RestClient GetRestClient (XTokenResponse tokens = null) {
            //
            var client = new RestClient (BaseUrl);

            //
            // Set Authenticator ...
            if (!tokens.IsNull () &&
                !tokens.AccessToken.IsNullOrEmpty ()) {
                client.Authenticator = new JwtAuthenticator (tokens.AccessToken);
            }

            //
            // Refresh Token ...
            if (!tokens.IsNull () &&
                !tokens.RefreshToken.IsNullOrEmpty ()) {
                client.AddDefaultHeader (XAuthorization.RefreshToken, tokens.RefreshToken);
            }

            //
            // ExpiresAt ...
            if (!tokens.IsNull () &&
                tokens.ExpiresAt > 0) {
                client.AddDefaultHeader (XAuthorization.ExpiresAt, tokens.ExpiresAt.AsHttpParamString ());
            }

            //
            // Set Default Timeout ...
            client.Timeout = identityConfiguration.DefaultClientTimeout;

            //
            // SSL Validation Handler ...
            client.RemoteCertificateValidationCallback = (sender, cert, chain, sslPolicyErrors) => {
                //
                Logger.LogInformation (
                    $"XSSL Handler: {Environment.NewLine}, sender: {sender}, {Environment.NewLine} cert: {cert}, {Environment.NewLine} chain: {chain}, {Environment.NewLine} sslPolicyErrors: {sslPolicyErrors}"
                );

                //
                return true;
            };

            //
            return client;
        }

        /// <summary>
        /// Get an Instance of RestRequest 
        /// </summary>
        public RestRequest GetRestRequet (
            XApiAccountEndpoint endpoint,
            bool addXPoweredValue = true,
            IDictionary<string, string> @params = null,
            IDictionary<string, string> headers = null,
            IDictionary<string, string> queryStrings = null
        ) {
            //
            var url = endpoint.GetStringValue ();

            //
            // Add Route Payloads ...
            if (!@params.IsNull () && @params.Count > 0) {
                //
                var enumerator = @params.GetEnumerator ();
                while (enumerator.MoveNext ()) {
                    //
                    var item = enumerator.Current;

                    //
                    url = url.Replace (item.Key, item.Value.ToUrlEncoded ());
                }
            }

            //
            // Add Query Strings ...
            if (!queryStrings.IsNull () && queryStrings.Count > 0) {
                //
                url = $"{url}?";
                var enumerator = queryStrings.GetEnumerator ();
                while (enumerator.MoveNext ()) {
                    //
                    var item = enumerator.Current;

                    //
                    url += $"{item.Key}={item.Value.ToUrlEncoded ()}&";
                }

                //
                // remove lates & ...
                if (url.EndsWith ("&")) {
                    url = url.Substring (0, url.Length - 1);
                }
            }

            //
            // Create request ...
            var request = new RestRequest (url, DataFormat.Json);

            //
            if (addXPoweredValue) {
                request.AddHeader (XAuthorization.XPoweredBy, identityConfiguration.XPoweredValue);
            }

            //
            // Add Headers to request ...
            if (!headers.IsNull () && headers.Count > 0) {
                //
                var enumerator = headers.GetEnumerator ();
                while (enumerator.MoveNext ()) {
                    //
                    var item = enumerator.Current;
                    request.AddHeader (item.Key, item.Value);
                }
            }

            //
            return request;
        }

        /// <summary>
        /// Handle Call Specific Request and retrieve Response
        /// </summary>
        /// <param name="client"></param>
        /// <param name="request"></param>
        /// <param name="method"></param>
        /// <typeparam name="T"></typeparam>
        /// <returns></returns>
        public async Task<T> RunRestRequest<T> (
            RestClient client,
            RestRequest request,
            XHttpMethod method,
            bool supportRefreshingTokens = true
        ) {
            //
            var response = await Task.Run (async () => {
                //
                IRestResponse resp = null;

                //
                // Call Endpoint Service using Specified Method ...
                switch (method) {
                    //
                    // Get ...
                    case XHttpMethod.GET:
                        resp = client.Get (request);
                        break;

                        //
                        // Put ...
                    case XHttpMethod.PUT:
                        resp = client.Put (request);
                        break;

                        //
                        // Post ...
                    case XHttpMethod.POST:
                        resp = client.Post (request);
                        break;

                        //
                        // Delete ...
                    case XHttpMethod.DELETE:
                        resp = client.Delete (request);
                        break;
                }

                //
                if (!resp.IsSuccessful) {
                    //
                    // Log Exception ...
                    Logger.LogError ($"Error: {resp.ErrorMessage}");
                    Logger.LogError ($"Exception: {resp.ErrorException.ToJSON()}");
                    if (!resp.ErrorMessage.IsNullOrEmpty () &&
                        resp.ErrorMessage.Contains ("timed out")) {
                        XException.Timeout.Throw ();
                    }

                    //
                    // TODO: Check UnAuthorized Status here for
                    // Refresh Tokens or Issue Correct Exception ...
                    if (supportRefreshingTokens &&
                        resp.StatusCode == System.Net.HttpStatusCode.Unauthorized) {
                        //
                        var isRefreshed = request.Parameters.Any (rp =>
                            rp.Name == XParam.XIsRefreshed.GetStringValue () &&
                            rp.Value.ToString ().ToNormalString () == true.ToJSON ());

                        //
                        Logger.LogInformation ($"isRefreshed: {isRefreshed}");

                        //
                        // Get Access Token ...
                        XTokenResponse tokens = null;
                        var accessToken = request.Parameters.FirstOrDefault (rp =>
                            rp.Name.ToNormalString () == XAuthorization.Header.ToNormalString ()).Value.ToString ();
                        if (!accessToken.IsNullOrEmpty ()) {
                            //
                            accessToken = accessToken.Replace (XAuthorization.TokenIdentifier, "");

                            //
                            if (!accessToken.IsNullOrEmpty ()) {
                                tokens = await tokenProvider.RetrieveToken (accessToken);
                            }
                        }

                        //
                        // Refresh Token and then re do request ...
                        if (!isRefreshed &&
                            !accessToken.IsNullOrEmpty () &&
                            !tokens.IsNull () &&
                            tokens.IsRefreshable ()) {
                            //
                            request.AddHeader (XParam.XIsRefreshed.GetStringValue (), true.ToJSON ());

                            //
                            // Refreshe Tokens ...
                            var refreshedTokens = await RefreshTokens (tokens);

                            //
                            // Renew Rest Client with Refreshed Tokens ...
                            var timeout = client.Timeout;
                            client = GetRestClient (refreshedTokens);
                            client.Timeout = Timeout.Infinite;

                            //
                            // Do Request Again using renew Client ...
                            return await RunRestRequest<T> (
                                client: client,
                                request: request,
                                method: method);
                        }
                    }

                    //
                    var ex = resp.Content.ToXError ();
                    if (!ex.IsNull ()) {
                        throw ex.ToException ();
                    }

                    //
                    // UnAuthorized ...
                    if (resp.StatusCode == System.Net.HttpStatusCode.Unauthorized) {
                        XException.NotAuthorized.Throw ();
                    }

                    //
                    // NotFound ...
                    if (resp.StatusCode == System.Net.HttpStatusCode.NotFound) {
                        XException.NotFound.Throw ();
                    }

                    //
                    XException.ActionFailed.Throw ();
                }

                //
                var result = resp.Content.FromJSON<T> ();
                return result;
            });

            //
            return response;
        }
        public async Task<XBaseRestResponse<T>> RunRestRequestByResponse<T> (
            RestClient client,
            RestRequest request,
            XHttpMethod method,
            bool supportRefreshingTokens = true
        ) {
            //
            var response = await Task.Run (async () => {
                //
                IRestResponse resp = null;

                //
                // Call Endpoint Service using Specified Method ...
                switch (method) {
                    //
                    // Get ...
                    case XHttpMethod.GET:
                        resp = client.Get (request);
                        break;

                        //
                        // Put ...
                    case XHttpMethod.PUT:
                        resp = client.Put (request);
                        break;

                        //
                        // Post ...
                    case XHttpMethod.POST:
                        resp = client.Post (request);
                        break;

                        //
                        // Delete ...
                    case XHttpMethod.DELETE:
                        resp = client.Delete (request);
                        break;
                }

                //
                if (!resp.IsSuccessful) {
                    //
                    // Log Exception ...
                    Logger.LogError ($"Error: {resp.ErrorMessage}");
                    Logger.LogError ($"Exception: {resp.ErrorException.ToJSON()}");
                    if (!resp.ErrorMessage.IsNullOrEmpty () &&
                        resp.ErrorMessage.Contains ("timed out")) {
                        XException.Timeout.Throw ();
                    }

                    //
                    // TODO: Check UnAuthorized Status here for
                    // Refresh Tokens or Issue Correct Exception ...
                    if (supportRefreshingTokens &&
                        resp.StatusCode == System.Net.HttpStatusCode.Unauthorized) {
                        //
                        var isRefreshed = request.Parameters.Any (rp =>
                            rp.Name == XParam.XIsRefreshed.GetStringValue () &&
                            rp.Value.ToString ().ToNormalString () == true.ToJSON ());

                        //
                        Logger.LogInformation ($"isRefreshed: {isRefreshed}");

                        //
                        // Get Access Token ...
                        XTokenResponse tokens = null;
                        var accessToken = request.Parameters.FirstOrDefault (rp =>
                            rp.Name.ToNormalString () == XAuthorization.Header.ToNormalString ()).Value.ToString ();
                        if (!accessToken.IsNullOrEmpty ()) {
                            //
                            accessToken = accessToken.Replace (XAuthorization.TokenIdentifier, "");

                            //
                            if (!accessToken.IsNullOrEmpty ()) {
                                tokens = await tokenProvider.RetrieveToken (accessToken);
                            }
                        }

                        //
                        // Refresh Token and then re do request ...
                        if (!isRefreshed &&
                            !accessToken.IsNullOrEmpty () &&
                            !tokens.IsNull () &&
                            tokens.IsRefreshable ()) {
                            //
                            request.AddHeader (XParam.XIsRefreshed.GetStringValue (), true.ToJSON ());

                            //
                            // Refreshe Tokens ...
                            var refreshedTokens = await RefreshTokens (tokens);

                            //
                            // Renew Rest Client with Refreshed Tokens ...
                            var timeout = client.Timeout;
                            client = GetRestClient (refreshedTokens);
                            client.Timeout = Timeout.Infinite;

                            //
                            // Do Request Again using renew Client ...
                            return await RunRestRequestByResponse<T> (
                                client: client,
                                request: request,
                                method: method
                            );
                        }
                    }

                    //
                    var ex = resp.Content.ToXError ();
                    if (!ex.IsNull ()) {
                        throw ex.ToException ();
                    }

                    //
                    // UnAuthorized ...
                    if (resp.StatusCode == System.Net.HttpStatusCode.Unauthorized) {
                        XException.NotAuthorized.Throw ();
                    }

                    //
                    // NotFound ...
                    if (resp.StatusCode == System.Net.HttpStatusCode.NotFound) {
                        XException.NotFound.Throw ();
                    }

                    //
                    XException.ActionFailed.Throw ();
                }

                //
                var result = new XBaseRestResponse<T>
                {
                    Response = resp,
                    Model = resp.Content.FromJSON<T> ()
                };

                //
                return result;
            });

            //
            return response;
        }

        /// <summary>
        /// Get User SelectBy Param 
        /// </summary>
        /// <param name="model"></param>
        /// <param name="forceNotNull"></param>
        /// <param name="excludes"></param>
        /// <returns></returns>
        public string GetUserSelectByParam (
            XActionRequest model,
            bool forceNotNull = true,
            ICollection<XUserSelectBy> excludes = null
        ) {
            //
            // Validate Args ...
            validationProvider.NotNull (model);

            //
            var id = model.UserId;
            var userName = model.UserName;
            var email = model.Email;
            var phoneNumber = model.MobileNumber;

            //
            if (excludes != null) {
                //
                if (excludes.Contains (XUserSelectBy.ID)) {
                    id = null;
                }
                if (excludes.Contains (XUserSelectBy.Email)) {
                    email = null;
                }
                if (excludes.Contains (XUserSelectBy.MobileNumber)) {
                    phoneNumber = null;
                }
                if (excludes.Contains (XUserSelectBy.Username)) {
                    userName = null;
                }
            }

            var selectByParam =
                id.IsNullOrEmpty () ?
                userName.IsNullOrEmpty () ?
                email.IsNullOrEmpty () ?
                phoneNumber.IsNullOrEmpty () ? null : phoneNumber : email : userName : id;

            //
            // Check result ...
            if (forceNotNull &&
                selectByParam.IsNullOrEmpty ()) {
                XException.InvalidData.Throw ();
            }

            //
            return selectByParam;
        }
        #endregion
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xIdentityService\Providers\XInMemoryTokenProvider.cs

using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using xCommons.Extensions;
using xIdentityModels.Models;
using xIdentityService.Interfaces;

namespace xIdentityService.Providers {
    public partial class XInMemoryTokenProvider : IXTokenProvider {
        private IDictionary<string, XTokenResponse> DbContext;

        public XInMemoryTokenProvider () {
            //
            this.DbContext = new Dictionary<string, XTokenResponse> ();
        }

        public async Task<bool> IsTokenExists (string accessToken) {
            //
            // Validate Args ...
            if (accessToken.IsNullOrEmpty ()) {
                return false;
            }

            //
            // Process Result ...
            var result = DbContext.Keys.Any (k => k == accessToken);
            return await Task.FromResult (result);
        }

        public async Task<bool> IsTokenExists (XTokenResponse tokens) {
            //
            // Validate Args ...
            if (tokens.IsNull () ||
                tokens.AccessToken.IsNullOrEmpty () ||
                !await IsTokenExists (tokens.AccessToken)) {
                return false;
            };

            //
            // Process Result ...
            var result = await IsTokenExists (tokens.AccessToken);
            return result;
        }

        public async Task<bool> RemoveToken (string accessToken) {
            //
            // Validate Args ...
            if (accessToken.IsNullOrEmpty ()) {
                return false;
            }

            //
            // Process Result ...
            var result = DbContext.Remove (accessToken);
            return await Task.FromResult (result);
        }

        public async Task<bool> RemoveToken (XTokenResponse tokens) {
            //
            // Validate Args ...
            if (tokens.IsNull () ||
                tokens.AccessToken.IsNullOrEmpty () ||
                !await IsTokenExists (tokens.AccessToken)) {
                return false;
            };

            //
            // Process Result ...
            var result = await RemoveToken (tokens.AccessToken);
            return result;
        }

        public async Task<XTokenResponse> RetrieveToken (string accessToken) {
            //
            // Validate Args ...
            if (accessToken.IsNullOrEmpty () ||
                !await IsTokenExists (accessToken)) {
                return null;
            }

            //
            // Process Result ...
            var result = DbContext[accessToken];
            return result;
        }

        public async Task<bool> AddToken (XTokenResponse tokens) {
            //
            // Validate Args ...
            if (tokens.IsNull () ||
                tokens.AccessToken.IsNullOrEmpty () ||
                await IsTokenExists (tokens.AccessToken)) {
                return false;
            };

            //
            // Process Result ...
            try {
                //
                DbContext.Add (tokens.AccessToken, tokens);
                return true;
            } catch {
                return false;
            }
        }

        public async Task<bool> UpdateToken (XTokenResponse tokens) {
            //
            // Validate Args ...
            if (tokens.IsNull () ||
                tokens.AccessToken.IsNullOrEmpty () ||
                !await IsTokenExists (tokens.AccessToken)) {
                return false;
            };

            //
            // Process Result ...
            try {
                //
                DbContext[tokens.AccessToken] = tokens;
                return true;
            } catch {
                return false;
            }
        }

        public async Task<bool> AddOrUpdateToken (XTokenResponse tokens) {
            //
            // Validate Args ...
            if (tokens.IsNull () ||
                tokens.AccessToken.IsNullOrEmpty ()
            ) {
                return false;
            };

            //
            // Process Result ...
            try {
                //
                var isExists = await IsTokenExists (tokens);
                if (isExists) {
                    return await UpdateToken (tokens);
                } else {
                    return await AddToken (tokens);
                }
            } catch {
                return false;
            }
        }
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xIdentityService\Providers\XProxyHelper.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Web;
using xCommons.Extensions;
using xExceptions.Constants;
using xIdentityService.Configuration;
using xIdentityService.Interfaces;

namespace xIdentityService.Providers {
    public class XProxyHelper : IXProxyHelper {
        //
        #region Props ...
        public XProxyConfiguration Configuration { get; }
        #endregion

        //
        #region Constructor ...
        public XProxyHelper (XProxyConfiguration configuration) {
            this.Configuration = configuration;
        }
        #endregion

        //
        #region Actions ...
        /// <summary>
        /// Validate XProxy Configuration for Client ...
        /// </summary>
        /// <returns></returns>
        public bool ValidateConfiguration () {
            //
            var result = !Configuration.IsNull () &&
                !Configuration.Host.IsNullOrEmpty () &&
                Configuration.Host.IsValidUrl () &&
                Configuration.Routes.HasChild ();

            //
            return result;
        }

        /// <summary>
        /// retrie Normalize Host ...
        /// </summary>
        /// <returns></returns>
        public string NormalizeHost () {
            //
            var result = string.Empty;

            //
            if (!Configuration.IsNull () &&
                !Configuration.Host.IsNullOrEmpty () &&
                Configuration.Host.IsValidUrl ()
            ) {
                //
                result = Configuration.Host
                    .ToNormalString ();

                //
                if (result.EndsWith ("/")) {
                    result = result.Substring (0, result.Length - 1);
                }
            }

            //
            return result;
        }

        /// <summary>
        /// retrieve all registred Routes ...
        /// </summary>
        /// <returns></returns>
        public IEnumerable<XProxyRouteDescriptor> GetRoutes () {
            //
            // Validate Args ...
            if (Configuration.IsNull ()) {
                return null;
            }

            //
            return Configuration.Routes;
        }

        /// <summary>
        /// Retrieve all Prepared url of Routes ...
        /// </summary>
        /// <returns></returns>
        public IEnumerable<string> GetRouteUrls () {
            //
            var normalHost = NormalizeHost ();
            if (normalHost.IsNullOrEmpty ()) {
                return null;
            }

            //
            var result = GetRoutes ()
                .Select (r => $"{normalHost}{r.Route}");

            //
            return result;
        }

        /// <summary>
        /// Find an Specific Route ...
        /// </summary>
        /// <param name="whereClause"></param>
        /// <returns></returns>
        public XProxyRouteDescriptor FindRoute (Expression<Func<XProxyRouteDescriptor, bool>> whereClause) {
            //
            // Validate Arg ...
            if (whereClause.IsNull ()) {
                return null;
            }

            //
            var whereFunc = whereClause
                .Compile ();

            //
            var result = GetRoutes ()
                .FirstOrDefault (whereFunc);

            //
            return result;
        }

        /// <summary>
        /// Prepare a request url for a Proxy Route ...
        /// </summary>
        /// <param name="url"></param>
        /// <param name="descriptor"></param>
        /// <returns></returns>
        public string PrepareActionUrlForXProxyRoute (
            string url,
            XProxyRouteDescriptor descriptor
        ) {
            //
            if (!url.IsValidUrl () ||
                url.IsNullOrEmpty () ||
                !ValidateConfiguration ()
            ) {
                throw XException.InvalidArgs.ToException ();
            }

            //
            // find Route ...
            var routeDescriptor = GetRoutes ()
                .FirstOrDefault (r => r
                    .IsSameContent (descriptor)
                );

            //
            // Validate Route Descriptor ...
            if (
                routeDescriptor.IsNull () ||
                routeDescriptor.Route.IsNullOrEmpty ()
            ) {
                throw XException.InvalidArgs.ToException ();
            }

            //
            // Retrieve and Validate Host Address ...
            var host = NormalizeHost ();
            if (!host.IsValidUrl () ||
                host.IsNullOrEmpty ()
            ) {
                throw XException.InvalidArgs.ToException ();
            }

            //
            url = $"{host}{routeDescriptor.Route}/{HttpUtility.UrlEncode(url)}";

            //
            return url;
        }

        /// <summary>
        /// Prepare a request url for a Selected Proxy Route ...
        /// </summary>
        /// <param name="url"></param>
        /// <param name="whereClause"></param>
        /// <returns></returns>
        public string PrepareActionUrlForXProxyRoute (
            string url,
            Expression<Func<XProxyRouteDescriptor, bool>> whereClause
        ) {
            //
            if (!url.IsValidUrl () ||
                url.IsNullOrEmpty () ||
                whereClause.IsNull () ||
                !ValidateConfiguration ()
            ) {
                throw XException.InvalidArgs.ToException ();
            }

            //
            var descriptor = FindRoute (whereClause);

            //
            // find Route ...
            var result = PrepareActionUrlForXProxyRoute (
                url: url,
                descriptor: descriptor
            );

            //
            return result;
        }
        #endregion

        //
        #region Private ...
        #endregion
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xIdentityService\Security\XSecurityProvider.cs

using System;
using System.IO;
using System.Security.Cryptography;
using System.Text;
using xCommons.Extensions;
using xCommons.Helpers;
using xCommons.Providers;
using xIdentityService.Configuration;
using xIdentityService.Interfaces;

namespace xIdentityService.Security {
    public partial class XSecurityProvider : IXSecurityProvider {
        private readonly string secretKey;
        private readonly byte[] iv;
        private readonly byte[] key;
        private readonly XValidationProvider validationProvider;

        public XSecurityProvider (
            XIdentityServiceConfiguration identityConfiguration,
            XValidationProvider validationProvider
        ) {
            //
            this.secretKey = identityConfiguration.XRevisionSecretKey.ToMd5String ();
            this.validationProvider = validationProvider;

            //
            var ivBytes = new byte[16];
            var keyBytes = new byte[32];
            var secretBytes = Encoding.UTF8.GetBytes (this.secretKey);

            //
            Array.Copy (
                secretBytes,
                ivBytes,
                secretBytes.Length < ivBytes.Length ?
                secretBytes.Length :
                ivBytes.Length
            );
            this.iv = ivBytes;

            //
            Array.Copy (
                secretBytes,
                keyBytes,
                secretBytes.Length < keyBytes.Length ?
                secretBytes.Length :
                keyBytes.Length
            );
            this.key = keyBytes;

            // Encoding.UTF8.GetBytes (this.secretKey);
        }

        public string Encrypt (string plainText) {
            //
            validationProvider.NotEmpty (plainText);

            //
            var textBytes = Encoding.UTF8.GetBytes (plainText);
            var result = EncryptFromBytes (textBytes);

            //
            return result;
        }

        public string Decrypt (string cipherText) {
            //
            validationProvider.NotEmpty (cipherText);

            //
            var cipherBytes = Convert.FromBase64String (cipherText);
            var result = DecryptFromBytes (cipherBytes);

            //
            return result;
        }

        public string EncryptFromBytes (byte[] textBytes) {
            //
            // Validate Args ...
            validationProvider.NotNull (textBytes);

            // Declare the string used to hold
            // the decrypted text.
            byte[] encryptedBytes = null;

            // Create an RijndaelManaged object
            // with the specified key and IV.
            using (var rijAlg = new RijndaelManaged ()) {
                //Settings
                rijAlg.Mode = CipherMode.CBC;
                rijAlg.Padding = PaddingMode.PKCS7;
                // rijAlg.FeedbackSize = 128;

                rijAlg.Key = key;
                rijAlg.IV = iv;

                //
                using (var encryptor = rijAlg.CreateEncryptor (rijAlg.Key, rijAlg.IV)) {
                    encryptedBytes = encryptor.TransformFinalBlock (textBytes, 0, textBytes.Length);
                }
            }

            //
            return Convert.ToBase64String (encryptedBytes);
        }

        public string DecryptFromBytes (byte[] cipherBytes) {
            //
            // Validate Args ...
            validationProvider.NotNull (cipherBytes);

            // Declare the string used to hold
            // the decrypted text.
            string plaintext = null;

            // Create an RijndaelManaged object
            // with the specified key and IV.
            using (var rijAlg = new RijndaelManaged ()) {
                //Settings
                rijAlg.Mode = CipherMode.CBC;
                rijAlg.Padding = PaddingMode.PKCS7;
                // rijAlg.FeedbackSize = 128;

                rijAlg.Key = key;
                rijAlg.IV = iv;

                // Create a decrytor to perform the stream transform.
                var decryptor = rijAlg.CreateDecryptor (rijAlg.Key, rijAlg.IV);

                // Create the streams used for decryption.
                using (var msDecrypt = new MemoryStream (cipherBytes)) {
                    using (var csDecrypt = new CryptoStream (msDecrypt, decryptor, CryptoStreamMode.Read)) {
                        using (var srDecrypt = new StreamReader (csDecrypt)) {
                            // Read the decrypted bytes from the decrypting stream
                            // and place them in a string.
                            plaintext = srDecrypt.ReadToEnd ();
                        }
                    }
                }
            }

            //
            return plaintext;
        }
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xMessageService\Constants\ConfigurationNodeNames.cs

namespace xMessageService.Constants {
    public partial struct ConfigurationNodeNames {
        public const string MESSAGE_NODE_NAME = "MessageConfiguration";
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xMessageService\Constants\xMessageServiceConstants.cs

namespace xMessageService.Constants {
    public struct xMessageServiceConstants {
        public const string DEFAULT_EMPTY_PROVIDER = "EMPTY";
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xMessageService\DI\XDIHelperExtension.cs

using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using xCommons.Extensions;
using xMessageService.Constants;
using xMessageService.Interfaces;
using xMessageService.Models;
using xMessageService.Providers;

namespace xMessageService.DI {
    public static partial class XDIHelperExtension {
        /// <summary>
        /// Retrieve XMessage Configuration from App Settings 
        /// </summary>
        /// <param name="config"></param>
        /// <returns></returns>
        public static XMessageConfiguration GetXMessageConfiguration (this IConfiguration config) {
            //
            var xMessageConfigSection = config.GetSection (ConfigurationNodeNames.MESSAGE_NODE_NAME);
            var xMessageConfiguration = xMessageConfigSection.Get<XMessageConfiguration> ();

            //
            var defaultMailConfiguration = new Dictionary<string, XMailConfiguration> {
                    ["EMPTY"] =
                    new XMailConfiguration {
                    Title = xMessageServiceConstants.DEFAULT_EMPTY_PROVIDER,
                    Host = "",
                    Port = 25,
                    EnableSsl = false,
                    Username = "",
                    Password = ""
                    }
                };

            //
            var defaultSmsConfiguration = new Dictionary<string, XSmsConfiguration> {
                    ["EMPTY"] =
                    new XSmsConfiguration {
                    ServiceUrl = "",
                    Username = "",
                    Password = "",
                    LineNumber = "",
                    UserApiKey = "",
                    SecretKey = "",
                    }
                };

            //
            if (xMessageConfiguration.IsNull ()) {
                //
                xMessageConfiguration = new XMessageConfiguration {
                    DefaultSMSProvider = xMessageServiceConstants.DEFAULT_EMPTY_PROVIDER,
                    DefaultMailProvider = xMessageServiceConstants.DEFAULT_EMPTY_PROVIDER,
                    MailConfigurations = defaultMailConfiguration,
                    SmsConfigurations = defaultSmsConfiguration
                };

                //
                // Warn Message is Default Configuration ...
                Console.WriteLine ($"IMPORTANT: xMessageService Configuration is Default, so the Service can't works properly ...");
            }

            //
            // Handle Default Mail Provider ...
            if (xMessageConfiguration.DefaultMailProvider.IsNullOrEmpty ()) {
                //
                if (xMessageConfiguration.IsNull () ||
                    //
                    xMessageConfiguration.MailConfigurations.IsNull () ||
                    xMessageConfiguration.MailConfigurations.Count == 0) {
                    //
                    Console.WriteLine ("There is no defined Mail Provider Configurations ...");
                    xMessageConfiguration.DefaultMailProvider = xMessageServiceConstants.DEFAULT_EMPTY_PROVIDER;
                }

                //
                if (xMessageConfiguration.DefaultMailProvider == xMessageServiceConstants.DEFAULT_EMPTY_PROVIDER) {
                    xMessageConfiguration.MailConfigurations = defaultMailConfiguration;
                } else {
                    xMessageConfiguration.DefaultMailProvider = xMessageConfiguration.MailConfigurations.Keys.First ();
                }
            }

            //
            // Handle Default SMS Provider ...
            if (xMessageConfiguration.DefaultSMSProvider.IsNullOrEmpty ()) {
                //
                if (xMessageConfiguration.IsNull () ||
                    xMessageConfiguration.SmsConfigurations.IsNull () ||
                    xMessageConfiguration.SmsConfigurations.Count == 0) {
                    //
                    Console.WriteLine ("There is no defined SMS Provider Configurations ...");
                    xMessageConfiguration.DefaultSMSProvider = xMessageServiceConstants.DEFAULT_EMPTY_PROVIDER;
                }

                //
                if (xMessageConfiguration.DefaultSMSProvider == xMessageServiceConstants.DEFAULT_EMPTY_PROVIDER) {
                    xMessageConfiguration.SmsConfigurations = defaultSmsConfiguration;
                } else {
                    xMessageConfiguration.DefaultSMSProvider = xMessageConfiguration.SmsConfigurations.Keys.First ();
                }
            }

            //
            return xMessageConfiguration;
        }

        /// <summary>
        /// Register XMessage Service 
        /// </summary>
        /// <param name="services"></param>
        /// <param name="config"></param>
        public static void AddXMessageService (this IServiceCollection services, IConfiguration config) {
            //
            var xMessageConfiguration = config.GetXMessageConfiguration ();
            services.AddSingleton<XMessageConfiguration> (xMessageConfiguration);

            //
            // Register SMS Service ...
            var xSmsService = new XSmsService (
                xMessageConfiguration.DefaultSMSProvider,
                xMessageConfiguration.SmsConfigurations
            );
            services.AddSingleton<IXSmsService> (xSmsService);

            //
            // Register Mail Service ...
            var xMailService = new XMailService (
                xMessageConfiguration.DefaultMailProvider,
                xMessageConfiguration.MailConfigurations
            );
            services.AddSingleton<IXMailService> (xMailService);

            //
            // Register MEssage Provider ...
            services.AddSingleton<IXMessageProvider, XMessageProvider> ();
        }
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xMessageService\Interfaces\IXMailService.cs

using System.Threading.Tasks;
using xMessageService.Models;

namespace xMessageService.Interfaces {
    public partial interface IXMailService {
        Task SendMailAsync (
            XMessage message,
            string provider = null
        );
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xMessageService\Interfaces\IXMessageProvider.cs

using System;
using System.Threading.Tasks;
using xMessageService.Models;

namespace xMessageService.Interfaces {
    public partial interface IXMessageProvider {
        bool IsReady (
            bool? checkMailService = false,
            bool? checkSmsService = false
        );

        Task SendMailAsync (
            XMessage message,
            string provider = null,
            bool throwException = true,
            Exception exception = null
        );

        Task SendSmsAsync (
            XMessage message,
            string provider = null,
            bool throwException = true,
            Exception exception = null
        );
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xMessageService\Interfaces\IXSmsService.cs

using System.Threading.Tasks;
using xMessageService.Models;

namespace xMessageService.Interfaces {
    public partial interface IXSmsService {
        Task SendSmsAsync (
            XMessage message,
            string provider = null
        );
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xMessageService\Models\XMailConfiguration.cs

namespace xMessageService.Models {
    public partial class XMailConfiguration {
        public string Title { get; set; }
        public string Host { get; set; }
        public int Port { get; set; }
        public bool EnableSsl { get; set; }
        public string Username { get; set; }
        public string Password { get; set; }
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xMessageService\Models\XMessage.cs

using System.Collections.Generic;
using xModels.Base;

namespace xMessageService.Models {
    public partial class XMessage : XBaseDto {
        public HashSet<string> Recievers { get; set; } = new HashSet<string> ();
        public string Message { get; set; }
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xMessageService\Models\XMessageConfiguration.cs

using System.Collections.Generic;

namespace xMessageService.Models {
    public partial class XMessageConfiguration {
        public string DefaultSMSProvider { get; set; }
        public string DefaultMailProvider { get; set; }
        public IDictionary<string, XMailConfiguration> MailConfigurations { get; set; }
        public IDictionary<string, XSmsConfiguration> SmsConfigurations { get; set; }
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xMessageService\Models\XSmsConfiguration.cs

namespace xMessageService.Models {
    public partial class XSmsConfiguration {
        public string ServiceUrl { get; set; }
        public string Username { get; set; }
        public string Password { get; set; }
        public string LineNumber { get; set; }
        public string UserApiKey { get; set; }
        public string SecretKey { get; set; }
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xMessageService\Providers\XMailService.cs

using System;
using System.Collections.Generic;
using System.Net;
using System.Net.Mail;
using System.Threading.Tasks;
using xCommons.Extensions;
using xExceptions.Constants;
using xMessageService.Interfaces;
using xMessageService.Models;

namespace xMessageService.Providers {
    public partial class XMailService : IXMailService {
        private SmtpClient smtpClient;
        private readonly string defaultProvider;
        private readonly IDictionary<string, XMailConfiguration> configurations;

        public XMailService (
            string defaultProvider,
            IDictionary<string, XMailConfiguration> configurations
        ) {
            this.defaultProvider = defaultProvider;
            this.configurations = configurations;

            //
            // Get instance of SMTP Client ...
            PrepareSmtpClient ();
        }

        public Task SendMailAsync (
            XMessage message,
            string provider = null
        ) {
            //
            // Run Send Mail Asynchronous ...
            return Task.Run (() => {
                SendMail (message, provider);
            });
        }

        #region Private ...
        /// <summary>
        /// Validate and Retrieve Provider Configuration for Service
        /// </summary>
        /// <param name="provider"></param>
        /// <returns></returns>
        private XMailConfiguration GetConfiguration (string provider = null) {
            //
            if (provider.IsNullOrEmpty ()) {
                provider = defaultProvider;
            }

            //
            if (!configurations.Keys.Contains (provider)) {
                XException.MessageServiceInitialFailed.Throw ();
            }

            //
            return configurations[provider];
        }

        /// <summary>
        /// Prepare SMTP Client by Using Specified/Default Provider
        /// </summary>
        /// <param name="provider"></param>
        private void PrepareSmtpClient (string provider = null) {
            //
            var config = GetConfiguration (provider);
            if (config.IsNull()) {
                return;
            }

            //
            smtpClient = new SmtpClient () {
                Host = config.Host,
                Port = config.Port,
                EnableSsl = config.EnableSsl,
                UseDefaultCredentials = false,
                Credentials = new NetworkCredential (
                config.Username,
                config.Password)
            };
        }

        /// <summary>
        /// Prepare Mail Message With Specified/Default Provider
        /// </summary>
        /// <param name="message"></param>
        /// <param name="provider"></param>
        /// <returns></returns>
        private MailMessage PrepareMailMessage (
            XMessage message,
            string provider = null
        ) {
            //
            if (message == null ||
                message.Message.IsNullOrEmpty () ||
                message.Recievers.Count == 0) {
                XException.InvalidMessage.Throw ();
            }

            //
            var config = GetConfiguration (provider);
            var mailMessage = new MailMessage () {
                From = new MailAddress (config.Username),
                Subject = config.Title,
                Body = message.Message
            };

            //
            foreach (var reciever in message.Recievers) {
                mailMessage.To.Add (reciever);
            }

            //
            return mailMessage;
        }

        /// <summary>
        /// Send Mail Using Specified/Default Provider
        /// </summary>
        /// <param name="message"></param>
        /// <param name="provider"></param>
        private void SendMail (
            XMessage message,
            string provider = null
        ) {
            //
            if (smtpClient.IsNull()) {
                //
                Console.WriteLine ($"SMTP Error: MessageServiceInitialFailed ...");
                XException.MessageServiceInitialFailed.Throw ();
            }

            //
            var mailMessage = PrepareMailMessage (message, provider);

            //
            try {
                smtpClient.Send (mailMessage);
            } catch (Exception ex) {
                //
                Console.WriteLine ($"SMTP Error: {ex.Message}");
                XException.MessageServiceInitialFailed.Throw ();
            }
        }
        #endregion        
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xMessageService\Providers\XMessageProvider.cs

using System;
using System.Threading.Tasks;
using Microsoft.Extensions.Logging;
using xCommons.Extensions;
using xExceptions.Constants;
using xMessageService.Interfaces;
using xMessageService.Models;

namespace xMessageService.Providers {
    public partial class XMessageProvider : IXMessageProvider {
        private readonly XMessageConfiguration configuration;
        private readonly ILogger<XMessageProvider> logger;
        private readonly IXSmsService smsService;
        private readonly IXMailService mailService;

        public XMessageProvider (
            XMessageConfiguration configuration,
            ILogger<XMessageProvider> logger,
            IXSmsService smsService,
            IXMailService mailService
        ) {
            this.configuration = configuration;
            this.logger = logger;
            this.smsService = smsService;
            this.mailService = mailService;
        }

        /// <summary>
        /// Send a Mail Message
        /// </summary>
        /// <param name="message"></param>
        /// <param name="provider"></param>
        /// <param name="throwException"></param>
        /// <param name="exception"></param>
        /// <returns></returns>
        public async Task SendMailAsync (
            XMessage message,
            string provider = null,
            bool throwException = true,
            Exception exception = null
        ) {
            //
            if (exception.IsNull ()) {
                exception = XException.ActionFailed.ToException ();
            }

            //
            try {
                await mailService.SendMailAsync (message, provider);
            } catch (Exception ex) {
                //
                logger.LogError ($"Exeption: {ex.Message}");

                //
                if (throwException) {
                    throw exception;
                }
            }
        }

        /// <summary>
        /// Send SMS Message 
        /// </summary>
        /// <param name="message"></param>
        /// <returns></returns>
        public async Task SendSmsAsync (
            XMessage message,
            string provider = null,
            bool throwException = true,
            Exception exception = null
        ) {
            //
            if (exception.IsNull ()) {
                exception = XException.ActionFailed.ToException ();
            }

            //
            try {
                await smsService.SendSmsAsync (message, provider);
            } catch {
                if (throwException) {
                    throw exception;
                }
            }
        }

        /// <summary>
        /// Check Message Provider is Ready or not
        /// </summary>
        /// <param name="checkMailService"></param>
        /// <param name="checkSmsService"></param>
        /// <returns></returns>
        public bool IsReady (
            bool? checkMailService = false,
            bool? checkSmsService = false
        ) {
            //
            var result = true;

            //
            // Check Mail Service ...
            if (checkMailService.HasValue &&
                checkMailService.GetValueOrDefault ()) {
                result = result && mailService != null;
            }

            //
            // Check Sms Service ...
            if (checkSmsService.HasValue &&
                checkSmsService.GetValueOrDefault ()) {
                result = result && smsService != null;
            }

            //
            return result;
        }
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xMessageService\Providers\XSmsService.cs

using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using PhoneNumbers;
using RestSharp;
using xCommons.Extensions;
using xExceptions.Constants;
using xMessageService.Interfaces;
using xMessageService.Models;

namespace xMessageService.Providers {
    public partial class XSmsService : IXSmsService {
        private string serviceUrl;
        private readonly string defaultProvider;
        private readonly IDictionary<string, XSmsConfiguration> configurations;

        public XSmsService (
            string defaultProvider,
            IDictionary<string, XSmsConfiguration> configurations
        ) {
            this.defaultProvider = defaultProvider;
            this.configurations = configurations;

            //
            PrepareServiceUrl ();
        }

        public Task SendSmsAsync (
            XMessage message,
            string provider = null
        ) {
            //
            // Run Send SMS Asynchronous ...
            return Task.Run (() => {
                SendSMS (message, provider);
            });
        }

        #region Private ...
        /// <summary>
        /// Prepare Service Url for Specified/Default Provider
        /// </summary>
        /// <param name="provider"></param>
        private void PrepareServiceUrl (string provider = null) {
            //
            if (provider.IsNullOrEmpty ()) {
                provider = defaultProvider;
            }

            //
            var config = GetConfiguration (provider);
            if (config.IsNull ()) {
                return;
            }

            //
            serviceUrl = config.ServiceUrl;
            serviceUrl += "&username=" + config.Username + "&password=" + config.Password + "&";
        }

        /// <summary>
        /// Prepare Service url for Integrating XMessage by 
        /// using Specified/Default Provider Configurations
        /// </summary>
        /// <param name="message"></param>
        /// <param name="provider"></param>
        private void PrepareSmsMessage (
            XMessage message,
            string provider = null
        ) {
            //
            if (message == null ||
                message.Message.IsNullOrEmpty () ||
                message.Recievers.Count == 0) {
                XException.InvalidMessage.Throw ();
            }

            //
            // Validating Mobile Numbers ...
            var phoneNumberUtil = PhoneNumbers.PhoneNumberUtil.GetInstance ();
            var recieversList = "";

            //
            PrepareServiceUrl (provider);

            //
            foreach (var reciever in message.Recievers) {
                try {
                    //
                    var mPhoneNumber = phoneNumberUtil.Parse (reciever, null);
                    if (phoneNumberUtil.IsValidNumber (mPhoneNumber)) {
                        //
                        // Format Phone Numbers to the '+989120000000' pattern ...
                        var recieverPhone = phoneNumberUtil.Format (mPhoneNumber, PhoneNumberFormat.E164);
                        if (recieversList.Length > 0) {
                            recieversList += ",";
                        }
                        recieversList += reciever;
                    }
                } catch { }
            }

            //
            var config = GetConfiguration ();

            //
            // Preparing All Content and Configurations for Sending Messages ...
            serviceUrl += "to=" +
                recieversList +
                "&message=" +
                message.Message +
                "&from=" +
                config.LineNumber +
                "&flash=" +
                false;
        }

        /// <summary>
        /// Send a Message as SMS by Specified/Default Provider
        /// </summary>
        /// <param name="message"></param>
        /// <param name="provider"></param>
        private void SendSMS (
            XMessage message,
            string provider = null
        ) {
            //
            if (serviceUrl.IsNullOrEmpty ()) {
                //
                Console.WriteLine ($"SMS Error: MessageServiceInitialFailed ...");
                XException.MessageServiceInitialFailed.Throw ();
            }

            //
            try {
                //
                // preparing Service Url based on message data ...
                PrepareSmsMessage (message, provider);

                //
                // Implementing Service Calling Using RestSharp Library ...
                // We Select RestSharp because it supports Sync/Async Calls ...
                var client = new RestClient (serviceUrl);
                var request = new RestRequest (Method.POST);

                //
                // Send Request ...
                var response = client.Execute (request);
            } catch (Exception ex) {
                Console.WriteLine ($"SMS Error: {ex.Message}");
                XException.MessageServiceInitialFailed.Throw ();
            }
        }

        /// <summary>
        /// Validate and Retrieve Provider Configuration for Service
        /// </summary>
        /// <param name="provider"></param>
        /// <returns></returns>
        private XSmsConfiguration GetConfiguration (string provider = null) {
            //
            if (
                provider.IsNullOrEmpty () ||
                provider.ToNormalString () == "empty"
            ) {
                //
                provider = defaultProvider;
                return null;
            }

            //
            if (!configurations.Keys.Contains (provider)) {
                XException.MessageServiceInitialFailed.Throw ();
            }

            //
            return configurations[provider];
        }
        #endregion        
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xModels\Base\XBaseClass.cs

using System;
using Microsoft.Extensions.Logging;
using xCommons.Extensions;
using xExceptions.Constants;

namespace xModels.Base {
    /// <summary>
    /// a Base class which carry required things as a Father for it's childs ...
    /// </summary>
    public abstract class XBaseClass {
        //
        #region Properties ...
        /// <summary>
        /// LogTag which Specified for this class ...
        /// </summary>
        private readonly string LOG_TAG;

        /// <summary>
        /// logger instance ...
        /// </summary>
        private readonly ILogger logger;
        #endregion

        //
        #region Constructor ...
        public XBaseClass (ILoggerFactory loggerFactory) {
            //
            // Preparing Log Tag ...
            LOG_TAG = this.GetType ().Name;

            //
            Type classType = this.GetType ();
            logger = loggerFactory.CreateLogger (classType);
        }
        #endregion

        //
        #region Protected ...
        /// <summary>
        /// Extract Prepared Log MEssage ...
        /// </summary>
        /// <param name="message"></param>
        /// <returns></returns>
        protected virtual string GetLogMessage (string message) {
            //
            // Prepare Log Message ...
            message = $"{LOG_TAG} => {message}";
            return message;
        }

        /// <summary>
        /// Logging specific Message ...
        /// </summary>
        /// <param name="message"></param>
        /// <param name="logLevel"></param>
        protected virtual void LogMessage (
            string message,
            LogLevel logLevel = LogLevel.Information
        ) {
            //
            // Validate Args ...
            if (message.IsNullOrEmpty ()) {
                throw XException.InvalidArgs
                    .ToException ();
            }

            //
            // Prepare Log Message ...
            message = GetLogMessage (message);

            //
            // Logging Message ...
            logger.Log (
                message: message,
                logLevel: logLevel
            );
        }

        /// <summary>
        /// Logging specific Message to Console ...
        /// </summary>
        /// <param name="message"></param>
        protected virtual void ConsoleMessage (string message) {
            //
            // Validate Args ...
            if (message.IsNullOrEmpty ()) {
                throw XException.InvalidArgs
                    .ToException ();
            }

            //
            // Prepare Log Message ...
            message = GetLogMessage (message);

            //
            // Logging Message ...
            Console.WriteLine (message);
        }
        #endregion
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xModels\Base\XBaseDescriptor.cs

namespace xModels.Base {
    /// <summary>
    /// Descriptors classes Map required data for creating Entities on Seeding time ...
    /// this is a Base Descriptor class ...
    /// </summary>
    public abstract class XBaseDescriptor { }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xModels\Base\XBaseDto.cs

namespace xModels.Base {
    /// <summary>
    /// DTO - Data Transfer Objects is a kind of classes which Represent Entities ...
    /// this is base Dto class ...
    /// </summary>
    public abstract class XBaseDto { }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xModels\Base\XBaseEntity.cs

using System.ComponentModel.DataAnnotations;

namespace xModels.Base {
    /// <summary>
    /// Base Entity Class
    /// </summary>
    /// <typeparam name="T"></typeparam>
    public abstract class XBaseEntity<T> {
        /// <summary>
        /// Entity Id
        /// </summary>
        /// <value>entity unique id</value>
        [Key]
        [Required]
        public T Id { get; set; }

        /// <summary>
        /// Provided Soft Delete Behaviour ...
        /// </summary>
        /// <value></value>
        public bool Deleted { get; set; }
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xModels\Base\XBaseEntityDto.cs

namespace xModels.Base
{
    /// <summary>
    /// Base Entity Related Dto Class ...
    /// </summary>
    /// <typeparam name="TKey"></typeparam>
    public abstract class XBaseEntityDto<TKey>
    {
        /// <summary>
        /// Entity Id
        /// </summary>
        /// <value>entity unique id</value>
        public TKey Id { get; set; }

        /// <summary>
        /// Provided Soft Delete Behaviour ...
        /// </summary>
        /// <value></value>
        public bool Deleted { get; set; }
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xModels\Base\XBaseGuidIDEntity.cs

using System;

namespace xModels.Base {
    /// <summary>
    /// a BaseEntity Class which has Id of Guid type
    /// </summary>
    public class XBaseGuidIDEntity : XBaseEntity<Guid> { }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xModels\Base\XBaseGuidIDEntityDto.cs

using System;

namespace xModels.Base
{
    public class XBaseGuidIDEntityDto : XBaseEntityDto<Guid>
    { }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xModels\Base\XBaseIntIDEntity.cs

using System.ComponentModel.DataAnnotations;

namespace xModels.Base {
    /// <summary>
    /// a BaseEntity Class which has Id of int type
    /// </summary>
    public abstract class XBaseIntIDEntity : XBaseEntity<int> { }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xModels\Base\XBaseIntIDEntityDto.cs

namespace xModels.Base
{
    public class XBaseIntIDEntityDto : XBaseEntityDto<int>
    { }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xModels\Base\XBaseLongIDEntity.cs

namespace xModels.Base
{
    public class XBaseLongIDEntity : XBaseEntity<long>
    { }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xModels\Base\XBaseLongIDEntityDto.cs

namespace xModels.Base
{
    public class XBaseLongIDEntityDto : XBaseEntityDto<long>
    { }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xModels\Base\XBaseRangeRequest.cs

using System.Collections.Generic;

namespace xModels.Base {
    /// <summary>
    /// Range Request Classes Carry a List of Objects
    /// </summary>
    /// <typeparam name="T"></typeparam>
    public class XBaseRangeRequest<T> {
        public IEnumerable<T> Items { get; set; } = new HashSet<T> ();
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xModels\Base\XBaseStorableDto.cs

namespace xModels.Base {
    public abstract class XBaseStorableDto<TKey> : XBaseDto {
        public abstract TKey Id { get; set; }
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xModels\Base\XBaseStorableDtoEventModel.cs

namespace xModels.Base
{
    public class XBaseStorableDtoEventModel<T>
    {
        public T Model { get; set; }

        public XBaseStorableDtoEventModel(T model)
        {
            Model = model;
        }
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xModels\Base\XBaseStoreEvent.cs

using System;
using System.Collections.Generic;
using System.Reactive.Linq;
using System.Reactive.Subjects;
using xModels.Interfaces;

namespace xModels.Base
{
    public abstract class XBaseStoreEvent<T, TKey> : IXBaseStoreEvents<T, TKey>
    where T : XBaseStorableDto<TKey>
    {
        //
        private readonly ISubject<XBaseStorableDtoEventModel<T>> onAddSubject;
        private readonly ISubject<XBaseStorableDtoEventModel<T>> onUpdateSubject;
        private readonly ISubject<XBaseStorableDtoEventModel<T>> onRemoveSubject;

        //
        private readonly ISubject<XBaseStorableDtoEventModel<IEnumerable<T>>> onAddManySubject;
        private readonly ISubject<XBaseStorableDtoEventModel<IEnumerable<T>>> onUpdateManySubject;
        private readonly ISubject<XBaseStorableDtoEventModel<IEnumerable<T>>> onRemoveManySubject;

        //
        public IObservable<XBaseStorableDtoEventModel<T>> OnAddObservable => onAddSubject.AsObservable();

        public IObservable<XBaseStorableDtoEventModel<T>> OnUpdateObservable => onUpdateSubject.AsObservable();

        public IObservable<XBaseStorableDtoEventModel<T>> OnRemoveObservable => onRemoveSubject.AsObservable();

        //

        public IObservable<XBaseStorableDtoEventModel<IEnumerable<T>>> OnAddManyObservable => onAddManySubject.AsObservable();

        public IObservable<XBaseStorableDtoEventModel<IEnumerable<T>>> OnUpdateManyObservable => onUpdateManySubject.AsObservable();

        public IObservable<XBaseStorableDtoEventModel<IEnumerable<T>>> OnRemoveManyObservable => onRemoveManySubject.AsObservable();

        //
        protected XBaseStoreEvent()
        {
            //
            onAddSubject = new ReplaySubject<XBaseStorableDtoEventModel<T>>(1);
            onUpdateSubject = new ReplaySubject<XBaseStorableDtoEventModel<T>>(1);
            onRemoveSubject = new ReplaySubject<XBaseStorableDtoEventModel<T>>(1);

            //
            onAddManySubject = new ReplaySubject<XBaseStorableDtoEventModel<IEnumerable<T>>>(1);
            onUpdateManySubject = new ReplaySubject<XBaseStorableDtoEventModel<IEnumerable<T>>>(1);
            onRemoveManySubject = new ReplaySubject<XBaseStorableDtoEventModel<IEnumerable<T>>>(1);
        }

        //
        #region Base Actions ...
        public void AddEvent(XBaseStorableDtoEventModel<T> model)
        {
            onAddSubject.OnNext(model);
        }

        public void AddManyEvent(XBaseStorableDtoEventModel<IEnumerable<T>> model)
        {
            onAddManySubject.OnNext(model);
        }

        public void RemoveEvent(XBaseStorableDtoEventModel<T> model)
        {
            onRemoveSubject.OnNext(model);
        }

        public void RemoveManyEvent(XBaseStorableDtoEventModel<IEnumerable<T>> model)
        {
            onRemoveManySubject.OnNext(model);
        }

        public void UpdateEvent(XBaseStorableDtoEventModel<T> model)
        {
            onUpdateSubject.OnNext(model);
        }

        public void UpdateManyEvent(XBaseStorableDtoEventModel<IEnumerable<T>> model)
        {
            onUpdateManySubject.OnNext(model);
        }
        #endregion
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xModels\Base\XBaseStringIDEntity.cs

using System;

namespace xModels.Base {
    /// <summary>
    /// a BaseEntity Class which has Id of string type
    /// </summary>
    public class XBaseStringIDEntity : XBaseEntity<string> { }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xModels\Base\XBaseStringIDEntityDto.cs

namespace xModels.Base
{
    public class XBaseStringIDEntityDto : XBaseEntityDto<string>
    { }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xModels\Base\XBaseValueContainer.cs

namespace xModels.Base
{
    public class XBaseValueContainer<T>
    {
        public T Value { get; set; }
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xModels\Dtos\XBaseIndexedDto.cs

using xModels.Base;

namespace xModels.Dtos
{
    public class XBaseIndexedDto<T, TKey, TIndex> : XBaseDto
    {
        public T Item { get; set; }
        public TKey Key { get; set; }
        public TIndex Index { get; set; }
    }

    public class XBaseIntIndexedDto<T> : XBaseIndexedDto<T, string, int> { }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xModels\Dtos\XDeviceDto.cs

using xCommons.Constants;
using xModels.Base;

namespace xModels.Dtos {
    public class XDeviceDto : XBaseDto {
        /// <summary>
        /// Operating System
        /// </summary>
        /// <value>device operating system identifier</value>
        public string Os { get; set; }
        /// <summary>
        /// Operating System Version
        /// </summary>
        /// <value>which version of operatin system is in use</value>
        public string OsVersion { get; set; }
        /// <summary>
        /// Device Browser
        /// </summary>
        /// <value>the Browser identifier</value>
        public string Browser { get; set; }
        /// <summary>
        /// Browser Engine Agent
        /// </summary>
        /// <value>browser engine Agent</value>
        public string UserAgent { get; set; }
        /// <summary>
        /// Type of client Device
        /// </summary>
        /// <value>represent device type <see>XDeviceType</see></value>
        public XDeviceType DeviceType { get; set; }
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xModels\Dtos\XFileDto.cs

using System;
using System.ComponentModel.DataAnnotations;
using xCommons.Constants;
using xModels.Base;

namespace xModels.Dtos {
    public partial class XFileDto : XBaseDto {
        [Required]
        public string AuthorId { get; set; }

        public XFileType Type { get; set; }

        [Required]
        [StringLength (255)]
        public string Name { get; set; }

        [StringLength (255)]
        public string Thumb { get; set; }

        [Required]
        [StringLength (255)]
        public string Path { get; set; }

        [StringLength (255)]
        public string ThumbPath { get; set; }

        [Required]
        public DateTime UploadedOn { get; set; }
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xModels\Dtos\XObjectResponseResult.cs

namespace xModels.Dtos {
    /// <summary>
    /// Some Requests Get Object Response Result of Data ...
    /// </summary>
    public struct XObjectResponseResult<T> {

        public XObjectResponseResult (T responseObject, string responseText) {
            this.Object = responseObject;
            this.Text = responseText;
        }

        public T Object { get; }

        public string Text { get; }
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xModels\Dtos\XPersonDto.cs

using xModels.Base;

namespace xModels.Dtos
{
    /// <summary>
    /// Since in Many Cases we have to Retrieve Specified User's Minimal
    /// Infos for Handle Data Transfering, this Dto is Used ...
    /// </summary>
    public class XPersonDto : XBaseDto
    {
        public string Username { get; set; }
        public string Firstname { get; set; }
        public string Lastname { get; set; }
        public string Avatar { get; set; }
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xModels\Dtos\XQuery.cs

using xModels.Base;

namespace xModels.Dtos {
    /// <summary>
    /// Request a Page of Data Based on Query ...
    /// this can used in every Data Providers ...
    /// </summary>
    public class XQuery : XBaseDto {
        /// <summary>
        /// an string for filtering results
        /// </summary>
        /// <value></value>
        public string Filter { get; set; } = null;

        /// <summary>
        /// determines fully load object with it's relational fields or not
        /// </summary>
        /// <value></value>
        public bool ContainsDetail { get; set; } = false;

        /// <summary>
        /// specifiy sorting of items
        /// </summary>
        /// <returns></returns>
        public string SortBy { get; set; } = nameof (XBaseIntIDEntity.Id);

        /// <summary>
        /// specify sorting direction
        /// </summary>
        /// <value></value>
        public bool IsAscending { get; set; } = true;

        /// <summary>
        /// specify page number
        /// </summary>
        /// <value></value>
        public int Page { get; set; } = 1;

        /// <summary>
        /// specify page size
        /// </summary>
        /// <value></value>
        public int PageSize { get; set; }
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xModels\Dtos\XQueryResult.cs

using System.Collections.Generic;
using xModels.Base;

namespace xModels.Dtos {
    /// <summary>
    /// Result of a Requested Page of Data Based on Query ...
    /// this can used in every Data Providers ...
    /// </summary>
    public class XQueryResult<T> : XBaseDto {
        /// <summary>
        /// a collection of items for a page ...
        /// </summary>
        /// <value></value>
        public IEnumerable<T> Items { get; set; }

        /// <summary>
        /// Current Page Number ...
        /// </summary>
        /// <value></value>
        public long Page { get; set; }

        /// <summary>
        /// Current Page Size ...
        /// </summary>
        /// <value></value>
        public long PageSize { get; set; }

        /// <summary>
        /// Total Pages ...
        /// </summary>
        /// <value></value>
        public long TotalPages { get; set; }

        /// <summary>
        /// Total Filtered Items Pages Count ...
        /// </summary>
        /// <value></value>
        public int TotalFilteredPages { get; set; }

        /// <summary>
        /// Total Filtered Items ...
        /// </summary>
        /// <value></value>
        public long TotalFilteredItems { get; set; }

        /// <summary>
        /// Total Exists Items ...
        /// </summary>
        /// <value></value>
        public long TotalItems { get; set; }
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xModels\Dtos\XResourceDto.cs

using System.Collections.Generic;
using xModels.Base;

namespace xModels.Dtos
{
    public class XLocaleResourceDto : XBaseDto
    {
        public string Language { get; set; }
        public string Value { get; set; }
    }

    public class XResourceDto : XBaseDto
    {
        public string Resource { get; set; }
        public IEnumerable<XLocaleResourceDto> Locales { get; set; } = new HashSet<XLocaleResourceDto>();
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xModels\Dtos\XValidateRevisionRequest.cs

using System.ComponentModel.DataAnnotations;

namespace xModels.Dtos {
    /// <summary>
    /// in some cases we have to validate a revision of request, this is a model 
    /// which used to request a revision validator ...
    /// </summary>
    public class XValidateRevisionRequest {
        [Required]
        public string Revision { get; set; }
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xModels\Extensions\DIExtensions.cs

using Microsoft.Extensions.DependencyInjection;
using xCommons.Extensions;
using xExceptions.Constants;
using xModels.Base;
using xModels.Interfaces;

namespace xModels.Extensions {
    public static class DIExtensions {
        /// <summary>
        /// Register an Specific Store in DI ...
        /// </summary>
        /// <param name="services">DI service collection ...</param>
        /// <param name="store">an implementation of inetrface of store ...</param>
        /// <param name="lifeTime">service lifetime</param>
        /// <typeparam name="TImplementation">implementation of TType ...</typeparam>
        /// <typeparam name="TType">an inetrface which implements IXBaseStore<TStoreItemDto, TKey></typeparam>
        /// <typeparam name="TStoreItemDto">type of an instance of XBaseStorable<TKey></typeparam>
        /// <typeparam name="TKey">type of key of StorableItem</typeparam>
        /// <returns></returns>
        public static void AddXStore<TImplementation, TType, TStoreItemDto, TKey> (
            this IServiceCollection services,
            TImplementation store,
            ServiceLifetime lifeTime = ServiceLifetime.Singleton
        )
        where TImplementation : TType
        where TType : IXBaseStore<TStoreItemDto, TKey>
            where TStoreItemDto : XBaseStorableDto<TKey> {
                //
                // Validate Args ...
                if (store.IsNull ()) {
                    throw XException.InvalidArgs
                        .ToException ();
                }

                //
                // Register Service in DI ...
                services.Add (new ServiceDescriptor (typeof (TType), typeof (TImplementation), lifeTime));
            }
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xModels\Extensions\XModelExtensions.cs

using System.Collections.Generic;
using System.Linq;
using xCommons.Extensions;
using xModels.Dtos;

namespace xModels.Extensions
{
    public static class XModelExtensions
    {
        /// <summary>
        /// Check to XDevice instance to be same or not
        /// </summary>
        /// <param name="source"></param>
        /// <param name="dest"></param>
        /// <returns></returns>
        public static bool IsSameAs(this XDeviceDto source, XDeviceDto dest)
        {
            //
            if (source.IsNull() ||
                dest.IsNull())
            {
                return false;
            }

            //
            var isSame = source.Os.ToNormalString() == dest.Os.ToNormalString() &&
                source.OsVersion.ToNormalString() == dest.OsVersion.ToNormalString() &&
                source.Browser.ToNormalString() == dest.Browser.ToNormalString() &&
                source.UserAgent.ToNormalString() == dest.UserAgent.ToNormalString() &&
                source.DeviceType == dest.DeviceType;

            //
            return isSame;
        }

        public static IEnumerable<T> AsEnumerable<T, TKey, TIndex>(
            this IEnumerable<XBaseIndexedDto<T, TKey, TIndex>> source
        )
        {
            return source.Select(i => i.Item);
        }
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xModels\Interfaces\IXAuditable.cs

using System;

namespace xModels.Interfaces {
    /// <summary>
    /// Some times we need to wrap Entities by some logs or audits ...
    /// this class provide Audit fields for an Auditable Entity ...
    /// </summary>
    public interface IXAuditable {
        string UserAgent { get; }
        string UserIp { get; }
        DateTime TransactionTime { get; }
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xModels\Interfaces\IXBaseStore.cs

using System;
using System.Collections.Generic;
using System.Linq.Expressions;
using System.Threading.Tasks;
using xModels.Base;

namespace xModels.Interfaces {
    public interface IXBaseStore<T, TKey> where T : XBaseStorableDto<TKey> {
        //
        #region Retrieve ...
        /// <summary>
        /// Retrieve all Exists Items ...
        /// </summary>
        /// <returns></returns>
        Task<IEnumerable<T>> GetAll ();

        /// <summary>
        /// Retrieve specific Item by key ...
        /// </summary>
        /// <param name="key"></param>
        /// <returns></returns>
        Task<T> Get (TKey key);

        /// <summary>
        /// retrieve items based on specific condition ...
        /// </summary>
        /// <param name="condition"></param>
        /// <returns></returns>
        Task<IEnumerable<T>> FindMany (Expression<Func<T, bool>> condition);

        /// <summary>
        /// retrieve item based on specific condition ...
        /// </summary>
        /// <param name="condition"></param>
        /// <returns></returns>
        Task<T> FindOne (Expression<Func<T, bool>> condition);
        #endregion

        //
        #region Add ...
        /// <summary>
        /// add specific item to Store ...
        /// </summary>
        /// <param name="item"></param>
        /// <returns></returns>
        Task<bool> Add (T item);

        /// <summary>
        /// Add a Collection of Items on Store ...
        /// </summary>
        /// <param name="items"></param>
        /// <returns></returns>
        Task<bool> AddMany (XBaseRangeRequest<T> items);
        #endregion

        //
        #region Remove ...
        /// <summary>
        /// Remove an item from store ...
        /// </summary>
        /// <param name="item"></param>
        /// <returns></returns>
        Task<bool> Remove (T item);

        /// <summary>
        /// remove an item by it's Key ...
        /// </summary>
        /// <param name="key"></param>
        /// <returns></returns>
        Task<bool> RemoveByKey (TKey key);
        
        /// <summary>
        /// remove a collection of items at once ...
        /// </summary>
        /// <param name="items"></param>
        /// <returns></returns>
        Task<bool> RemoveMany(XBaseRangeRequest<T> items);
        #endregion

        //
        #region Update ...
        /// <summary>
        /// Update Exists Item in store ...
        /// </summary>
        /// <param name="item"></param>
        /// <param name="propertyWhiteList"></param>
        /// <param name="propertyBlackList"></param>
        /// <param name="propertyValueProviders"></param>
        /// <param name="updateWithNullOrEmptyValues"></param>
        /// <returns></returns>
        Task<T> Update (
            T item,
            ICollection<string> propertyWhiteList = null,
            ICollection<string> propertyBlackList = null,
            ICollection<KeyValuePair<string, Func<T, object>>> propertyValueProviders = null,
            bool updateWithNullOrEmptyValues = false
        );

        /// <summary>
        /// Update a Collection of Exists Items ...
        /// </summary>
        /// <param name="items"></param>
        /// <param name="propertyWhiteList"></param>
        /// <param name="propertyBlackList"></param>
        /// <param name="propertyValueProviders"></param>
        /// <param name="updateWithNullOrEmptyValues"></param>
        /// <returns></returns>
        Task<bool> UpdateMany (
            XBaseRangeRequest<T> items,
            ICollection<string> propertyWhiteList = null,
            ICollection<string> propertyBlackList = null,
            ICollection<KeyValuePair<string, Func<T, object>>> propertyValueProviders = null,
            bool updateWithNullOrEmptyValues = false
        );
        #endregion

        //
        #region Exists ...
        /// <summary>
        /// retrieve item(s) exists based on specific condition ...
        /// </summary>
        /// <param name="condition"></param>
        /// <returns></returns>
        Task<bool> IsExists (Expression<Func<T, bool>> condition);

        /// <summary>
        /// is exists an item by providing it's key ...
        /// </summary>
        /// <param name="key"></param>
        /// <returns></returns>
        Task<bool> IsExistsByKey (TKey key);
        #endregion

        //
        #region Count ...
        /// <summary>
        /// Count Exists items ...
        /// </summary>
        /// <returns></returns>
        Task<int> Count ();
        #endregion        
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xModels\Interfaces\IXBaseStoreEvents.cs

using System;
using System.Collections.Generic;
using xModels.Base;

namespace xModels.Interfaces
{
    public interface IXBaseStoreEvents<T, TKey> where T : XBaseStorableDto<TKey>
    {
        //
        void AddEvent(XBaseStorableDtoEventModel<T> model);
        void UpdateEvent(XBaseStorableDtoEventModel<T> model);
        void RemoveEvent(XBaseStorableDtoEventModel<T> model);

        //
        void AddManyEvent(XBaseStorableDtoEventModel<IEnumerable<T>> model);
        void UpdateManyEvent(XBaseStorableDtoEventModel<IEnumerable<T>> model);
        void RemoveManyEvent(XBaseStorableDtoEventModel<IEnumerable<T>> model);

        //
        IObservable<XBaseStorableDtoEventModel<T>> OnAddObservable { get; }
        IObservable<XBaseStorableDtoEventModel<T>> OnUpdateObservable { get; }
        IObservable<XBaseStorableDtoEventModel<T>> OnRemoveObservable { get; }

        //
        IObservable<XBaseStorableDtoEventModel<IEnumerable<T>>> OnAddManyObservable { get; }
        IObservable<XBaseStorableDtoEventModel<IEnumerable<T>>> OnUpdateManyObservable { get; }
        IObservable<XBaseStorableDtoEventModel<IEnumerable<T>>> OnRemoveManyObservable { get; }

    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xModels\Providers\XBaseInMemoryStore.cs

using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Threading.Tasks;
using xCommons.Extensions;
using xModels.Base;
using xModels.Interfaces;

namespace xModels.Providers
{
    public abstract class XBaseInMemoryStore<T, TKey> : IXBaseStore<T, TKey>
        where T : XBaseStorableDto<TKey>
    {
        /// <summary>
        /// this is main store of items ...
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <returns></returns>
        private static ConcurrentBag<T> STORE = new ConcurrentBag<T>();

        //
        private readonly IXBaseStoreEvents<T, TKey> events;

        //
        #region Constructor ...
        protected XBaseInMemoryStore(
            IXBaseStoreEvents<T, TKey> events = null
        )
        {
            this.events = events;
        }
        #endregion

        //
        #region Retrieve ...
        /// <summary>
        /// Retrieve all Exists Items ...
        /// </summary>
        /// <returns></returns>
        public Task<IEnumerable<T>> GetAll()
        {
            //
            var result = STORE.AsEnumerable();
            return Task.FromResult(result);
        }

        /// <summary>
        /// Retrieve specific Item by key ...
        /// </summary>
        /// <param name="key"></param>
        /// <returns></returns>
        public Task<T> Get(TKey key)
        {
            //
            return IsExistsByKey(key)
                .ContinueWith(isExistsTask =>
                {
                    //
                    var isExists = isExistsTask
                        .RunTask();

                    //
                    if (!isExists)
                    {
                        return null;
                    }

                    //
                    try
                    {
                        var result = STORE
                            .FirstOrDefault(i => GetKey(i).Equals(key));
                        return result;
                    }
                    catch
                    {
                        return null;
                    }
                });
        }

        /// <summary>
        /// retrieve items based on specific condition ...
        /// </summary>
        /// <param name="condition"></param>
        /// <returns></returns>
        public Task<IEnumerable<T>> FindMany(Expression<Func<T, bool>> condition)
        {
            //
            // Validate Args ...
            if (condition.IsNull())
            {
                return Task.FromResult(new List<T>().AsEnumerable());
            }

            //
            var whereFunc = condition.Compile();
            var result = STORE.Where(whereFunc);

            //
            return Task.FromResult(result);
        }

        /// <summary>
        /// retrieve item based on specific condition ...
        /// </summary>
        /// <param name="condition"></param>
        /// <returns></returns>
        public Task<T> FindOne(Expression<Func<T, bool>> condition)
        {
            //
            // Validate Args ...
            if (condition.IsNull())
            {
                return null;
            }

            //
            var whereFunc = condition.Compile();
            var result = STORE.FirstOrDefault(whereFunc);

            //
            return Task.FromResult(result);
        }
        #endregion

        //
        #region Add ...
        /// <summary>
        /// add specific item to Store ...
        /// </summary>
        /// <param name="item"></param>
        /// <returns></returns>
        public Task<bool> Add(T item)
        {
            //
            // Validate Args ...
            if (item.IsNull() || GetKey(item).IsNull())
            {
                return Task.FromResult(false);
            }

            //
            // Try to add item ...
            return IsExistsByKey(GetKey(item))
                .ContinueWith(isExistsTask =>
                {
                    //
                    // Check item exists in Store or not ...
                    var isExists = isExistsTask.RunTask();
                    if (isExists)
                    {
                        return false;
                    }

                    //
                    // Add Item to Store ...
                    STORE.Add(item);
                    OnAdd(item);

                    //
                    return true;
                });
        }

        /// <summary>
        /// Add a Collection of Items on Store ...
        /// </summary>
        /// <param name="items"></param>
        /// <returns></returns>
        public Task<bool> AddMany(XBaseRangeRequest<T> items)
        {
            //
            // Validate Args ...
            if (
                items.IsNull() ||
                !items.Items.HasChild()
            )
            {
                return Task.FromResult(false);
            }

            //
            // Retrieve Must Add Items ...
            var mustAddItems = items.Items
                .Where(i => !GetKey(i)
                    .IsNull() && !STORE
                    .Any(si => GetKey(i).Equals(GetKey(si)))
                );
            if (!mustAddItems.HasChild())
            {
                return Task.FromResult(false);
            }

            //
            // Add Items ...
            try
            {
                //
                mustAddItems
                    .ToList()
                    .ForEach(mi => STORE.Add(mi));

                //
                OnAddMany(mustAddItems);

                //
                return Task.FromResult(true);
            }
            catch
            {
                return Task.FromResult(false);
            }
        }
        #endregion

        //
        #region Remove ...
        /// <summary>
        /// Remove an item from store ...
        /// </summary>
        /// <param name="item"></param>
        /// <returns></returns>
        public Task<bool> Remove(T item)
        {
            //
            // Validate Args ...
            if (
                item.IsNull() ||
                !STORE
                .Any(i => GetKey(i)
                    .Equals(GetKey(item)))
            )
            {
                return Task.FromResult(false);
            }

            //
            try
            {
                //
                RemoveItemFromStore(item);
                return Task.FromResult(true);
            }
            catch
            {
                return Task.FromResult(false);
            }
        }

        /// <summary>
        /// remove an item by it's Key ...
        /// </summary>
        /// <param name="key"></param>
        /// <returns></returns>
        public Task<bool> RemoveByKey(TKey key)
        {
            return Get(key)
                .ContinueWith(getTask =>
                {
                    //
                    // retrieve item by it's Key ...
                    var item = getTask
                        .RunTask();

                    //
                    // Check item exists ...
                    if (item.IsNull())
                    {
                        return false;
                    }

                    //
                    // Try to remove item ...
                    var result = false;
                    try
                    {
                        //
                        result = Remove(item)
                            .RunTask();
                    }
                    catch
                    {
                        result = false;
                    }

                    //
                    return result;
                });
        }

        /// <summary>
        /// remove a collection of items at once ...
        /// </summary>
        /// <param name="items"></param>
        /// <returns></returns>
        public Task<bool> RemoveMany(XBaseRangeRequest<T> items)
        {
            //
            // Validate Args ...
            if (
                items.IsNull() ||
                !items.Items.HasChild()
            )
            {
                return Task.FromResult(false);
            }

            //
            var mustRemovedItems = items.Items
                .Where(i => STORE
                    .Any(si => GetKey(si).Equals(GetKey(i)))
                );
            if (!mustRemovedItems.HasChild())
            {
                return Task.FromResult(false);
            }

            //
            try
            {
                //
                RemoveItemsFromStore(mustRemovedItems);
                return Task.FromResult(true);
            }
            catch
            {
                return Task.FromResult(false);
            }
        }
        #endregion

        //
        #region Update ...
        /// <summary>
        /// Update Exists Item in store ...
        /// </summary>
        /// <param name="item"></param>
        /// <param name="propertyWhiteList"></param>
        /// <param name="propertyBlackList"></param>
        /// <param name="propertyValueProviders"></param>
        /// <param name="updateWithNullOrEmptyValues"></param>
        /// <returns></returns>
        public Task<T> Update(
            T item,
            ICollection<string> propertyWhiteList = null,
            ICollection<string> propertyBlackList = null,
            ICollection<KeyValuePair<string, Func<T, object>>> propertyValueProviders = null,
            bool updateWithNullOrEmptyValues = false
        )
        {
            return Get(GetKey(item))
                .ContinueWith(getTask =>
                {
                    //
                    var existsItem = getTask
                        .RunTask();

                    //
                    // Validate item Exists ...
                    if (existsItem.IsNull())
                    {
                        return null;
                    }

                    //
                    try
                    {
                        //
                        var updatedItem = existsItem;
                        updatedItem.UpdateData(
                            updateWith: item,
                            propertyWhiteList: propertyWhiteList,
                            propertyBlackList: propertyBlackList,
                            propertyValueProviders: propertyValueProviders,
                            updateWithNullOrEmptyValues: updateWithNullOrEmptyValues,
                            throwExceptionOnFails: true
                        );

                        //
                        RemoveItemFromStore(existsItem);
                        STORE.Add(updatedItem);
                        OnUpdate(item);

                        //
                        return updatedItem;
                    }
                    catch
                    {
                        return null;
                    }
                });
        }

        /// <summary>
        /// Update a Collection of Exists Items ...
        /// </summary>
        /// <param name="items"></param>
        /// <param name="propertyWhiteList"></param>
        /// <param name="propertyBlackList"></param>
        /// <param name="propertyValueProviders"></param>
        /// <param name="updateWithNullOrEmptyValues"></param>
        /// <returns></returns>
        public Task<bool> UpdateMany(
            XBaseRangeRequest<T> items,
            ICollection<string> propertyWhiteList = null,
            ICollection<string> propertyBlackList = null,
            ICollection<KeyValuePair<string, Func<T, object>>> propertyValueProviders = null,
            bool updateWithNullOrEmptyValues = false
        )
        {
            //
            // Validate Args ...
            if (
                items.IsNull() ||
                !items.Items.HasChild()
            )
            {
                return Task.FromResult(false);
            }

            //
            // retrieve must updated items ...
            var mustUpdateItems = items
                .Items
                .Where(i => STORE
                    .Any(
                        si => GetKey(i).Equals(GetKey(si)))
                );
            if (!mustUpdateItems.HasChild())
            {
                return Task.FromResult(false);
            }

            //
            // Do Tasks ...
            var mustUpdateTasks = mustUpdateItems.Select(i => Update(
                i,
                propertyWhiteList: propertyWhiteList,
                propertyBlackList: propertyBlackList,
                propertyValueProviders: propertyValueProviders,
                updateWithNullOrEmptyValues: updateWithNullOrEmptyValues
            ));
            return Task.WhenAll(mustUpdateTasks)
                .ContinueWith(updateTasks =>
                {
                    //
                    var updatedItems = updateTasks
                        .RunTask();

                    //
                    if (!updatedItems.HasChild())
                    {
                        return false;
                    }
                    else
                    {
                        //
                        OnUpdateMany(mustUpdateItems);
                        return true;
                    }
                });
        }
        #endregion

        //
        #region Exists ...
        /// <summary>
        /// retrieve item(s) exists based on specific condition ...
        /// </summary>
        /// <param name="condition"></param>
        /// <returns></returns>
        public Task<bool> IsExists(Expression<Func<T, bool>> condition)
        {
            //
            // Validate Args ...
            if (condition.IsNull())
            {
                return Task.FromResult(false);
            }

            //
            var whereFunc = condition.Compile();
            var result = STORE.Any(whereFunc);

            //
            return Task.FromResult(result);
        }

        /// <summary>
        /// is exists an item by providing it's key ...
        /// </summary>
        /// <param name="key"></param>
        /// <returns></returns>
        public Task<bool> IsExistsByKey(TKey key)
        {
            return Task.Run(() =>
            {
                return STORE.Any(i => GetKey(i).Equals(key));
            });
        }
        #endregion

        //
        #region Count ...
        /// <summary>
        /// Count Exists items ...
        /// </summary>
        /// <returns></returns>
        public Task<int> Count()
        {
            //
            var result = STORE.Count();
            return Task.FromResult(result);
        }
        #endregion

        //
        #region Keys ...
        /// <summary>
        /// set Object Key ...
        /// </summary>
        /// <param name="item"></param>
        /// <param name="id"></param>
        public void SetKey(
            ref T item,
            TKey id
        )
        {
            //
            var props = item.GetType().GetProperties();
            var keyProp = props.FirstOrDefault(p => p.Name == "Id");
            if (keyProp.IsNull())
            {
                return;
            }

            //
            Type t = Nullable.GetUnderlyingType(keyProp.PropertyType) ?? keyProp.PropertyType;
            object safeValue = (id == null) ? null : Convert.ChangeType(id, t);
            keyProp.SetValue(item, safeValue, null);
        }

        /// <summary>
        /// Get Object Key ...
        /// </summary>
        /// <param name="item"></param>
        /// <returns></returns>
        public TKey GetKey(T item)
        {
            //
            var props = item.GetType().GetProperties();
            var keyProp = props.FirstOrDefault(p => p.Name == "Id");

            //
            var keyString = string.Empty;
            if (keyProp.IsNull())
            {
                keyString = string.Empty;
            }
            else
            {
                keyString = keyProp.GetValue(item).ToString();
            }

            //
            if (keyString.IsNullOrEmpty())
            {
                return default(TKey);
            }

            //
            // Prevent Deserializing issues throug JsonReader ...
            if (keyString.IsGuid() && typeof(TKey) == typeof(Guid))
            {
                return item.Id;
            }

            //
            TKey result;
            try
            {
                result = keyString.FromJSON<TKey>();
            }
            catch
            {
                result = keyString.ConvertTo<TKey>();
            }
            return result;
        }
        #endregion

        //
        #region Private ...
        private void RemoveItemFromStore(T item)
        {
            //
            STORE = new ConcurrentBag<T>(
                STORE.Except(new[] { item })
            );

            //
            OnRemove(item);
        }

        private void RemoveItemsFromStore(IEnumerable<T> items)
        {
            //
            STORE = new ConcurrentBag<T>(
                STORE.Except(items)
            );

            //
            OnRemoveMany(items);
        }

        //
        #region Event Notifiers ...
        private void OnAdd(T item)
        {
            //
            if (!events.IsNull())
            {
                events.AddEvent(new XBaseStorableDtoEventModel<T>(item));
            }
        }
        private void OnUpdate(T item)
        {
            //
            if (!events.IsNull())
            {
                events.UpdateEvent(new XBaseStorableDtoEventModel<T>(item));
            }
        }

        private void OnRemove(T item)
        {
            //
            if (!events.IsNull())
            {
                events.RemoveEvent(new XBaseStorableDtoEventModel<T>(item));
            }
        }

        private void OnAddMany(IEnumerable<T> items)
        {
            //
            if (!events.IsNull())
            {
                events.AddManyEvent(new XBaseStorableDtoEventModel<IEnumerable<T>>(items));
            }
        }

        private void OnUpdateMany(IEnumerable<T> items)
        {
            //
            if (!events.IsNull())
            {
                events.UpdateManyEvent(new XBaseStorableDtoEventModel<IEnumerable<T>>(items));
            }
        }

        private void OnRemoveMany(IEnumerable<T> items)
        {
            //
            if (!events.IsNull())
            {
                events.RemoveManyEvent(new XBaseStorableDtoEventModel<IEnumerable<T>>(items));
            }
        }
        #endregion
        #endregion
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xPushService\Base\XBaseDtoHub.cs

using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.AspNetCore.SignalR;
using Microsoft.Extensions.Logging;
using xCommons.Extensions;
using xModels.Base;
using xPushService.Constants;
using xPushService.Interfaces;

namespace xPushService.Base
{
    public abstract class XBaseDtoHub<TEntity, TDto, TKey> : XBaseHub, IXBaseDtoHub<TEntity, TDto, TKey>
    where TEntity : XBaseEntity<TKey>
    where TDto : XBaseEntityDto<TKey>
    {
        //
        #region Constructor ...
        protected XBaseDtoHub(ILogger<XBaseHub> logger) : base(logger)
        { }
        #endregion

        //
        #region Actions ...
        /// <summary>
        /// Notify a New Item added ...
        /// </summary>
        /// <param name="item"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public async Task Add(
            TDto item,
            CancellationToken cancellationToken = default
        )
        {
            //
            var connectionId = Context.ConnectionId;
            if (!connectionId.IsNullOrEmpty())
            {
                //
                await Clients
                    .AllExcept(connectionId)
                    .SendAsync(
                        XBaseEntityHubAction.Add.GetStringValue(),
                        item.ToJSON(camelCase: true),
                        connectionId,
                        cancellationToken
                    );
            }
        }

        /// <summary>
        /// Notify a New Item added ...
        /// </summary>
        /// <param name="item"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public async Task AddOrUpdate(
            TDto item,
            CancellationToken cancellationToken = default
        )
        {
            //
            var connectionId = Context.ConnectionId;
            if (!connectionId.IsNullOrEmpty())
            {
                //
                await Clients
                    .AllExcept(connectionId)
                    .SendAsync(
                        XBaseEntityHubAction.AddOrUpdate.GetStringValue(),
                        item.ToJSON(camelCase: true),
                        connectionId,
                        cancellationToken
                    );
            }
        }

        /// <summary>
        /// Notify Add Many Items ...
        /// </summary>
        /// <param name="items"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public async Task AddMany(
            IEnumerable<TDto> items,
            CancellationToken cancellationToken = default
        )
        {
            //
            var connectionId = Context.ConnectionId;
            if (!connectionId.IsNullOrEmpty())
            {
                //
                await Clients
                    .AllExcept(connectionId)
                    .SendAsync(
                        XBaseEntityHubAction.AddOrUpdate.GetStringValue(),
                        items.ToJSON(camelCase: true),
                        connectionId,
                        cancellationToken
                    );
            }
        }

        /// <summary>
        /// Notify an Item Deleted ...
        /// </summary>
        /// <param name="item"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public async Task Delete(
            TDto item,
            CancellationToken cancellationToken = default
        )
        {
            //
            var connectionId = Context.ConnectionId;
            if (!connectionId.IsNullOrEmpty())
            {
                //
                await Clients
                    .AllExcept(connectionId)
                    .SendAsync(
                        XBaseEntityHubAction.Delete.GetStringValue(),
                        item.ToJSON(camelCase: true),
                        connectionId,
                        cancellationToken
                    );
            }
        }

        /// <summary>
        /// Notify Delete Many Items ...
        /// </summary>
        /// <param name="items"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public async Task DeleteMany(
            IEnumerable<TDto> items,
            CancellationToken cancellationToken = default
        )
        {
            //
            var connectionId = Context.ConnectionId;
            if (!connectionId.IsNullOrEmpty())
            {
                //
                await Clients
                    .AllExcept(connectionId)
                    .SendAsync(
                        XBaseEntityHubAction.DeleteMany.GetStringValue(),
                        items.ToJSON(camelCase: true),
                        connectionId,
                        cancellationToken
                    );
            }
        }

        /// <summary>
        /// Notify an Item Updated ...
        /// </summary>
        /// <param name="item"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public async Task Update(
            TDto item,
            CancellationToken cancellationToken = default
        )
        {
            //
            var connectionId = Context.ConnectionId;
            if (!connectionId.IsNullOrEmpty())
            {
                //
                await Clients
                    .AllExcept(connectionId)
                    .SendAsync(
                        XBaseEntityHubAction.Update.GetStringValue(),
                        item.ToJSON(camelCase: true),
                        connectionId,
                        cancellationToken
                    );
            }
        }

        /// <summary>
        /// Notify Update Many Items ...
        /// </summary>
        /// <param name="items"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public async Task UpdateMany(
            IEnumerable<TDto> items,
            CancellationToken cancellationToken = default
        )
        {
            //
            var connectionId = Context.ConnectionId;
            if (!connectionId.IsNullOrEmpty())
            {
                //
                await Clients
                    .AllExcept(connectionId)
                    .SendAsync(
                        XBaseEntityHubAction.UpdateMany.GetStringValue(),
                        items.ToJSON(camelCase: true),
                        connectionId,
                        cancellationToken
                    );
            }
        }
        #endregion        
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xPushService\Base\XBaseDtoProvider.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Runtime.CompilerServices;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.AspNetCore.SignalR;
using Microsoft.EntityFrameworkCore.Query;
using xCommons.Extensions;
using xDataService.Configuration;
using xDataService.Interfaces;
using xIdentityService.Interfaces;
using xModels.Base;
using xModels.Dtos;
using xPushService.Constants;
using xPushService.Interfaces;

namespace xPushService.Base
{
    public abstract class XBaseDtoProvider<TEntity, TDto, TKey, THub> : IXBaseDtoProvider<TEntity, TDto, TKey, THub>
    where TEntity : XBaseEntity<TKey>
    where TDto : XBaseEntityDto<TKey>
    where THub : XBaseDtoHub<TEntity, TDto, TKey>
    {
        //
        #region Properties ...
        public IHubContext<THub> Hub { get; }
        public IXIdentityProvider IdentityProvider { get; }
        public XDataServiceConfiguration DataConfiguration { get; }
        public IXBaseRepositoryService<TEntity, TDto, TKey> Service { get; }
        #endregion

        //
        #region Constructor ...
        protected XBaseDtoProvider(
            IHubContext<THub> hub,
            XDataServiceConfiguration dataConfiguration,
            IXBaseRepositoryService<TEntity, TDto, TKey> service,
            IXIdentityProvider identityProvider = null
        )
        {
            //
            Hub = hub;
            Service = service;
            IdentityProvider = identityProvider;
            DataConfiguration = dataConfiguration;
        }
        #endregion

        //
        #region Actions ...
        /// <summary>
        /// add a new Item ...
        /// </summary>
        /// <param name="item"></param>
        /// <param name="saveChanges"></param>
        /// <param name="connectionId"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public virtual async Task<TDto> AddAsync(
            TDto item,
            bool saveChanges = true,
            string connectionId = null,
            CancellationToken cancellationToken = default
        )
        {
            //
            var result = await Service.AddAsync(
                item: item,
                saveChanges: saveChanges,
                cancellationToken: cancellationToken
            );

            //
            var isValid = !result.IsNullOrDefault();
            if (isValid)
            {
                //
                await SendPush(
                    connectionId: connectionId,
                    cancellationToken: cancellationToken,
                    payLoad: result.ToJSON(camelCase: true),
                    action: XBaseEntityHubAction.Add.GetStringValue()
                );
            }

            //
            return result;
        }

        /// <summary>
        /// Update an Item values ...
        /// </summary>
        /// <param name="id"></param>
        /// <param name="item"></param>
        /// <param name="saveChanges"></param>
        /// <param name="connectionId"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public virtual async Task<TDto> UpdateAsync(
            TKey id,
            TDto item,
            bool saveChanges = true,
            string connectionId = null,
            CancellationToken cancellationToken = default
        )
        {
            //
            var result = await Service.UpdateAsync(
                id: id,
                item: item,
                saveChanges: saveChanges,
                cancellationToken: cancellationToken
            );

            //
            var isValid = !result.IsNullOrDefault();
            if (isValid)
            {
                //
                await SendPush(
                    connectionId: connectionId,
                    cancellationToken: cancellationToken,
                    payLoad: result.ToJSON(camelCase: true),
                    action: XBaseEntityHubAction.Update.GetStringValue()
                );
            }

            //
            return result;
        }

        /// <summary>
        /// remove an Item by it's Id ...
        /// </summary>
        /// <param name="id"></param>
        /// <param name="softDelete"></param>
        /// <param name="saveChanges"></param>
        /// <param name="connectionId"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public virtual async Task<TDto> RemoveAsync(
            TKey id,
            bool softDelete = true,
            bool saveChanges = true,
            string connectionId = null,
            CancellationToken cancellationToken = default
        )
        {
            //
            var result = await Service.RemoveAsync(
                id: id,
                softDelete: softDelete,
                saveChanges: saveChanges,
                cancellationToken: cancellationToken
            );

            //
            var isValid = !result.IsNullOrDefault();
            if (isValid)
            {
                //
                await SendPush(
                    connectionId: connectionId,
                    cancellationToken: cancellationToken,
                    payLoad: result.ToJSON(camelCase: true),
                    action: XBaseEntityHubAction.Delete.GetStringValue()
                );
            }

            //
            return result;
        }

        /// <summary>
        /// count all exists Items ...
        /// </summary>
        /// <param name="ignoreSoftDeleteds"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public virtual async Task<int> CountAsync(
            bool ignoreSoftDeleteds = true,
            CancellationToken cancellationToken = default
        )
        {
            //
            var result = await Service.CountAsync(
                cancellationToken: cancellationToken,
                ignoreSoftDeleteds: ignoreSoftDeleteds
            );

            //
            return result;
        }

        /// <summary>
        /// Check an Item exists or not ...
        /// </summary>
        /// <param name="id"></param>
        /// <param name="ignoreSoftDeleteds"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public virtual async Task<bool> IsExistsAsync(
            TKey id,
            bool ignoreSoftDeleteds = true,
            CancellationToken cancellationToken = default
        )
        {
            //
            var result = await Service.IsExistsAsync(
                id: id,
                cancellationToken: cancellationToken,
                ignoreSoftDeleteds: ignoreSoftDeleteds
            );

            //
            return result;
        }

        /// <summary>
        /// retrieve an Item by it's Id ...
        /// </summary>
        /// <param name="id"></param>
        /// <param name="ignoreSoftDeleteds"></param>
        /// <param name="includeBuilder"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public virtual async Task<TDto> GetAsync(
            TKey id,
            bool ignoreSoftDeleteds = true,
            Func<IQueryable<TEntity>, IIncludableQueryable<TEntity, object>> includeBuilder = null,
            CancellationToken cancellationToken = default
        )
        {
            //
            var result = await Service.GetAsync(
                id: id,
                includeBuilder: includeBuilder,
                cancellationToken: cancellationToken,
                ignoreSoftDeleteds: ignoreSoftDeleteds
            );

            //
            return result;
        }

        /// <summary>
        /// retrieve all exists Items ...
        /// </summary>
        /// <param name="ignoreSoftDeleteds"></param>
        /// <param name="orderBuilder"></param>
        /// <param name="includeBuilder"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public virtual async Task<IEnumerable<TDto>> GetAllAsync(
            bool ignoreSoftDeleteds = true,
            Func<IQueryable<TEntity>, IOrderedQueryable<TEntity>> orderBuilder = null,
            Func<IQueryable<TEntity>, IIncludableQueryable<TEntity, object>> includeBuilder = null,
            CancellationToken cancellationToken = default
        )
        {
            //
            var result = await Service.GetAllAsync(
                orderBuilder: orderBuilder,
                includeBuilder: includeBuilder,
                cancellationToken: cancellationToken,
                ignoreSoftDeleteds: ignoreSoftDeleteds
            );

            //
            return result;
        }

        /// <summary>
        /// retrieve all exists Dtos
        /// as Async Enumerable ...
        /// </summary>
        /// <param name="ignoreSoftDeleteds"></param>
        /// <param name="orderBuilder"></param>
        /// <param name="includeBuilder"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public virtual async IAsyncEnumerable<TDto> GetAllAsAsyncEnumerable(
            bool ignoreSoftDeleteds = true,
            Func<IQueryable<TEntity>, IOrderedQueryable<TEntity>> orderBuilder = null,
            Func<IQueryable<TEntity>, IIncludableQueryable<TEntity, object>> includeBuilder = null,
            [EnumeratorCancellation] CancellationToken cancellationToken = default
        )
        {
            //
            var enumerable = Service.GetAllAsAsyncEnumerable(
                orderBuilder: orderBuilder,
                includeBuilder: includeBuilder,
                cancellationToken: cancellationToken,
                ignoreSoftDeleteds: ignoreSoftDeleteds
            );

            //
            await foreach (var dto in enumerable)
            {
                //
                if (cancellationToken.IsCancellationRequested)
                {
                    yield break;
                }

                //
                yield return dto;
            }
        }

        /// <summary>
        /// find an Item by providing a Conditional Expression ...
        /// </summary>
        /// <param name="predicate"></param>
        /// <param name="ignoreSoftDeleteds"></param>
        /// <param name="includeBuilder"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public virtual async Task<TDto> FindOneAsync(
            Expression<Func<TEntity, bool>> predicate,
            bool ignoreSoftDeleteds = true,
            Func<IQueryable<TEntity>, IIncludableQueryable<TEntity, object>> includeBuilder = null,
            CancellationToken cancellationToken = default
        )
        {
            //
            var result = await Service.FindOneAsync(
                predicate: predicate,
                includeBuilder: includeBuilder,
                cancellationToken: cancellationToken,
                ignoreSoftDeleteds: ignoreSoftDeleteds
            );

            //
            return result;
        }

        /// <summary>
        /// find a collection of Items by proving a Conditional Expression ...
        /// </summary>
        /// <param name="predicate"></param>
        /// <param name="ignoreSoftDeleteds"></param>
        /// <param name="orderBuilder"></param>
        /// <param name="includeBuilder"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public virtual async Task<IEnumerable<TDto>> FindManyAsync(
            Expression<Func<TEntity, bool>> predicate,
            bool ignoreSoftDeleteds = true,
            Func<IQueryable<TEntity>, IOrderedQueryable<TEntity>> orderBuilder = null,
            Func<IQueryable<TEntity>, IIncludableQueryable<TEntity, object>> includeBuilder = null,
            CancellationToken cancellationToken = default
        )
        {
            //
            var result = await Service.FindManyAsync(
                predicate: predicate,
                orderBuilder: orderBuilder,
                includeBuilder: includeBuilder,
                cancellationToken: cancellationToken,
                ignoreSoftDeleteds: ignoreSoftDeleteds
            );

            //
            return result;
        }

        /// <summary>
        /// retrieve Items based on XQuery Pagination structure ...
        /// </summary>
        /// <param name="query"></param>
        /// <param name="ignoreSoftDeleteds"></param>
        /// <param name="predicate"></param>
        /// <param name="orderBuilder"></param>
        /// <param name="includeBuilder"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public virtual async Task<XQueryResult<TDto>> QueryAsync(
            XQuery query,
            bool ignoreSoftDeleteds = true,
            Expression<Func<TEntity, bool>> predicate = null,
            Func<IQueryable<TEntity>, IOrderedQueryable<TEntity>> orderBuilder = null,
            Func<IQueryable<TEntity>, IIncludableQueryable<TEntity, object>> includeBuilder = null,
            CancellationToken cancellationToken = default
        )
        {
            //
            var result = await Service.QueryAsync(
                query: query,
                predicate: predicate,
                orderBuilder: orderBuilder,
                includeBuilder: includeBuilder,
                cancellationToken: cancellationToken,
                ignoreSoftDeleteds: ignoreSoftDeleteds
            );

            //
            return result;
        }
        #endregion    

        //
        #region Hub Actions ...
        /// <summary>
        /// Send Custom Push Message ...
        /// </summary>
        /// <param name="action"></param>
        /// <param name="payLoad"></param>
        /// <param name="connectionId"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public async Task SendPush(
            string action,
            string payLoad,
            string connectionId = null,
            CancellationToken cancellationToken = default
        )
        {
            //
            var actions = new List<string>
            {
                XBaseEntityHubAction.Add.GetStringValue(),
                XBaseEntityHubAction.Update.GetStringValue(),
                XBaseEntityHubAction.Delete.GetStringValue(),
                XBaseEntityHubAction.AddMany.GetStringValue(),
                XBaseEntityHubAction.DeleteMany.GetStringValue(),
                XBaseEntityHubAction.UpdateMany.GetStringValue(),
                XBaseEntityHubAction.AddOrUpdate.GetStringValue(),
            };

            //
            // Validate ...
            var isValid =
                !Hub.IsNull() &&
                !action.IsNullOrEmpty() &&
                !payLoad.IsNullOrEmpty() &&
                actions.Contains(action);
            if (!isValid)
            {
                return;
            }

            //
            // Retrieve Connection Id ...
            var clients = Hub.Clients.All;
            if (!connectionId.IsNullOrEmpty())
            {
                clients = Hub.Clients.AllExcept(connectionId);
            }

            //
            await clients.SendAsync(
                action,
                payLoad,
                connectionId,
                cancellationToken
            );
        }
        #endregion        
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xPushService\Base\XBaseEntityHub.cs

using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.AspNetCore.SignalR;
using Microsoft.Extensions.Logging;
using xCommons.Extensions;
using xModels.Base;
using xPushService.Constants;
using xPushService.Interfaces;

namespace xPushService.Base
{
    public abstract class XBaseEntityHub<TEntity, TKey> : XBaseHub, IXBaseEntityHub<TEntity, TKey>
    where TEntity : XBaseEntity<TKey>
    {
        //
        #region Constructor ...
        protected XBaseEntityHub(ILogger<XBaseHub> logger) : base(logger)
        { }
        #endregion

        //
        #region Actions ...
        /// <summary>
        /// Notify a New Entity added ...
        /// </summary>
        /// <param name="entity"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public async Task Add(
            TEntity entity,
            CancellationToken cancellationToken = default
        )
        {
            //
            var connectionId = Context.ConnectionId;
            if (!connectionId.IsNullOrEmpty())
            {
                //
                await Clients
                    .AllExcept(connectionId)
                    .SendAsync(
                        XBaseEntityHubAction.Add.GetStringValue(),
                        entity.ToJSON(camelCase: true),
                        connectionId,
                        cancellationToken
                    );
            }
        }

        /// <summary>
        /// Notify a New Entity added ...
        /// </summary>
        /// <param name="entity"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public async Task AddOrUpdate(
            TEntity entity,
            CancellationToken cancellationToken = default
        )
        {
            //
            var connectionId = Context.ConnectionId;
            if (!connectionId.IsNullOrEmpty())
            {
                //
                await Clients
                    .AllExcept(connectionId)
                    .SendAsync(
                        XBaseEntityHubAction.AddOrUpdate.GetStringValue(),
                        entity.ToJSON(camelCase: true),
                        connectionId,
                        cancellationToken
                    );
            }
        }

        /// <summary>
        /// Notify Add Many Entities ...
        /// </summary>
        /// <param name="entities"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public async Task AddMany(
            IEnumerable<TEntity> entities,
            CancellationToken cancellationToken = default
        )
        {
            //
            var connectionId = Context.ConnectionId;
            if (!connectionId.IsNullOrEmpty())
            {
                //
                await Clients
                    .AllExcept(connectionId)
                    .SendAsync(
                        XBaseEntityHubAction.AddOrUpdate.GetStringValue(),
                        entities.ToJSON(camelCase: true),
                        connectionId,
                        cancellationToken
                    );
            }
        }

        /// <summary>
        /// Notify an Entity Deleted ...
        /// </summary>
        /// <param name="entity"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public async Task Delete(
            TEntity entity,
            CancellationToken cancellationToken = default
        )
        {
            //
            var connectionId = Context.ConnectionId;
            if (!connectionId.IsNullOrEmpty())
            {
                //
                await Clients
                    .AllExcept(connectionId)
                    .SendAsync(
                        XBaseEntityHubAction.Delete.GetStringValue(),
                        entity.ToJSON(camelCase: true),
                        connectionId,
                        cancellationToken
                    );
            }
        }

        /// <summary>
        /// Notify Delete Many Entities ...
        /// </summary>
        /// <param name="entities"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public async Task DeleteMany(
            IEnumerable<TEntity> entities,
            CancellationToken cancellationToken = default
        )
        {
            //
            var connectionId = Context.ConnectionId;
            if (!connectionId.IsNullOrEmpty())
            {
                //
                await Clients
                    .AllExcept(connectionId)
                    .SendAsync(
                        XBaseEntityHubAction.DeleteMany.GetStringValue(),
                        entities.ToJSON(camelCase: true),
                        connectionId,
                        cancellationToken
                    );
            }
        }

        /// <summary>
        /// Notify an Entity Updated ...
        /// </summary>
        /// <param name="entity"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public async Task Update(
            TEntity entity,
            CancellationToken cancellationToken = default
        )
        {
            //
            var connectionId = Context.ConnectionId;
            if (!connectionId.IsNullOrEmpty())
            {
                //
                await Clients
                    .AllExcept(connectionId)
                    .SendAsync(
                        XBaseEntityHubAction.Update.GetStringValue(),
                        entity.ToJSON(camelCase: true),
                        connectionId,
                        cancellationToken
                    );
            }
        }

        /// <summary>
        /// Notify Update Many Entities ...
        /// </summary>
        /// <param name="entities"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public async Task UpdateMany(
            IEnumerable<TEntity> entities,
            CancellationToken cancellationToken = default
        )
        {
            //
            var connectionId = Context.ConnectionId;
            if (!connectionId.IsNullOrEmpty())
            {
                //
                await Clients
                    .AllExcept(connectionId)
                    .SendAsync(
                        XBaseEntityHubAction.UpdateMany.GetStringValue(),
                        entities.ToJSON(camelCase: true),
                        connectionId,
                        cancellationToken
                    );
            }
        }
        #endregion
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xPushService\Base\XBaseEntityProvider.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.AspNetCore.SignalR;
using Microsoft.EntityFrameworkCore.Query;
using xCommons.Extensions;
using xDataService.Configuration;
using xDataService.Interfaces;
using xIdentityService.Interfaces;
using xModels.Base;
using xModels.Dtos;
using xPushService.Constants;
using xPushService.Interfaces;

namespace xPushService.Base
{
    public abstract class XBaseEntityProvider<TEntity, TKey, THub> : IXBaseEntityProvider<TEntity, TKey, THub>
    where TEntity : XBaseEntity<TKey>
    where THub : XBaseEntityHub<TEntity, TKey>
    {
        //
        #region Properties ...
        public IHubContext<THub> Hub { get; }
        public IXIdentityProvider IdentityProvider { get; }
        public IXBaseRepository<TEntity, TKey> Repository { get; }
        public XDataServiceConfiguration DataConfiguration { get; }
        #endregion

        //
        #region Constructor ...
        protected XBaseEntityProvider(
            IHubContext<THub> hub,
            IXBaseRepository<TEntity, TKey> repository,
            XDataServiceConfiguration dataConfiguration,
            IXIdentityProvider identityProvider = null
        )
        {
            //
            Hub = hub;
            Repository = repository;
            IdentityProvider = identityProvider;
            DataConfiguration = dataConfiguration;
        }
        #endregion

        //
        #region Actions ...
        /// <summary>
        /// add a new Item ...
        /// </summary>
        /// <param name="item"></param>
        /// <param name="saveChanges"></param>
        /// <param name="connectionId"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public virtual async Task<TEntity> AddAsync(
            TEntity item,
            bool saveChanges = true,
            string connectionId = null,
            CancellationToken cancellationToken = default
        )
        {
            //
            var result = await Repository.AddAsync(
                item: item,
                saveChanges: saveChanges,
                cancellationToken: cancellationToken
            );

            //
            var isValid = !result.IsNullOrDefault();
            if (isValid)
            {
                //
                await SendPush(
                    connectionId: connectionId,
                    cancellationToken: cancellationToken,
                    payLoad: result.ToJSON(camelCase: true),
                    action: XBaseEntityHubAction.Add.GetStringValue()
                );
            }

            //
            return result;
        }

        /// <summary>
        /// Update an Item values ...
        /// </summary>
        /// <param name="id"></param>
        /// <param name="item"></param>
        /// <param name="saveChanges"></param>
        /// <param name="connectionId"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public virtual async Task<TEntity> UpdateAsync(
            TKey id,
            TEntity item,
            bool saveChanges = true,
            string connectionId = null,
            CancellationToken cancellationToken = default
        )
        {
            //
            var result = await Repository.UpdateAsync(
                id: id,
                item: item,
                saveChanges: saveChanges,
                cancellationToken: cancellationToken
            );

            //
            var isValid = !result.IsNullOrDefault();
            if (isValid)
            {
                //
                await SendPush(
                    connectionId: connectionId,
                    cancellationToken: cancellationToken,
                    payLoad: result.ToJSON(camelCase: true),
                    action: XBaseEntityHubAction.Update.GetStringValue()
                );
            }

            //
            return result;
        }

        /// <summary>
        /// remove an Item by it's Id ...
        /// </summary>
        /// <param name="id"></param>
        /// <param name="softDelete"></param>
        /// <param name="saveChanges"></param>
        /// <param name="connectionId"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public virtual async Task<TEntity> RemoveAsync(
            TKey id,
            bool softDelete = true,
            bool saveChanges = true,
            string connectionId = null,
            CancellationToken cancellationToken = default
        )
        {
            //
            var result = await Repository.RemoveAsync(
                id: id,
                softDelete: softDelete,
                saveChanges: saveChanges,
                cancellationToken: cancellationToken
            );

            //
            var isValid = !result.IsNullOrDefault();
            if (isValid)
            {
                //
                await SendPush(
                    connectionId: connectionId,
                    cancellationToken: cancellationToken,
                    payLoad: result.ToJSON(camelCase: true),
                    action: XBaseEntityHubAction.Delete.GetStringValue()
                );
            }

            //
            return result;
        }

        /// <summary>
        /// count all exists Items ...
        /// </summary>
        /// <param name="ignoreSoftDeleteds"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public virtual async Task<int> CountAsync(
            bool ignoreSoftDeleteds = true,
            CancellationToken cancellationToken = default
        )
        {
            //
            var result = await Repository.CountAsync(
                cancellationToken: cancellationToken,
                ignoreSoftDeleteds: ignoreSoftDeleteds
            );

            //
            return result;
        }

        /// <summary>
        /// Check an Item exists or not ...
        /// </summary>
        /// <param name="id"></param>
        /// <param name="ignoreSoftDeleteds"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public virtual async Task<bool> IsExistsAsync(
            TKey id,
            bool ignoreSoftDeleteds = true,
            CancellationToken cancellationToken = default
        )
        {
            //
            var result = await Repository.IsExistsAsync(
                id: id,
                cancellationToken: cancellationToken,
                ignoreSoftDeleteds: ignoreSoftDeleteds
            );

            //
            return result;
        }

        /// <summary>
        /// retrieve an Item by it's Id ...
        /// </summary>
        /// <param name="id"></param>
        /// <param name="ignoreSoftDeleteds"></param>
        /// <param name="includeBuilder"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public virtual async Task<TEntity> GetAsync(
            TKey id,
            bool ignoreSoftDeleteds = true,
            Func<IQueryable<TEntity>, IIncludableQueryable<TEntity, object>> includeBuilder = null,
            CancellationToken cancellationToken = default
        )
        {
            //
            var result = await Repository.GetAsync(
                id: id,
                includeBuilder: includeBuilder,
                cancellationToken: cancellationToken,
                ignoreSoftDeleteds: ignoreSoftDeleteds
            );

            //
            return result;
        }

        /// <summary>
        /// retrieve all exists Items ...
        /// </summary>
        /// <param name="ignoreSoftDeleteds"></param>
        /// <param name="orderBuilder"></param>
        /// <param name="includeBuilder"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public virtual async Task<IEnumerable<TEntity>> GetAllAsync(
            bool ignoreSoftDeleteds = true,
            Func<IQueryable<TEntity>, IOrderedQueryable<TEntity>> orderBuilder = null,
            Func<IQueryable<TEntity>, IIncludableQueryable<TEntity, object>> includeBuilder = null,
            CancellationToken cancellationToken = default
        )
        {
            //
            var result = await Repository.GetAllAsync(
                orderBuilder: orderBuilder,
                includeBuilder: includeBuilder,
                cancellationToken: cancellationToken,
                ignoreSoftDeleteds: ignoreSoftDeleteds
            );

            //
            return result;
        }

        /// <summary>
        /// find an Item by providing a Conditional Expression ...
        /// </summary>
        /// <param name="predicate"></param>
        /// <param name="ignoreSoftDeleteds"></param>
        /// <param name="includeBuilder"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public virtual async Task<TEntity> FindOneAsync(
            Expression<Func<TEntity, bool>> predicate,
            bool ignoreSoftDeleteds = true,
            Func<IQueryable<TEntity>, IIncludableQueryable<TEntity, object>> includeBuilder = null,
            CancellationToken cancellationToken = default
        )
        {
            //
            var result = await Repository.FindOneAsync(
                predicate: predicate,
                includeBuilder: includeBuilder,
                cancellationToken: cancellationToken,
                ignoreSoftDeleteds: ignoreSoftDeleteds
            );

            //
            return result;
        }

        /// <summary>
        /// find a collection of Items by proving a Conditional Expression ...
        /// </summary>
        /// <param name="predicate"></param>
        /// <param name="ignoreSoftDeleteds"></param>
        /// <param name="orderBuilder"></param>
        /// <param name="includeBuilder"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public virtual async Task<IEnumerable<TEntity>> FindManyAsync(
            Expression<Func<TEntity, bool>> predicate,
            bool ignoreSoftDeleteds = true,
            Func<IQueryable<TEntity>, IOrderedQueryable<TEntity>> orderBuilder = null,
            Func<IQueryable<TEntity>, IIncludableQueryable<TEntity, object>> includeBuilder = null,
            CancellationToken cancellationToken = default
        )
        {
            //
            var result = await Repository.FindManyAsync(
                predicate: predicate,
                orderBuilder: orderBuilder,
                includeBuilder: includeBuilder,
                cancellationToken: cancellationToken,
                ignoreSoftDeleteds: ignoreSoftDeleteds
            );

            //
            return result;
        }

        /// <summary>
        /// retrieve Items based on XQuery Pagination structure ...
        /// </summary>
        /// <param name="query"></param>
        /// <param name="ignoreSoftDeleteds"></param>
        /// <param name="predicate"></param>
        /// <param name="orderBuilder"></param>
        /// <param name="includeBuilder"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public virtual async Task<XQueryResult<TEntity>> QueryAsync(
            XQuery query,
            bool ignoreSoftDeleteds = true,
            Expression<Func<TEntity, bool>> predicate = null,
            Func<IQueryable<TEntity>, IOrderedQueryable<TEntity>> orderBuilder = null,
            Func<IQueryable<TEntity>, IIncludableQueryable<TEntity, object>> includeBuilder = null,
            CancellationToken cancellationToken = default
        )
        {
            //
            var result = await Repository.QueryAsync(
                query: query,
                predicate: predicate,
                orderBuilder: orderBuilder,
                includeBuilder: includeBuilder,
                cancellationToken: cancellationToken,
                ignoreSoftDeleteds: ignoreSoftDeleteds
            );

            //
            return result;
        }
        #endregion

        //
        #region Hub Actions ...
        /// <summary>
        /// Send Custom Push Message ...
        /// </summary>
        /// <param name="action"></param>
        /// <param name="payLoad"></param>
        /// <param name="connectionId"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public async Task SendPush(
            string action,
            string payLoad,
            string connectionId = null,
            CancellationToken cancellationToken = default
        )
        {
            //
            var actions = new List<string>
            {
                XBaseEntityHubAction.Add.GetStringValue(),
                XBaseEntityHubAction.Update.GetStringValue(),
                XBaseEntityHubAction.Delete.GetStringValue(),
                XBaseEntityHubAction.AddMany.GetStringValue(),
                XBaseEntityHubAction.DeleteMany.GetStringValue(),
                XBaseEntityHubAction.UpdateMany.GetStringValue(),
                XBaseEntityHubAction.AddOrUpdate.GetStringValue(),
            };

            //
            // Validate ...
            var isValid =
                !Hub.IsNull() &&
                !action.IsNullOrEmpty() &&
                !payLoad.IsNullOrEmpty() &&
                actions.Contains(action);
            if (!isValid)
            {
                return;
            }

            //
            // Retrieve Connection Id ...
            var clients = Hub.Clients.All;
            if (!connectionId.IsNullOrEmpty())
            {
                clients = Hub.Clients.AllExcept(connectionId);
            }

            //
            await clients.SendAsync(
                action,
                payLoad,
                connectionId,
                cancellationToken
            );
        }
        #endregion        
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xPushService\Base\XBaseHub.cs

using System;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.AspNetCore.SignalR;
using Microsoft.Extensions.Logging;
using xCommons.Extensions;
using xPushService.Constants;
using xPushService.Interfaces;

namespace xPushService.Base
{
    public abstract class XBaseHub : Hub, IXBaseHub
    {
        //
        #region Props ...
        protected readonly ILogger<XBaseHub> logger;
        #endregion

        //
        #region Constructor ...
        public XBaseHub(
            ILogger<XBaseHub> logger
        )
        {
            this.logger = logger;
        }
        #endregion

        //
        #region Overrides ...
        public override async Task OnConnectedAsync()
        {
            //
            var connectionId = Context.ConnectionId;
            if (!connectionId.IsNullOrEmpty())
            {
                //
                // Notify Other Clients Which a new Connection Joins ...
                await Clients.AllExcept(connectionId).SendAsync(XBaseHubAction.NewConnection.GetStringValue(), connectionId);
            }

            //
            await base.OnConnectedAsync();
        }

        public override async Task OnDisconnectedAsync(Exception exception)
        {
            //
            var connectionId = Context.ConnectionId;
            if (!connectionId.IsNullOrEmpty())
            {
                //
                // Notify Other Clients Which a Connection Closed ...
                await Clients.AllExcept(connectionId).SendAsync(XBaseHubAction.ConnectionClosed.GetStringValue(), connectionId);
            }
            await base.OnDisconnectedAsync(exception);
        }
        #endregion

        //
        #region Actions ...
        public async Task SendCustomAction(
            string actionName, 
            string payLoad,
            CancellationToken cancellationToken = default
        )
        {
            //
            var connectionId = Context.ConnectionId;
            await Clients.AllExcept(connectionId).SendAsync(
                actionName, 
                payLoad, 
                connectionId,
                cancellationToken
            );
        }
        #endregion
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xPushService\Base\XBaseProvider.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.AspNetCore.SignalR;
using Microsoft.EntityFrameworkCore.Query;
using xCommons.Extensions;
using xDataService.Configuration;
using xDataService.Interfaces;
using xIdentityService.Interfaces;
using xModels.Base;
using xModels.Dtos;
using xPushService.Constants;
using xPushService.Interfaces;

namespace xPushService.Base
{
    public abstract class XBaseProvider<TEntity, TDto, TKey> : IXBaseProvider<TEntity, TDto, TKey>
    where TEntity : XBaseEntity<TKey>
    where TDto : XBaseEntityDto<TKey>
    {
        //
        #region Props ...
        public IXIdentityProvider IdentityProvider { get; }
        public XDataServiceConfiguration DataConfiguration { get; }
        public IHubContext<XBaseEntityHub<TEntity, TKey>> Hub { get; }
        public IXBaseRepositoryService<TEntity, TDto, TKey> RepositoryService { get; }
        #endregion

        //
        #region Actions ...
        /// <summary>
        /// add a new Dto ...
        /// </summary>
        /// <param name="item"></param>
        /// <param name="saveChanges"></param>
        /// <param name="connectionId"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public async Task<TDto> AddAsync(
            TDto item,
            bool saveChanges = true,
            string connectionId = null,
            CancellationToken cancellationToken = default
        )
        {
            //
            var result = await RepositoryService.AddAsync(
                item: item,
                saveChanges: saveChanges,
                cancellationToken: cancellationToken
            );

            //
            if (!result.IsNullOrDefault())
            {
                //
                await SendPush(
                    action: XBaseEntityHubAction.Add.GetStringValue(),
                    payLoad: result.ToJSON(camelCase: true),
                    connectionId: connectionId
                );
            }

            //
            return result;
        }

        /// <summary>
        /// Update an Dto values ...
        /// </summary>
        /// <param name="id"></param>
        /// <param name="item"></param>
        /// <param name="saveChanges"></param>
        /// <param name="connectionId"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public async Task<TDto> UpdateAsync(
            TKey id,
            TDto item,
            bool saveChanges = true,
            string connectionId = null,
            CancellationToken cancellationToken = default
        )
        {
            //
            var result = await RepositoryService.UpdateAsync(
                id: id,
                item: item,
                saveChanges: saveChanges,
                cancellationToken: cancellationToken
            );

            //
            if (!result.IsNullOrDefault())
            {
                //
                await SendPush(
                    action: XBaseEntityHubAction.Update.GetStringValue(),
                    payLoad: result.ToJSON(camelCase: true),
                    connectionId: connectionId
                );
            }

            //
            return result;
        }

        /// <summary>
        /// remove an Dto by it's Id ...
        /// </summary>
        /// <param name="id"></param>
        /// <param name="softDelete"></param>
        /// <param name="saveChanges"></param>
        /// <param name="connectionId"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public async Task<TDto> RemoveAsync(
            TKey id,
            bool softDelete = true,
            bool saveChanges = true,
            string connectionId = null,
            CancellationToken cancellationToken = default
        )
        {
            //
            var result = await RepositoryService.RemoveAsync(
                id: id,
                softDelete: softDelete,
                saveChanges: saveChanges,
                cancellationToken: cancellationToken
            );

            //
            if (!result.IsNullOrDefault())
            {
                //
                await SendPush(
                    action: XBaseEntityHubAction.Update.GetStringValue(),
                    payLoad: result.ToJSON(camelCase: true),
                    connectionId: connectionId
                );
            }

            //
            return result;
        }

        /// <summary>
        /// count all exists Dtos ...
        /// </summary>
        /// <param name="ignoreSoftDeleteds"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public async Task<int> CountAsync(
            bool ignoreSoftDeleteds = true,
            CancellationToken cancellationToken = default
        )
        {
            //
            var result = await RepositoryService.CountAsync(
                cancellationToken: cancellationToken,
                ignoreSoftDeleteds: ignoreSoftDeleteds
            );

            //
            return result;
        }

        /// <summary>
        /// Check a Dto exists or not ...
        /// </summary>
        /// <param name="id"></param>
        /// <param name="ignoreSoftDeleteds"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public async Task<bool> IsExistsAsync(
            TKey id,
            bool ignoreSoftDeleteds = true,
            CancellationToken cancellationToken = default
        )
        {
            //
            var result = await RepositoryService.IsExistsAsync(
                id: id,
                cancellationToken: cancellationToken,
                ignoreSoftDeleteds: ignoreSoftDeleteds
            );

            //
            return result;
        }

        /// <summary>
        /// retrieve an Dto by it's Id ...
        /// </summary>
        /// <param name="id"></param>
        /// <param name="ignoreSoftDeleteds"></param>
        /// <param name="includeBuilder"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public async Task<TDto> GetAsync(
            TKey id,
            bool ignoreSoftDeleteds = true,
            Func<IQueryable<TEntity>, IIncludableQueryable<TEntity, object>> includeBuilder = null,
            CancellationToken cancellationToken = default
        )
        {
            //
            var result = await RepositoryService.GetAsync(
                id: id,
                includeBuilder: includeBuilder,
                cancellationToken: cancellationToken,
                ignoreSoftDeleteds: ignoreSoftDeleteds
            );

            //
            return result;
        }

        /// <summary>
        /// retrieve all exists Dtos ...
        /// </summary>
        /// <param name="ignoreSoftDeleteds"></param>
        /// <param name="orderBuilder"></param>
        /// <param name="includeBuilder"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public async Task<IEnumerable<TDto>> GetAllAsync(
            bool ignoreSoftDeleteds = true,
            Func<IQueryable<TEntity>, IOrderedQueryable<TEntity>> orderBuilder = null,
            Func<IQueryable<TEntity>, IIncludableQueryable<TEntity, object>> includeBuilder = null,
            CancellationToken cancellationToken = default
        )
        {
            //
            var result = await RepositoryService.GetAllAsync(
                orderBuilder: orderBuilder,
                includeBuilder: includeBuilder,
                cancellationToken: cancellationToken,
                ignoreSoftDeleteds: ignoreSoftDeleteds
            );

            //
            return result;
        }

        /// <summary>
        /// find an Dto by providing a Conditional Expression ...
        /// </summary>
        /// <param name="predicate"></param>
        /// <param name="ignoreSoftDeleteds"></param>
        /// <param name="includeBuilder"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public async Task<TDto> FindOneAsync(
            Expression<Func<TEntity, bool>> predicate,
            bool ignoreSoftDeleteds = true,
            Func<IQueryable<TEntity>, IIncludableQueryable<TEntity, object>> includeBuilder = null,
            CancellationToken cancellationToken = default
        )
        {
            //
            var result = await RepositoryService.FindOneAsync(
                predicate: predicate,
                includeBuilder: includeBuilder,
                cancellationToken: cancellationToken,
                ignoreSoftDeleteds: ignoreSoftDeleteds
            );

            //
            return result;            
        }

        /// <summary>
        /// find a collection of Dtos by proving a Conditional Expression ...
        /// </summary>
        /// <param name="predicate"></param>
        /// <param name="ignoreSoftDeleteds"></param>
        /// <param name="orderBuilder"></param>
        /// <param name="includeBuilder"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public async Task<IEnumerable<TDto>> FindManyAsync(
             Expression<Func<TEntity, bool>> predicate,
             bool ignoreSoftDeleteds = true,
             Func<IQueryable<TEntity>, IOrderedQueryable<TEntity>> orderBuilder = null,
             Func<IQueryable<TEntity>, IIncludableQueryable<TEntity, object>> includeBuilder = null,
             CancellationToken cancellationToken = default
         )
        {
            //
            var result = await RepositoryService.FindManyAsync(
                predicate: predicate,
                orderBuilder: orderBuilder,
                includeBuilder: includeBuilder,
                cancellationToken: cancellationToken,
                ignoreSoftDeleteds: ignoreSoftDeleteds
            );

            //
            return result;               
        }

        /// <summary>
        /// retrieve Dtos based on XQuery Pagination structure ...
        /// </summary>
        /// <param name="query"></param>
        /// <param name="ignoreSoftDeleteds"></param>
        /// <param name="predicate"></param>
        /// <param name="orderBuilder"></param>
        /// <param name="includeBuilder"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public async Task<XQueryResult<TDto>> QueryAsync(
            XQuery query,
            bool ignoreSoftDeleteds = true,
            Expression<Func<TEntity, bool>> predicate = null,
            Func<IQueryable<TEntity>, IOrderedQueryable<TEntity>> orderBuilder = null,
            Func<IQueryable<TEntity>, IIncludableQueryable<TEntity, object>> includeBuilder = null,
            CancellationToken cancellationToken = default
        )
        {
            //
            var result = await RepositoryService.QueryAsync(
                query: query,
                predicate: predicate,
                orderBuilder: orderBuilder,
                includeBuilder: includeBuilder,
                cancellationToken: cancellationToken,
                ignoreSoftDeleteds: ignoreSoftDeleteds
            );

            //
            return result;             
        }
        #endregion

        //
        #region Hub Actions ...
        /// <summary>
        /// Send Custom Push Message ...
        /// </summary>
        /// <param name="action"></param>
        /// <param name="payLoad"></param>
        /// <param name="connectionId"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public async Task SendPush(
            string action,
            string payLoad,
            string connectionId = null,
            CancellationToken cancellationToken = default
        )
        {
            //
            var actions = new List<string>
            {
                XBaseEntityHubAction.Add.GetStringValue(),
                XBaseEntityHubAction.Update.GetStringValue(),
                XBaseEntityHubAction.Delete.GetStringValue(),
                XBaseEntityHubAction.AddMany.GetStringValue(),
                XBaseEntityHubAction.DeleteMany.GetStringValue(),
                XBaseEntityHubAction.UpdateMany.GetStringValue(),
                XBaseEntityHubAction.AddOrUpdate.GetStringValue(),
            };

            //
            // Validate ...
            var isValid =
                !Hub.IsNull() &&
                !action.IsNullOrEmpty() &&
                actions.Contains(action);
            if (!isValid)
            {
                return;
            }

            //
            var clients = Hub.Clients.All;
            if (!connectionId.IsNullOrEmpty())
            {
                clients = Hub.Clients.AllExcept(connectionId);
            }

            //
            try
            {
                //
                await clients.SendAsync(
                    action,
                    payLoad,
                    connectionId,
                    cancellationToken
                );
            }
            catch { }
        }
        #endregion
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xPushService\Base\XBaseWebRTCHub.cs

using System.Threading.Tasks;
using Microsoft.Extensions.Logging;
using xPushService.Interfaces;
using Microsoft.AspNetCore.SignalR;
using xPushService.Constants;
using xCommons.Extensions;
using System.Threading;

namespace xPushService.Base
{
    public abstract class XBaseWebRTCHub : XBaseHub, IXBaseWebRTCHub
    {
        //
        #region Props ...
        #endregion

        //
        #region Constructor ...
        protected XBaseWebRTCHub(
            ILogger<XBaseHub> logger
        ) : base(logger)
        { }
        #endregion

        //
        #region WebRTCActions ...
        /// <summary>
        /// Sending WebRTC Offer To Specified Connection ...
        /// </summary>
        /// <param name="offer"></param>
        /// <param name="to"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public async Task Offer(
            string offer,
            string to,
            CancellationToken cancellationToken = default
        )
        {
            //
            await Clients.Client(to).SendAsync(
                XWebRTCAction.Offer.GetStringValue(), 
                offer,
                cancellationToken
            );
        }

        /// <summary>
        /// Sending WebRTC Answer to Specified Connection ...
        /// </summary>
        /// <param name="answer"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public async Task Answer(
            string answer,
            CancellationToken cancellationToken = default
        )
        {
            //
            await Clients.All.SendAsync(
                XWebRTCAction.Answer.GetStringValue(), 
                answer, 
                Context.ConnectionId,
                cancellationToken
            );
        }

        /// <summary>
        /// Sending WebRTC Candidate to Specified Connecton ...
        /// </summary>
        /// <param name="candidate"></param>
        /// <param name="to"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public async Task Candidate(
            string candidate, 
            string to,
            CancellationToken cancellationToken = default
        )
        {
            //
            string actionName = XWebRTCAction.Candidate.GetStringValue();
            if (!string.IsNullOrEmpty(to))
            {
                //
                await Clients.Client(to).SendAsync(
                    actionName, 
                    candidate, 
                    Context.ConnectionId,
                    cancellationToken
                );
            }
            else
            {
                //
                await Clients.All.SendAsync(
                    actionName, 
                    candidate, 
                    Context.ConnectionId,
                    cancellationToken
                );
            }
        }
        #endregion
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xPushService\Configurations\XPushServiceConfiguration.cs

namespace xPushService.Configurations {
    public partial class XPushServiceConfiguration {
        /// <summary>
        /// Base route of WebSocket Server ...
        /// </summary>
        /// <value>string</value>
        public string BaseRoute { get; set; }

        /// <summary>
        /// determines log level of signalR ...
        /// </summary>
        /// <value></value>
        public object ConnectionLogLevel { get; set; }

        /// <summary>
        /// when client disconnected it's automatically try to reconnect, this
        /// determines max number of try to connect ...
        /// </summary>
        /// <value></value>
        public int PushConnectionMaxRetry { get; set; }

        /// <summary>
        /// add support for message protocol ...
        /// </summary>
        /// <value></value>
        public bool AddSupportMessageProtocol { get; set; }

        /// <summary>
        /// the delay between two connection try ..
        /// </summary>
        /// <value></value>
        public int PushConnectionReconnectDelay { get; set; }
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xPushService\Constants\XPushAction.cs

using xExceptions.Attributes;

namespace xPushService.Constants
{
    public enum XBaseHubAction
    {
        /// <summary>
        /// new Connection Join ...
        /// </summary>
        [StringValue("NewConnection")]
        NewConnection,
        /// <summary>
        /// an Exists Connection Closed ...
        /// </summary>
        [StringValue("ConnectionClosed")]
        ConnectionClosed,
    }

    /// <summary>
    /// All Actions in WebRTC Hubs ...
    /// </summary>
    public enum XWebRTCAction
    {
        //
        [StringValue("Offer")]
        Offer,

        [StringValue("Answer")]
        Answer,

        [StringValue("Candidate")]
        Candidate,
    }

    /// <summary>
    /// Provides All Actions Based on Entities ...
    /// </summary>
    public enum XBaseEntityHubAction
    {
        [StringValue("Add")]
        Add,
        [StringValue("AddOrUpdate")]
        AddOrUpdate,
        [StringValue("AddMany")]
        AddMany,
        [StringValue("Update")]
        Update,
        [StringValue("UpdateMany")]
        UpdateMany,
        [StringValue("Delete")]
        Delete,
        [StringValue("DeleteMany")]
        DeleteMany,
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xPushService\Constants\XPushServiceConstants.cs

namespace xPushService.Constants {
    public partial class XPushServiceConstants {
        public partial struct XConfigurationNodes {
            public const string XPushServiceConfiguration = "PushServiceConfiguration";
        }
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xPushService\Controllers\XBaseProvidedController.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore.Query;
using Microsoft.Extensions.Logging;
using xCommons.Configurations;
using xCommons.Extensions;
using xCommons.Providers;
using xExceptions.Constants;
using xIdentityService.Controllers;
using xIdentityService.Interfaces;
using xModels.Base;
using xModels.Dtos;
using xPushService.Base;
using xPushService.Interfaces;

namespace xPushService.Controllers
{
    [AllowAnonymous]
    public abstract class XBaseProvidedController<TEntity, TDto, TKey, THub> : XBaseIdentityApiV1Controller, IXBaseProvidedController<TEntity, TDto, TKey, THub>
    where TEntity : XBaseEntity<TKey>
    where TDto : XBaseEntityDto<TKey>
    where THub : XBaseDtoHub<TEntity, TDto, TKey>
    {
        private readonly IXBaseProvided<TEntity, TDto, TKey, THub> provider;
        private readonly Func<IQueryable<TEntity>, IOrderedQueryable<TEntity>> defaultOrderBuilder;
        private readonly Func<IQueryable<TEntity>, IIncludableQueryable<TEntity, object>> defaultIncludeBuilder;

        protected XBaseProvidedController(
            ILogger<XBaseProvidedController<TEntity, TDto, TKey, THub>> logger,
            XAppConfiguration appConfiguration,
            IXIdentityProvider identityProvider,
            XValidationProvider validationProvider,
            IXBaseProvided<TEntity, TDto, TKey, THub> provider,
            Func<IQueryable<TEntity>, IOrderedQueryable<TEntity>> defaultOrderBuilder = null,
            Func<IQueryable<TEntity>, IIncludableQueryable<TEntity, object>> defaultIncludeBuilder = null
        ) : base(
            logger,
            appConfiguration,
            identityProvider,
            validationProvider
        )
        {
            this.provider = provider;
            this.defaultOrderBuilder = defaultOrderBuilder;
            this.defaultIncludeBuilder = defaultIncludeBuilder;
        }

        //
        #region Retrieve ...
        /// <summary>
        /// Get Specified Item by ID ...
        /// </summary>
        /// <param name="id"></param>
        /// <param name="useDefaultIncludes"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        [HttpGet("{id}")]
        public virtual async Task<ActionResult<TDto>> Get(
            [FromRoute] TKey id,
            [FromQuery] bool useDefaultIncludes = false,
            CancellationToken cancellationToken = default
        )
        {
            //
            try
            {
                //
                // Validate ...
                if (!ModelState.IsValid)
                {
                    XException.InvalidArgs.Throw();
                }
                ValidationProvider.NotNull(id);

                //
                var result = await provider.Get(
                    id: id,
                    includeBuilder: !useDefaultIncludes
                        ? null
                        : defaultIncludeBuilder,
                    cancellationToken: cancellationToken
                );

                //
                return Ok(result.ToDynamicObject());
            }
            catch (Exception ex)
            {
                //
                var result = GetExceptionActionResult(ex);
                return result;
            }
        }

        /// <summary>
        /// Get All Exists Items ...
        /// </summary>
        /// <param name="useDefaultOrders"></param>
        /// <param name="useDefaultIncludes"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        [HttpGet("")]
        public virtual async Task<ActionResult<IEnumerable<TDto>>> GetAll(
            [FromQuery] bool useDefaultOrders = false,
            [FromQuery] bool useDefaultIncludes = false,
            CancellationToken cancellationToken = default
        )
        {
            //
            try
            {
                //
                // Validate ...
                if (!ModelState.IsValid)
                {
                    XException.InvalidArgs.Throw();
                }

                //
                var result = await provider.GetAll(
                    orderBuilder: !useDefaultOrders
                        ? null
                        : defaultOrderBuilder,
                    includeBuilder: !useDefaultIncludes
                        ? null
                        : defaultIncludeBuilder,
                    cancellationToken: cancellationToken
                );

                //
                return Ok(result.ToDynamicObject());
            }
            catch (Exception ex)
            {
                //
                var result = GetExceptionActionResult(ex);
                return result;
            }
        }

        /// <summary>
        /// Find an item by providing a Conditional Expression ...
        /// </summary>
        /// <param name="query"></param>
        /// <param name="useDefaultIncludes"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        [HttpGet("Find/One")]
        public virtual async Task<ActionResult<TDto>> FindOne(
            [FromRoute] string query,
            [FromQuery] bool useDefaultIncludes = false,
            CancellationToken cancellationToken = default
        )
        {
            //
            try
            {
                //
                // Validate ...
                if (!ModelState.IsValid)
                {
                    XException.InvalidArgs.Throw();
                }
                await ValidationProvider
                    .GroupValidationBuilder()
                    .AddNotEmpty(query)
                    .ValidateGroupAsync();

                //
                var result = await provider.FindOne(
                    includeBuilder: !useDefaultIncludes
                        ? null
                        : defaultIncludeBuilder,
                    cancellationToken: cancellationToken,
                    predicate: x => x.PropValuesContains(query)
                );

                //
                return Ok(result.ToDynamicObject());
            }
            catch (Exception ex)
            {
                //
                var result = GetExceptionActionResult(ex);
                return result;
            }
        }

        /// <summary>
        /// Find a collection of Items by proving a Query Search ...
        /// </summary>
        /// <param name="query"></param>
        /// <param name="useDefaultOrders"></param>
        /// <param name="useDefaultIncludes"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        [HttpGet("Find/Many")]
        public virtual async Task<ActionResult<IEnumerable<TDto>>> FindMany(
            [FromRoute] string query,
            [FromQuery] bool useDefaultOrders = false,
            [FromQuery] bool useDefaultIncludes = false,
            CancellationToken cancellationToken = default
        )
        {
            //
            try
            {
                //
                // Validate ...
                if (!ModelState.IsValid)
                {
                    XException.InvalidArgs.Throw();
                }
                await ValidationProvider
                    .GroupValidationBuilder()
                    .AddNotEmpty(query)
                    .ValidateGroupAsync();

                //
                var result = await provider.FindMany(
                    orderBuilder: !useDefaultOrders
                        ? null
                        : defaultOrderBuilder,
                    includeBuilder: !useDefaultIncludes
                        ? null
                        : defaultIncludeBuilder,
                    cancellationToken: cancellationToken,
                    predicate: x => x.PropValuesContains(query)
                );

                //
                return Ok(result.ToDynamicObject());
            }
            catch (Exception ex)
            {
                //
                var result = GetExceptionActionResult(ex);
                return result;
            }
        }

        /// <summary>
        /// Retrieve Items based on XQuery Pagination structure ...
        /// </summary>
        /// <param name="query"></param>
        /// <param name="useDefaultOrders"></param>
        /// <param name="useDefaultIncludes"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        [HttpGet("Query")]
        public virtual async Task<ActionResult<XQueryResult<TDto>>> Query(
            [FromQuery] XQuery query,
            [FromQuery] bool useDefaultOrders = false,
            [FromQuery] bool useDefaultIncludes = false,
            CancellationToken cancellationToken = default
        )
        {
            //
            try
            {
                //
                // Validate ...
                if (!ModelState.IsValid)
                {
                    XException.InvalidArgs.Throw();
                }
                await ValidationProvider
                    .GroupValidationBuilder()
                    .AddNotNull(query)
                    .ValidateGroupAsync();

                //
                var result = await provider.Query(
                    query: query,
                    predicate: null,
                    orderBuilder: !useDefaultOrders
                        ? null
                        : defaultOrderBuilder,
                    includeBuilder: !useDefaultIncludes
                        ? null
                        : defaultIncludeBuilder,
                    cancellationToken: cancellationToken
                );

                //
                return Ok(result.ToDynamicObject());
            }
            catch (Exception ex)
            {
                //
                var result = GetExceptionActionResult(ex);
                return result;
            }
        }

        /// <summary>
        /// Retrieve Owned Items based on XQuery Pagination structure ...
        /// </summary>
        /// <param name="query"></param>
        /// <param name="useDefaultOrders"></param>
        /// <param name="useDefaultIncludes"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        [HttpGet("Query/Owned")]
        public virtual async Task<ActionResult<XQueryResult<TDto>>> QueryOwned(
            [FromQuery] XQuery query,
            [FromQuery] bool useDefaultOrders = false,
            [FromQuery] bool useDefaultIncludes = false,
            CancellationToken cancellationToken = default
        )
        {
            //
            try
            {
                //
                // Validate ...
                if (!ModelState.IsValid)
                {
                    XException.InvalidArgs.Throw();
                }
                await ValidationProvider
                    .GroupValidationBuilder()
                    .AddNotNull(query)
                    .ValidateGroupAsync();

                //
                var userInfo = await GetUserInfo();

                //
                var result = await provider.QueryOwned(
                    query: query,
                    predicate: null,
                    userInfo: userInfo,
                    orderBuilder: !useDefaultOrders
                        ? null
                        : defaultOrderBuilder,
                    includeBuilder: !useDefaultIncludes
                        ? null
                        : defaultIncludeBuilder,
                    cancellationToken: cancellationToken
                );

                //
                return Ok(result.ToDynamicObject());
            }
            catch (Exception ex)
            {
                //
                var result = GetExceptionActionResult(ex);
                return result;
            }
        }
        #endregion

        //
        #region Add/Update/Remove ...
        /// <summary>
        /// Add an item ...
        /// </summary>
        /// <param name="item"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        [HttpPost("")]
        public virtual async Task<ActionResult<TDto>> Add(
            [FromBody] TDto item,
            CancellationToken cancellationToken = default
        )
        {
            //
            try
            {
                //
                // Validate ...
                if (!ModelState.IsValid)
                {
                    XException.InvalidArgs.Throw();
                }
                await ValidationProvider
                    .GroupValidationBuilder()
                    .AddNotNull(item)
                    .ValidateGroupAsync();

                //
                var userInfo = await GetUserInfo();
                var connectionId = GetConnectionId();

                //
                var result = await provider.Add(
                    item: item,
                    userInfo: userInfo,
                    connectionId: connectionId,
                    cancellationToken: cancellationToken
                );

                //
                return Ok(result.ToDynamicObject());
            }
            catch (Exception ex)
            {
                //
                var result = GetExceptionActionResult(ex);
                return result;
            }
        }

        /// <summary>
        /// Update an item values ...
        /// </summary>
        /// <param name="id"></param>
        /// <param name="item"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        [HttpPut("{id}")]
        public virtual async Task<ActionResult<TDto>> Update(
            [FromRoute] TKey id,
            [FromBody] TDto item,
            CancellationToken cancellationToken = default
        )
        {
            //
            try
            {
                //
                // Validate ...
                if (!ModelState.IsValid)
                {
                    XException.InvalidArgs.Throw();
                }
                await ValidationProvider
                    .GroupValidationBuilder()
                    .AddNotNull(id)
                    .AddNotNull(item)
                    .ValidateGroupAsync();

                //
                var userInfo = await GetUserInfo();
                var connectionId = GetConnectionId();

                //
                var result = await provider.Update(
                    id: id,
                    item: item,
                    userInfo: userInfo,
                    connectionId: connectionId,
                    cancellationToken: cancellationToken
                );

                //
                return Ok(result.ToDynamicObject());
            }
            catch (Exception ex)
            {
                //
                var result = GetExceptionActionResult(ex);
                return result;
            }
        }

        /// <summary>
        /// Remove an Item ...
        /// </summary>
        /// <param name="id"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        [HttpDelete("{id}")]
        public virtual async Task<ActionResult<TDto>> Remove(
            [FromRoute] TKey id,
            CancellationToken cancellationToken = default
        )
        {
            //
            try
            {
                //
                // Validate ...
                if (!ModelState.IsValid)
                {
                    XException.InvalidArgs.Throw();
                }
                await ValidationProvider
                    .GroupValidationBuilder()
                    .AddNotNull(id)
                    .ValidateGroupAsync();

                //
                var userInfo = await GetUserInfo();
                var connectionId = GetConnectionId();

                //
                var result = await provider.Remove(
                    id: id,
                    userInfo: userInfo,
                    connectionId: connectionId,
                    cancellationToken: cancellationToken
                );

                //
                return Ok(result.ToDynamicObject());
            }
            catch (Exception ex)
            {
                //
                var result = GetExceptionActionResult(ex);
                return result;
            }
        }
        #endregion
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xPushService\Controllers\XBaseRepositoryProviderController.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore.Query;
using Microsoft.Extensions.Logging;
using xCommons.Configurations;
using xCommons.Extensions;
using xCommons.Providers;
using xDataService.Extensions;
using xExceptions.Constants;
using xIdentityService.Controllers;
using xIdentityService.Interfaces;
using xModels.Base;
using xModels.Dtos;
using xPushService.Base;
using xPushService.Interfaces;

namespace xPushService.Controllers
{
    [AllowAnonymous]
    public abstract class XBaseRepositoryProviderController<TEntity, TKey, THub> : XBaseIdentityApiV1Controller, IXBaseRepositoryProviderController<TEntity, TKey, THub>
    where TEntity : XBaseEntity<TKey>
    where THub : XBaseEntityHub<TEntity, TKey>
    {
        //
        #region Properties ...
        public IXBaseEntityProvider<TEntity, TKey, THub> Provider { get; }
        public Func<IQueryable<TEntity>, IOrderedQueryable<TEntity>> DefaultOrderBuilder { get; }
        public Func<IQueryable<TEntity>, IIncludableQueryable<TEntity, object>> DefaultIncludeBuilder { get; }
        #endregion

        protected XBaseRepositoryProviderController(
            ILogger logger,
            XAppConfiguration appConfiguration,
            IXIdentityProvider identityProvider,
            XValidationProvider validationProvider,
            IXBaseEntityProvider<TEntity, TKey, THub> provider,
            Func<IQueryable<TEntity>, IOrderedQueryable<TEntity>> defaultOrderBuilder = null,
            Func<IQueryable<TEntity>, IIncludableQueryable<TEntity, object>> defaultIncludeBuilder = null
        ) : base(
            logger: logger,
            appConfiguration: appConfiguration,
            identityProvider: identityProvider,
            validationProvider: validationProvider
        )
        {
            //
            Provider = provider;
            DefaultOrderBuilder = defaultOrderBuilder;
            DefaultIncludeBuilder = defaultIncludeBuilder;
        }

        //
        #region Actions ...
        /// <summary>
        /// add a new Item ...
        /// </summary>
        /// <param name="item"></param>
        /// <param name="saveChanges"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        [HttpPost]
        public virtual async Task<ActionResult<TEntity>> Add(
            [FromBody] TEntity item,
            [FromQuery] bool saveChanges = true,
            CancellationToken cancellationToken = default
        )
        {
            //
            try
            {
                //
                // Validate ...
                if (!ModelState.IsValid)
                {
                    XException.InvalidArgs.Throw();
                }
                ValidationProvider.NotNull(item);

                //
                var connectionId = GetConnectionId();

                //
                var result = await Provider.AddAsync(
                    item: item,
                    saveChanges: saveChanges,
                    connectionId: connectionId,
                    cancellationToken: cancellationToken
                );

                //
                return Ok(result.ToDynamicObject());
            }
            catch (Exception ex)
            {
                //
                var result = GetExceptionActionResult(ex);
                return result;
            }
        }

        /// <summary>
        /// Update an Item values ...
        /// </summary>
        /// <param name="id"></param>
        /// <param name="item"></param>
        /// <param name="saveChanges"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        [HttpPut("{id}")]
        public virtual async Task<ActionResult<TEntity>> Update(
            [FromRoute] TKey id,
            [FromBody] TEntity item,
            [FromQuery] bool saveChanges = true,
            CancellationToken cancellationToken = default
        )
        {
            //
            try
            {
                //
                // Validate ...
                if (!ModelState.IsValid)
                {
                    XException.InvalidArgs.Throw();
                }
                ValidationProvider.NotNull(item);

                //
                var connectionId = GetConnectionId();

                //
                var result = await Provider.UpdateAsync(
                    id: id,
                    item: item,
                    saveChanges: saveChanges,
                    connectionId: connectionId,
                    cancellationToken: cancellationToken
                );

                //
                return Ok(result.ToDynamicObject());
            }
            catch (Exception ex)
            {
                //
                var result = GetExceptionActionResult(ex);
                return result;
            }
        }

        /// <summary>
        /// remove an Item by it's Id ...
        /// </summary>
        /// <param name="id"></param>
        /// <param name="softDelete"></param>
        /// <param name="saveChanges"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        [HttpDelete("{id}")]
        public virtual async Task<ActionResult<TEntity>> Remove(
            [FromRoute] TKey id,
            [FromQuery] bool softDelete = true,
            [FromQuery] bool saveChanges = true,
            CancellationToken cancellationToken = default
        )
        {
            //
            try
            {
                //
                // Validate ...
                if (!ModelState.IsValid)
                {
                    XException.InvalidArgs.Throw();
                }

                //
                var connectionId = GetConnectionId();

                //
                var result = await Provider.RemoveAsync(
                    id: id,
                    softDelete: softDelete,
                    saveChanges: saveChanges,
                    connectionId: connectionId,
                    cancellationToken: cancellationToken
                );

                //
                return Ok(result.ToDynamicObject());
            }
            catch (Exception ex)
            {
                //
                var result = GetExceptionActionResult(ex);
                return result;
            }
        }

        /// <summary>
        /// Check an Item exists or not ...
        /// </summary>
        /// <param name="id"></param>
        /// <param name="ignoreSoftDeleteds"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        [HttpGet("{id}/[action]")]
        public virtual async Task<ActionResult<bool>> IsExists(
            [FromRoute] TKey id,
            [FromQuery] bool ignoreSoftDeleteds = true,
            CancellationToken cancellationToken = default
        )
        {
            //
            try
            {
                //
                // Validate ...
                if (!ModelState.IsValid)
                {
                    XException.InvalidArgs.Throw();
                }

                //
                var result = await Provider.IsExistsAsync(
                    id: id,
                    cancellationToken: cancellationToken,
                    ignoreSoftDeleteds: ignoreSoftDeleteds
                );

                //
                return Ok(result);
            }
            catch (Exception ex)
            {
                //
                var result = GetExceptionActionResult(ex);
                return result;
            }
        }

        /// <summary>
        /// count all exists Items ...
        /// </summary>
        /// <param name="ignoreSoftDeleteds"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        [HttpGet("Count")]
        public virtual async Task<ActionResult<long>> Count(
            [FromQuery] bool ignoreSoftDeleteds = true,
            CancellationToken cancellationToken = default
        )
        {
            //
            try
            {
                //
                // Validate ...
                if (!ModelState.IsValid)
                {
                    XException.InvalidArgs.Throw();
                }

                //
                var result = await Provider.CountAsync(
                    cancellationToken: cancellationToken,
                    ignoreSoftDeleteds: ignoreSoftDeleteds
                );

                //
                return Ok(result);
            }
            catch (Exception ex)
            {
                //
                var result = GetExceptionActionResult(ex);
                return result;
            }
        }

        /// <summary>
        /// retrieve an Item by it's Id ...
        /// </summary>
        /// <param name="id"></param>
        /// <param name="ignoreSoftDeleteds"></param>
        /// <param name="useDefaultIncludes"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        [HttpGet("{id}")]
        public virtual async Task<ActionResult<TEntity>> Get(
            [FromRoute] TKey id,
            [FromQuery] bool ignoreSoftDeleteds = true,
            [FromQuery] bool useDefaultIncludes = false,
            CancellationToken cancellationToken = default
        )
        {
            //
            try
            {
                //
                // Validate ...
                if (!ModelState.IsValid)
                {
                    XException.InvalidArgs.Throw();
                }

                //
                var result = await Provider.GetAsync(
                    id: id,
                    includeBuilder: !useDefaultIncludes
                        ? null
                        : DefaultIncludeBuilder,
                    cancellationToken: cancellationToken,
                    ignoreSoftDeleteds: ignoreSoftDeleteds
                );

                //
                return Ok(result.ToDynamicObject());
            }
            catch (Exception ex)
            {
                //
                var result = GetExceptionActionResult(ex);
                return result;
            }
        }

        /// <summary>
        /// retrieve all exists Items ...
        /// </summary>
        /// <param name="ignoreSoftDeleteds"></param>
        /// <param name="useDefaultOrders"></param>
        /// <param name="useDefaultIncludes"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        [HttpGet]
        public virtual async Task<ActionResult<IEnumerable<TEntity>>> GetAll(
            [FromQuery] bool ignoreSoftDeleteds = true,
            [FromQuery] bool useDefaultOrders = false,
            [FromQuery] bool useDefaultIncludes = false,
            CancellationToken cancellationToken = default
        )
        {
            //
            try
            {
                //
                // Validate ...
                if (!ModelState.IsValid)
                {
                    XException.InvalidArgs.Throw();
                }

                //
                var result = await Provider.GetAllAsync(
                    orderBuilder: !useDefaultOrders
                        ? null
                        : DefaultOrderBuilder,
                    includeBuilder: !useDefaultIncludes
                        ? null
                        : DefaultIncludeBuilder,
                    cancellationToken: cancellationToken,
                    ignoreSoftDeleteds: ignoreSoftDeleteds
                );

                //
                return Ok(result.ToDynamicObject());
            }
            catch (Exception ex)
            {
                //
                var result = GetExceptionActionResult(ex);
                return result;
            }
        }

        /// <summary>
        /// find an Item by providing a Conditional Expression ...
        /// </summary>
        /// <param name="query"></param>
        /// <param name="ignoreSoftDeleteds"></param>
        /// <param name="useDefaultIncludes"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        [HttpGet("FindOne")]
        public virtual async Task<ActionResult<TEntity>> FindOne(
            [FromRoute] string query,
            [FromQuery] bool ignoreSoftDeleteds = true,
            [FromQuery] bool useDefaultIncludes = false,
            CancellationToken cancellationToken = default
        )
        {
            //
            try
            {
                //
                if (!ModelState.IsValid)
                {
                    XException.InvalidArgs.Throw();
                }
                ValidationProvider.NotEmpty(query);

                //
                Expression<Func<TEntity, bool>> predicate = x => x.PropValuesContains(query);
                var result = await Provider.FindOneAsync(
                    predicate: predicate,
                    includeBuilder: !useDefaultIncludes
                        ? null
                        : DefaultIncludeBuilder,
                    cancellationToken: cancellationToken,
                    ignoreSoftDeleteds: ignoreSoftDeleteds
                );

                //
                return Ok(result.ToDynamicObject());
            }
            catch (Exception ex)
            {
                //
                var result = GetExceptionActionResult(ex);
                return result;
            }
        }

        /// <summary>
        /// find a collection of Items by proving a Query Search ...
        /// </summary>
        /// <param name="query"></param>
        /// <param name="ignoreSoftDeleteds"></param>
        /// <param name="useDefaultOrders"></param>
        /// <param name="useDefaultIncludes"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        [HttpGet("FindMany")]
        public virtual async Task<ActionResult<IEnumerable<TEntity>>> FindMany(
            [FromRoute] string query,
            [FromQuery] bool ignoreSoftDeleteds = true,
            [FromQuery] bool useDefaultOrders = false,
            [FromQuery] bool useDefaultIncludes = false,
            CancellationToken cancellationToken = default
        )
        {
            //
            try
            {
                //
                if (!ModelState.IsValid)
                {
                    XException.InvalidArgs.Throw();
                }
                ValidationProvider.NotEmpty(query);

                //
                Expression<Func<TEntity, bool>> predicate = x => x.PropValuesContains(query);
                var result = await Provider.FindManyAsync(
                    predicate: predicate,
                    orderBuilder: !useDefaultOrders
                        ? null
                        : DefaultOrderBuilder,
                    includeBuilder: !useDefaultIncludes
                        ? null
                        : DefaultIncludeBuilder,
                    cancellationToken: cancellationToken,
                    ignoreSoftDeleteds: ignoreSoftDeleteds
                );

                //
                return Ok(result.ToDynamicObject());
            }
            catch (Exception ex)
            {
                //
                var result = GetExceptionActionResult(ex);
                return result;
            }
        }

        /// <summary>
        /// Retrieve Items based on XQuery Pagination structure ...
        /// </summary>
        /// <param name="query"></param>
        /// <param name="ignoreSoftDeleteds"></param>
        /// <param name="useDefaultOrders"></param>
        /// <param name="useDefaultIncludes"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        [HttpGet("Query")]
        public virtual async Task<ActionResult<XQueryResult<TEntity>>> Query(
            [FromQuery] XQuery query,
            [FromQuery] bool ignoreSoftDeleteds = true,
            [FromQuery] bool useDefaultOrders = false,
            [FromQuery] bool useDefaultIncludes = false,
            CancellationToken cancellationToken = default
        )
        {
            //
            try
            {
                //
                // Validate ...
                if (!ModelState.IsValid)
                {
                    XException.InvalidArgs.Throw();
                }

                //
                // Normalize ...
                if (query.IsNullOrDefault())
                {
                    query = query.NormalizeQuery(Provider.DataConfiguration);
                }

                //
                var result = await Provider.QueryAsync(
                    query: query,
                    predicate: null,
                    orderBuilder: !useDefaultOrders
                        ? null
                        : DefaultOrderBuilder,
                    includeBuilder: !useDefaultIncludes
                        ? null
                        : DefaultIncludeBuilder,
                    cancellationToken: cancellationToken,
                    ignoreSoftDeleteds: ignoreSoftDeleteds
                );

                //
                return Ok(result.ToDynamicObject());
            }
            catch (Exception ex)
            {
                //
                var result = GetExceptionActionResult(ex);
                return result;
            }
        }
        #endregion

        //
        #region NonActions ...
        /// <summary>
        /// Send Custom Push Message ...
        /// </summary>
        /// <param name="action"></param>
        /// <param name="payLoad"></param>
        /// <param name="connectionId"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        [NonAction]
        public virtual async Task SendPush(
            string action,
            string payLoad,
            string connectionId = null,
            CancellationToken cancellationToken = default
        )
        {
            //
            await Provider.SendPush(
                action: action,
                payLoad: payLoad,
                connectionId: connectionId,
                cancellationToken: cancellationToken
            );
        }
        #endregion
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xPushService\Controllers\XBaseServiceProviderController.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore.Query;
using Microsoft.Extensions.Logging;
using xCommons.Configurations;
using xCommons.Extensions;
using xCommons.Providers;
using xDataService.Extensions;
using xExceptions.Constants;
using xIdentityService.Controllers;
using xIdentityService.Interfaces;
using xModels.Base;
using xModels.Dtos;
using xPushService.Base;
using xPushService.Interfaces;

namespace xPushService.Controllers
{
    [AllowAnonymous]
    public abstract class XBaseServiceProviderController<TEntity, TDto, TKey, THub> : XBaseIdentityApiV1Controller, IXBaseServiceProviderController<TEntity, TDto, TKey, THub>
    where TEntity : XBaseEntity<TKey>
    where TDto : XBaseEntityDto<TKey>
    where THub : XBaseDtoHub<TEntity, TDto, TKey>
    {
        //
        #region Properties ...
        public IXBaseDtoProvider<TEntity, TDto, TKey, THub> Provider { get; }
        public Func<IQueryable<TEntity>, IOrderedQueryable<TEntity>> DefaultOrderBuilder { get; }
        public Func<IQueryable<TEntity>, IIncludableQueryable<TEntity, object>> DefaultIncludeBuilder { get; }
        #endregion

        //
        #region Constructor ...
        public XBaseServiceProviderController(
            ILogger logger,
            XAppConfiguration appConfiguration,
            IXIdentityProvider identityProvider,
            XValidationProvider validationProvider,
            IXBaseDtoProvider<TEntity, TDto, TKey, THub> provider,
            Func<IQueryable<TEntity>, IOrderedQueryable<TEntity>> defaultOrderBuilder = null,
            Func<IQueryable<TEntity>, IIncludableQueryable<TEntity, object>> defaultIncludeBuilder = null
        ) : base(
            logger,
            appConfiguration,
            identityProvider,
            validationProvider
        )
        {
            //
            Provider = provider;
            DefaultOrderBuilder = defaultOrderBuilder;
            DefaultIncludeBuilder = defaultIncludeBuilder;
        }
        #endregion

        //
        #region Actions ...
        /// <summary>
        /// add a new Item ...
        /// </summary>
        /// <param name="item"></param>
        /// <param name="saveChanges"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        [HttpPost]
        public virtual async Task<ActionResult<TDto>> Add(
            [FromBody] TDto item,
            [FromQuery] bool saveChanges = true,
            CancellationToken cancellationToken = default
        )
        {
            //
            try
            {
                //
                // Validate ...
                if (!ModelState.IsValid)
                {
                    XException.InvalidArgs.Throw();
                }
                ValidationProvider.NotNull(item);

                //
                var connectionId = GetConnectionId();

                //
                var result = await Provider.AddAsync(
                    item: item,
                    saveChanges: saveChanges,
                    connectionId: connectionId,
                    cancellationToken: cancellationToken
                );

                //
                return Ok(result.ToDynamicObject());
            }
            catch (Exception ex)
            {
                //
                var result = GetExceptionActionResult(ex);
                return result;
            }
        }

        /// <summary>
        /// Update an Item values ...
        /// </summary>
        /// <param name="id"></param>
        /// <param name="item"></param>
        /// <param name="saveChanges"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        [HttpPut("{id}")]
        public virtual async Task<ActionResult<TDto>> Update(
            [FromRoute] TKey id,
            [FromBody] TDto item,
            [FromQuery] bool saveChanges = true,
            CancellationToken cancellationToken = default
        )
        {
            //
            try
            {
                //
                // Validate ...
                if (!ModelState.IsValid)
                {
                    XException.InvalidArgs.Throw();
                }
                ValidationProvider.NotNull(item);

                //
                var connectionId = GetConnectionId();

                //
                var result = await Provider.UpdateAsync(
                    id: id,
                    item: item,
                    saveChanges: saveChanges,
                    connectionId: connectionId,
                    cancellationToken: cancellationToken
                );

                //
                return Ok(result.ToDynamicObject());
            }
            catch (Exception ex)
            {
                //
                var result = GetExceptionActionResult(ex);
                return result;
            }
        }

        /// <summary>
        /// remove an Item by it's Id ...
        /// </summary>
        /// <param name="id"></param>
        /// <param name="softDelete"></param>
        /// <param name="saveChanges"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        [HttpDelete("{id}")]
        public virtual async Task<ActionResult<TDto>> Remove(
            [FromRoute] TKey id,
            [FromQuery] bool softDelete = true,
            [FromQuery] bool saveChanges = true,
            CancellationToken cancellationToken = default
        )
        {
            //
            try
            {
                //
                // Validate ...
                if (!ModelState.IsValid)
                {
                    XException.InvalidArgs.Throw();
                }

                //
                var connectionId = GetConnectionId();

                //
                var result = await Provider.RemoveAsync(
                    id: id,
                    softDelete: softDelete,
                    saveChanges: saveChanges,
                    connectionId: connectionId,
                    cancellationToken: cancellationToken
                );

                //
                return Ok(result.ToDynamicObject());
            }
            catch (Exception ex)
            {
                //
                var result = GetExceptionActionResult(ex);
                return result;
            }
        }

        /// <summary>
        /// Check an Item exists or not ...
        /// </summary>
        /// <param name="id"></param>
        /// <param name="ignoreSoftDeleteds"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        [HttpGet("{id}/[action]")]
        public virtual async Task<ActionResult<bool>> IsExists(
            [FromRoute] TKey id,
            [FromQuery] bool ignoreSoftDeleteds = true,
            CancellationToken cancellationToken = default
        )
        {
            //
            try
            {
                //
                // Validate ...
                if (!ModelState.IsValid)
                {
                    XException.InvalidArgs.Throw();
                }

                //
                var result = await Provider.IsExistsAsync(
                    id: id,
                    cancellationToken: cancellationToken,
                    ignoreSoftDeleteds: ignoreSoftDeleteds
                );

                //
                return Ok(result);
            }
            catch (Exception ex)
            {
                //
                var result = GetExceptionActionResult(ex);
                return result;
            }
        }

        /// <summary>
        /// count all exists Items ...
        /// </summary>
        /// <param name="ignoreSoftDeleteds"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        [HttpGet("Count")]
        public virtual async Task<ActionResult<long>> Count(
            [FromQuery] bool ignoreSoftDeleteds = true,
            CancellationToken cancellationToken = default
        )
        {
            //
            try
            {
                //
                // Validate ...
                if (!ModelState.IsValid)
                {
                    XException.InvalidArgs.Throw();
                }

                //
                var result = await Provider.CountAsync(
                    cancellationToken: cancellationToken,
                    ignoreSoftDeleteds: ignoreSoftDeleteds
                );

                //
                return Ok(result);
            }
            catch (Exception ex)
            {
                //
                var result = GetExceptionActionResult(ex);
                return result;
            }
        }

        /// <summary>
        /// retrieve an Item by it's Id ...
        /// </summary>
        /// <param name="id"></param>
        /// <param name="ignoreSoftDeleteds"></param>
        /// <param name="useDefaultIncludes"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        [HttpGet("{id}")]
        public virtual async Task<ActionResult<TDto>> Get(
            [FromRoute] TKey id,
            [FromQuery] bool ignoreSoftDeleteds = true,
            [FromQuery] bool useDefaultIncludes = false,
            CancellationToken cancellationToken = default
        )
        {
            //
            try
            {
                //
                // Validate ...
                if (!ModelState.IsValid)
                {
                    XException.InvalidArgs.Throw();
                }

                //
                var result = await Provider.GetAsync(
                    id: id,
                    includeBuilder: !useDefaultIncludes
                        ? null
                        : DefaultIncludeBuilder,
                    cancellationToken: cancellationToken,
                    ignoreSoftDeleteds: ignoreSoftDeleteds
                );

                //
                return Ok(result.ToDynamicObject());
            }
            catch (Exception ex)
            {
                //
                var result = GetExceptionActionResult(ex);
                return result;
            }
        }

        /// <summary>
        /// retrieve all exists Items ...
        /// </summary>
        /// <param name="ignoreSoftDeleteds"></param>
        /// <param name="useDefaultOrders"></param>
        /// <param name="useDefaultIncludes"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        [HttpGet]
        public virtual async Task<ActionResult<IEnumerable<TDto>>> GetAll(
            [FromQuery] bool ignoreSoftDeleteds = true,
            [FromQuery] bool useDefaultOrders = false,
            [FromQuery] bool useDefaultIncludes = false,
            CancellationToken cancellationToken = default
        )
        {
            //
            try
            {
                //
                // Validate ...
                if (!ModelState.IsValid)
                {
                    XException.InvalidArgs.Throw();
                }

                //
                var result = await Provider.GetAllAsync(
                    orderBuilder: !useDefaultOrders
                        ? null
                        : DefaultOrderBuilder,
                    includeBuilder: !useDefaultIncludes
                        ? null
                        : DefaultIncludeBuilder,
                    cancellationToken: cancellationToken,
                    ignoreSoftDeleteds: ignoreSoftDeleteds
                );

                //
                return Ok(result.ToDynamicObject());
            }
            catch (Exception ex)
            {
                //
                var result = GetExceptionActionResult(ex);
                return result;
            }
        }

        /// <summary>
        /// find an Item by providing a Conditional Expression ...
        /// </summary>
        /// <param name="query"></param>
        /// <param name="ignoreSoftDeleteds"></param>
        /// <param name="useDefaultIncludes"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        [HttpGet("FindOne")]
        public virtual async Task<ActionResult<TDto>> FindOne(
            [FromRoute] string query,
            [FromQuery] bool ignoreSoftDeleteds = true,
            [FromQuery] bool useDefaultIncludes = false,
            CancellationToken cancellationToken = default
        )
        {
            //
            try
            {
                //
                if (!ModelState.IsValid)
                {
                    XException.InvalidArgs.Throw();
                }
                ValidationProvider.NotEmpty(query);

                //
                Expression<Func<TEntity, bool>> predicate = x => x.PropValuesContains(query);
                var result = await Provider.FindOneAsync(
                    predicate: predicate,
                    includeBuilder: !useDefaultIncludes
                        ? null
                        : DefaultIncludeBuilder,
                    cancellationToken: cancellationToken,
                    ignoreSoftDeleteds: ignoreSoftDeleteds
                );

                //
                return Ok(result.ToDynamicObject());
            }
            catch (Exception ex)
            {
                //
                var result = GetExceptionActionResult(ex);
                return result;
            }
        }

        /// <summary>
        /// find a collection of Items by proving a Conditional Expression ...
        /// </summary>
        /// <param name="query"></param>
        /// <param name="ignoreSoftDeleteds"></param>
        /// <param name="useDefaultOrders"></param>
        /// <param name="useDefaultIncludes"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        [HttpGet("FindMany")]
        public virtual async Task<ActionResult<IEnumerable<TDto>>> FindMany(
            [FromRoute] string query,
            [FromQuery] bool ignoreSoftDeleteds = true,
            [FromQuery] bool useDefaultOrders = false,
            [FromQuery] bool useDefaultIncludes = false,
            CancellationToken cancellationToken = default
        )
        {
            //
            try
            {
                //
                if (!ModelState.IsValid)
                {
                    XException.InvalidArgs.Throw();
                }
                ValidationProvider.NotEmpty(query);

                //
                Expression<Func<TEntity, bool>> predicate = x => x.PropValuesContains(query);
                var result = await Provider.FindManyAsync(
                    predicate: predicate,
                    orderBuilder: !useDefaultOrders
                        ? null
                        : DefaultOrderBuilder,
                    includeBuilder: !useDefaultIncludes
                        ? null
                        : DefaultIncludeBuilder,
                    cancellationToken: cancellationToken,
                    ignoreSoftDeleteds: ignoreSoftDeleteds
                );

                //
                return Ok(result.ToDynamicObject());
            }
            catch (Exception ex)
            {
                //
                var result = GetExceptionActionResult(ex);
                return result;
            }
        }

        /// <summary>
        /// retrieve Items based on XQuery Pagination structure ...
        /// </summary>
        /// <param name="query"></param>
        /// <param name="ignoreSoftDeleteds"></param>
        /// <param name="useDefaultOrders"></param>
        /// <param name="useDefaultIncludes"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        [HttpGet("Query")]
        public virtual async Task<ActionResult<XQueryResult<TDto>>> Query(
            [FromQuery] XQuery query,
            [FromQuery] bool ignoreSoftDeleteds = true,
            [FromQuery] bool useDefaultOrders = false,
            [FromQuery] bool useDefaultIncludes = false,
            CancellationToken cancellationToken = default
        )
        {
            //
            try
            {
                //
                // Validate ...
                if (!ModelState.IsValid)
                {
                    XException.InvalidArgs.Throw();
                }

                //
                // Normalize ...
                if (query.IsNullOrDefault())
                {
                    query = query.NormalizeQuery(Provider.DataConfiguration);
                }

                //
                var result = await Provider.QueryAsync(
                    query: query,
                    predicate: null,
                    orderBuilder: !useDefaultOrders
                        ? null
                        : DefaultOrderBuilder,
                    includeBuilder: !useDefaultIncludes
                        ? null
                        : DefaultIncludeBuilder,
                    cancellationToken: cancellationToken,
                    ignoreSoftDeleteds: ignoreSoftDeleteds
                );

                //
                return Ok(result.ToDynamicObject());
            }
            catch (Exception ex)
            {
                //
                var result = GetExceptionActionResult(ex);
                return result;
            }
        }
        #endregion

        //
        #region NonActions ...
        /// <summary>
        /// Send Custom Push Message ...
        /// </summary>
        /// <param name="action"></param>
        /// <param name="payLoad"></param>
        /// <param name="connectionId"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        [NonAction]
        public virtual async Task SendPush(
            string action,
            string payLoad,
            string connectionId = null,
            CancellationToken cancellationToken = default
        )
        {
            //
            await Provider.SendPush(
                action: action,
                payLoad: payLoad,
                connectionId: connectionId,
                cancellationToken: cancellationToken
            );
        }
        #endregion
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xPushService\DI\XDIHelperExtension.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.SignalR;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Newtonsoft.Json;
using Newtonsoft.Json.Serialization;
using xCommons.Extensions;
using xExceptions.Constants;
using xPushService.Configurations;
using xPushService.Constants;
using xPushService.Helpers;
using xPushService.Providers;

namespace xPushService.DI
{
    public static partial class XDIHelperExtension
    {
        /// <summary>
        /// Extract Module Configuration from provided IConfiguration
        /// </summary>
        /// <param name="config"></param>
        /// <returns>an instance of XPushServiceConfiguration</returns>
        public static XPushServiceConfiguration GetXPushServiceConfiguration(this IConfiguration config)
        {
            //
            var xPushConfigSection = config.GetSection(XPushServiceConstants.XConfigurationNodes.XPushServiceConfiguration);
            return xPushConfigSection.Get<XPushServiceConfiguration>();
        }

        /// <summary>
        /// Register XPushServiceHelper ...
        /// </summary>
        /// <param name="services"></param>
        /// <param name="helper"></param>
        public static void AddXPushServiceHelper(
            this IServiceCollection services,
            XPushServiceHelper helper
        )
        {
            //
            // Validate Args ...
            if (helper.IsNull())
            {
                //
                Log("AddXPushServiceHelper failed, helper not provided ...");
                throw XException.InvalidArgs.ToException();
            }

            //
            // Register Helper ...
            services.AddSingleton(helper);
        }

        /// <summary>
        /// Register Module Provided Service on DI
        /// </summary>
        /// <param name="services"></param>
        /// <param name="config"></param>
        /// <param name="lifeTime"></param>
        public static void AddXPushService(
            this IServiceCollection services,
            IConfiguration config,
            ServiceLifetime lifeTime = ServiceLifetime.Scoped
        )
        {
            //
            AddPushService(
                services,
                config.GetXPushServiceConfiguration(),
                lifeTime
            );
        }

        /// <summary>
        /// Register Module Provided Service on DI
        /// </summary>
        /// <param name="services"></param>
        /// <param name="config"></param>
        /// <param name="lifeTime"></param>
        public static void AddXPushService(
            this IServiceCollection services,
            XPushServiceConfiguration config,
            ServiceLifetime lifeTime = ServiceLifetime.Scoped
        )
        {
            //
            AddPushService(
                services,
                config,
                lifeTime
            );
        }

        /// <summary>
        /// Use Module Middlewares on Application Builder
        /// </summary>
        /// <param name="app"></param>
        /// <param name="helper"></param>
        public static void UseXPushService(
            this IApplicationBuilder app,
            XPushServiceHelper helper
        )
        {
            //
            // Validate Args ...
            var isHelperExists = !helper.IsNull();
            if (!isHelperExists)
            {
                //
                Log("AddXPushServiceHelper failed, helper not provided ...");
                throw XException.InvalidArgs.ToException();
            }

            //
            // Create an Scope for Accessing Registered Services ...
            using (var scope = app.ApplicationServices.CreateScope())
            {
                //
                // try to Retrieve Configuration ....
                var config = scope.ServiceProvider.GetService<XPushServiceConfiguration>();
                if (
                    config.IsNull() ||
                    config.BaseRoute.IsNullOrEmpty() ||
                    config.BaseRoute.Trim().IsNullOrEmpty()
                )
                {
                    //
                    Log("AddXPushServiceHelper failed, Configuration not provided ...");
                    throw XException.InvalidConfiguration.ToException();
                }

                //
                #region Normalize Routes ...
                //
                // Base Reoute ...
                config.BaseRoute = config.BaseRoute.ToNormalString();
                if (!config.BaseRoute.StartsWith("/"))
                {
                    config.BaseRoute = "/" + config.BaseRoute;
                }
                #endregion

                //
                // add XPushService Hub to Helper ...
                //
                var hubRoutes = new List<string>();

                //
                // Try to Register Hubs ...
                //
                // Use SignalR in App ...
                app.UseSignalR(routes =>
                {
                    //
                    helper.GetHubs().ForEach(hubDescriptor =>
                    {
                        //
                        var hubRoute = config.BaseRoute + "/" + hubDescriptor.Route;
                        hubRoutes.Add(hubRoute);

                        //
                        try
                        {
                            //
                            Type routesType = routes.GetType();
                            MethodInfo mapHubMethod = routesType
                                .GetMethods()
                                .SingleOrDefault(m =>
                                    m.Name == "MapHub" &&
                                    m.GetParameters().Length == 1
                                );
                            if (mapHubMethod.IsNull())
                            {
                                throw XException.ActionFailed.ToException();
                            }

                            //
                            object[] genericMapHubMethodArgs = { new PathString(hubRoute) };
                            MethodInfo genericMapHubMethod = mapHubMethod.MakeGenericMethod(hubDescriptor.Hub);
                            genericMapHubMethod.Invoke(routes, genericMapHubMethodArgs);

                            //
                            Log($"Register {hubDescriptor.Hub} Hub: {hubRoute}");
                        }
                        catch
                        {
                            throw;
                        }
                    });
                });
            }
        }

        //
        #region Private ...
        /// <summary>
        /// a LogTag for XPushService ...
        /// </summary>
        private static string XLogTag = "XPushService";

        /// <summary>
        /// print a log in Console ...
        /// </summary>
        /// <param name="message"></param>
        private static void Log(string message)
        {
            Console.WriteLine($"{XLogTag} => {message}");
        }

        /// <summary>
        /// Register Push Service ...
        /// </summary>
        /// <param name="services"></param>
        /// <param name="config"></param>
        /// <param name="lifeTime"></param>
        private static void AddPushService(
            IServiceCollection services,
            XPushServiceConfiguration config,
            ServiceLifetime lifeTime
        )
        {
            //
            #region Validate Args ...
            //
            var exception = XException.InvalidArgs.ToException(); ;

            //
            // Services ...
            var isServicesExists = !services.IsNull();
            if (!isServicesExists)
            {
                //
                Log("AddXPushServiceHelper failed, services not provided ...");
                throw exception;
            }

            //
            // Config ...
            var isConfigExists = !config.IsNull();
            if (!isConfigExists)
            {
                //
                Log("AddXPushServiceHelper failed, configuration not provided ...");
                throw exception;
            }

            //
            // Lifetime ...
            var isLifetimeExists = !lifeTime.IsNull();
            if (!isLifetimeExists)
            {
                //
                Log("AddXPushServiceHelper failed, lifetime not provided ...");
                throw exception;
            }
            #endregion

            //
            // Register XPushService Configuration ...
            services.AddSingleton(config);

            //
            // Register SignalR ...
            var builder = services.AddSignalR(options =>
            {
                options.KeepAliveInterval = TimeSpan.FromSeconds(10);
                options.ClientTimeoutInterval = TimeSpan.FromSeconds(10);
            });

            //
            // Add NewtonSoftJson Protocol ...
            builder.AddNewtonsoftJsonProtocol(x =>
            {
                x.PayloadSerializerSettings.ReferenceLoopHandling = ReferenceLoopHandling.Ignore;
                x.PayloadSerializerSettings.ContractResolver = new CamelCasePropertyNamesContractResolver();
            });
            
            //
            // Register XPushServiceUserNameProvider ...
            services.AddSingleton<IUserIdProvider, XPushServiceUserNameProvider>();

            //
            // add Message Protocol Support ...
            if (config.AddSupportMessageProtocol)
            {
                builder.AddMessagePackProtocol();
            }
        }
        #endregion
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xPushService\Extensions\ClaimsPrincipalExtensions.cs

using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.AspNetCore.SignalR;
using xCommons.Constants;
using xCommons.Extensions;
using xCommons.Helpers;
using xIdentityModels.Constants;
using xPushService.Models;

namespace xPushService.Extensions
{
    public static class ClaimsPrincipalExtensions
    {
        /// <summary>
        /// Generate User Info based on HubCallerContext ...
        /// </summary>
        /// <param name="source"></param>
        /// <returns></returns>
        public static XHubUserInfo GetUserInfo(this HubCallerContext source)
        {
            //
            XHubUserInfo result = null;

            //
            if (source.IsNull() || source.User.IsNull() || !source.User.Claims.HasChild())
            {
                return result;
            }

            //
            result = new XHubUserInfo
            {
                UserId = source.User.Claims.FirstOrDefault(c => c.Type == XCustomClaims.UserId)?.Value ?? "",
                UserName = source.User.Claims.FirstOrDefault(c => c.Type == XCustomClaims.UserName)?.Value ?? "",
                FirstName = source.User.Claims.FirstOrDefault(c => c.Type == XCustomClaims.FirstName)?.Value ?? "",
                LastName = source.User.Claims.FirstOrDefault(c => c.Type == XCustomClaims.LastName)?.Value ?? "",
                Picture = source.User.Claims.FirstOrDefault(c => c.Type == XCustomClaims.Picture)?.Value ?? "",
                Email = source.User.Claims.FirstOrDefault(c => c.Type == XCustomClaims.Email)?.Value ?? null,
                PhoneNumber = source.User.Claims.FirstOrDefault(c => c.Type == XCustomClaims.PhoneNumber)?.Value ?? null,
            };

            //
            #region Handle Gender ...
            var genders = ObjectHelper.ToEnumerableKeys<XGender>();
            var genderStr = source.User.Claims.FirstOrDefault(c => c.Type == XCustomClaims.Gender).Value ?? null;
            if (genderStr.IsNullOrEmpty())
            {
                result.Gender = XGender.Male;
            }
            else
            {
                result.Gender = genderStr.GetValue<XGender>();
            }
            #endregion

            //
            #region Handle IsBanned ...
            var isBannedStr = source.User.Claims.FirstOrDefault(c => c.Type == XCustomClaims.IsBanned).Value ?? null;
            if (isBannedStr.IsNullOrEmpty())
            {
                result.IsBanned = false;
            }
            else
            {
                //
                var isBanned = false;
                Boolean.TryParse(isBannedStr, out isBanned);

                //
                result.IsBanned = isBanned;
            }
            #endregion

            //
            #region Handle IsEnabled ...
            var isEnabledStr = source.User.Claims.FirstOrDefault(c => c.Type == XCustomClaims.IsEnabled).Value ?? null;
            if (isEnabledStr.IsNullOrEmpty())
            {
                result.IsEnabled = false;
            }
            else
            {
                //
                var isEnabled = false;
                Boolean.TryParse(isEnabledStr, out isEnabled);

                //
                result.IsEnabled = isEnabled;
            }
            #endregion

            //
            #region Handle Email Confirmed ...
            var emailConfirmedStr = source.User.Claims.FirstOrDefault(c => c.Type == XCustomClaims.EmailVerified).Value ?? null;
            if (emailConfirmedStr.IsNullOrEmpty())
            {
                result.EmailConfirmed = false;
            }
            else
            {
                //
                var emailConfirmed = false;
                Boolean.TryParse(emailConfirmedStr, out emailConfirmed);

                //
                result.EmailConfirmed = emailConfirmed;
            }
            #endregion

            //
            #region Handle PhoneNumber Confirmed ...
            var phoneNumberConfirmedStr = source.User.Claims.FirstOrDefault(c => c.Type == XCustomClaims.PhoneNumberVerified).Value ?? null;
            if (phoneNumberConfirmedStr.IsNullOrEmpty())
            {
                result.PhoneNumberConfirmed = false;
            }
            else
            {
                //
                var phoneNumberConfirmed = false;
                Boolean.TryParse(phoneNumberConfirmedStr, out phoneNumberConfirmed);

                //
                result.PhoneNumberConfirmed = phoneNumberConfirmed;
            }
            #endregion

            //
            #region  Handle ExpiredOn ...
            var expiredOnStr = source.User.Claims.FirstOrDefault(c => c.Type == XCustomClaims.ExpiredOn).Value ?? null;
            if (expiredOnStr.IsNullOrEmpty())
            {
                result.ExpiredOn = null;
            }
            else
            {
                //
                long expiredOn = 0;
                long.TryParse(expiredOnStr, out expiredOn);

                //
                result.ExpiredOn = expiredOn;
            }
            #endregion

            //
            #region Handle AuthenticatedOn ...
            var authenticatedOnStr = source.User.Claims.FirstOrDefault(c => c.Type == XCustomClaims.AuthenticatedOn).Value ?? null;
            if (authenticatedOnStr.IsNullOrEmpty())
            {
                result.AuthenticatedOn = null;
            }
            else
            {
                //
                long authenticatedOn = 0;
                long.TryParse(authenticatedOnStr, out authenticatedOn);

                //
                result.AuthenticatedOn = authenticatedOn;
            }
            #endregion

            //
            #region Handle BrithDate ...
            var brithDateStr = source.User.Claims.FirstOrDefault(c => c.Type == XCustomClaims.BrithDate)?.Value ?? "";
            if (brithDateStr.IsNullOrEmpty())
            {
                // BrithDate = null;
            }
            else
            {
                //
                DateTime bDate;
                DateTime.TryParse(brithDateStr, out bDate);

                //
                result.BrithDate = bDate;
            }
            #endregion

            //
            result.Issuers = source.User.Claims.Where(c => c.Type == XCustomClaims.Issuer)?
                .Select(c => c.Value) ?? new HashSet<string>();
            result.Audiences = source.User.Claims.Where(c => c.Type == XCustomClaims.Audience)?
                .Select(c => c.Value) ?? new HashSet<string>();
            result.ClientIds = source.User.Claims.Where(c => c.Type == XCustomClaims.ClientId)?
                .Select(c => c.Value) ?? new HashSet<string>();
            result.Scopes = source.User.Claims.Where(c => c.Type == XCustomClaims.Scope)?
                .Select(c => c.Value) ?? new HashSet<string>();
            result.Roles = source.User.Claims.Where(c => c.Type == XCustomClaims.Role)?
                .Select(c => c.Value) ?? new HashSet<string>();

            //
            return result;
        }
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xPushService\Helpers\XPushServiceHelper.cs

using System.Collections.Generic;
using System.Linq;
using xCommons.Extensions;
using xExceptions.Constants;
using xPushService.Base;
using xPushService.Models;

namespace xPushService.Helpers {
    public class XPushServiceHelper {
        /// <summary>
        /// a collection of Hubs for Registring ...
        /// </summary>
        /// <returns></returns>
        private List<XHubDescriptor> hubs = new List<XHubDescriptor> ();

        /// <summary>
        /// add specified hub to provided hubs for registration ...
        /// </summary>
        /// <param name="route"></param>
        /// <typeparam name="TXHub"></typeparam>
        public void AddHub<TXHub> (string route) where TXHub : XBaseHub {
            //
            #region Validate Args ...
            //
            // check route not null ...
            if (
                route.IsNullOrEmpty () ||
                route.Trim ().IsNullOrEmpty ()
            ) {
                throw XException.InvalidArgs.ToException ();
            }

            //
            // Normalize Route ...
            route = route.ToNormalString ();

            //
            // check route and hub must be unique ...
            var isRouteExists = hubs.Any (hd => hd.Route == route);
            var isHubExists = hubs.Any (hd => hd.Hub == typeof (TXHub));
            if (
                isHubExists ||
                isRouteExists
            ) {
                throw XException.Duplicate.ToException ();
            }
            #endregion

            //
            // Add Provided Hub to List ...
            hubs.Add (new XHubDescriptor {
                Route = route,
                    Hub = typeof (TXHub)
            });
        }

        /// <summary>
        /// remove an specific hub from provided list ...
        /// </summary>
        /// <typeparam name="TXHub"></typeparam>
        public void RemoveHub<TXHub> () where TXHub : XBaseHub {
            //
            var existsHubDescriptor = hubs.SingleOrDefault (hd => hd.Hub == typeof (TXHub));
            if (!existsHubDescriptor.IsNull ()) {
                hubs.Remove (existsHubDescriptor);
            }
        }

        /// <summary>
        /// retrieve provided hubs count ...
        /// </summary>
        /// <returns></returns>
        public int Count () {
            return hubs.Count;
        }

        /// <summary>
        /// retrieve all provided hubs for registration ...
        /// </summary>
        /// <returns></returns>
        public List<XHubDescriptor> GetHubs () {
            return hubs;
        }
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xPushService\Interfaces\IXBaseDtoHub.cs

using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;
using xModels.Base;

namespace xPushService.Interfaces
{
    public interface IXBaseDtoHub<TEntity, TDto, TKey>
    where TEntity : XBaseEntity<TKey>
    where TDto : XBaseEntityDto<TKey>
    {
        /// <summary>
        /// Notify a New Item added ...
        /// </summary>
        /// <param name="item"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        Task Add(
            TDto item,
            CancellationToken cancellationToken = default
        );

        /// <summary>
        /// Notify a New Item added ...
        /// </summary>
        /// <param name="item"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        Task AddOrUpdate(
            TDto item,
            CancellationToken cancellationToken = default
        );

        /// <summary>
        /// Notify Add Many Items ...
        /// </summary>
        /// <param name="items"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        Task AddMany(
            IEnumerable<TDto> items,
            CancellationToken cancellationToken = default
        );

        /// <summary>
        /// Notify an Item Deleted ...
        /// </summary>
        /// <param name="item"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        Task Delete(
            TDto item,
            CancellationToken cancellationToken = default
        );

        /// <summary>
        /// Notify Delete Many Items ...
        /// </summary>
        /// <param name="items"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        Task DeleteMany(
            IEnumerable<TDto> items,
            CancellationToken cancellationToken = default
        );

        /// <summary>
        /// Notify an Item Updated ...
        /// </summary>
        /// <param name="item"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        Task Update(
            TDto item,
            CancellationToken cancellationToken = default
        );

        /// <summary>
        /// Notify Update Many Items ...
        /// </summary>
        /// <param name="items"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        Task UpdateMany(
            IEnumerable<TDto> items,
            CancellationToken cancellationToken = default
        );        
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xPushService\Interfaces\IXBaseDtoProvider.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.AspNetCore.SignalR;
using Microsoft.EntityFrameworkCore.Query;
using xDataService.Configuration;
using xDataService.Interfaces;
using xIdentityService.Interfaces;
using xModels.Base;
using xModels.Dtos;
using xPushService.Base;

namespace xPushService.Interfaces
{
    public interface IXBaseDtoProvider<TEntity, TDto, TKey, THub>
    where TEntity : XBaseEntity<TKey>
    where TDto : XBaseEntityDto<TKey>
    where THub : XBaseDtoHub<TEntity, TDto, TKey>
    {
        //
        #region Props ...
        IHubContext<THub> Hub { get; }
        IXIdentityProvider IdentityProvider { get; }
        XDataServiceConfiguration DataConfiguration { get; }
        IXBaseRepositoryService<TEntity, TDto, TKey> Service { get; }
        #endregion

        //
        #region Actions ...
        /// <summary>
        /// add a new Item ...
        /// </summary>
        /// <param name="item"></param>
        /// <param name="saveChanges"></param>
        /// <param name="connectionId"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        Task<TDto> AddAsync(
            TDto item,
            bool saveChanges = true,
            string connectionId = null,
            CancellationToken cancellationToken = default
        );

        /// <summary>
        /// Update an Item values ...
        /// </summary>
        /// <param name="id"></param>
        /// <param name="item"></param>
        /// <param name="saveChanges"></param>
        /// <param name="connectionId"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        Task<TDto> UpdateAsync(
            TKey id,
            TDto item,
            bool saveChanges = true,
            string connectionId = null,
            CancellationToken cancellationToken = default
        );

        /// <summary>
        /// remove an Item by it's Id ...
        /// </summary>
        /// <param name="id"></param>
        /// <param name="softDelete"></param>
        /// <param name="saveChanges"></param>
        /// <param name="connectionId"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        Task<TDto> RemoveAsync(
            TKey id,
            bool softDelete = true,
            bool saveChanges = true,
            string connectionId = null,
            CancellationToken cancellationToken = default
        );

        /// <summary>
        /// count all exists Items ...
        /// </summary>
        /// <param name="ignoreSoftDeleteds"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        Task<int> CountAsync(
            bool ignoreSoftDeleteds = true,
            CancellationToken cancellationToken = default
        );

        /// <summary>
        /// Check an Item exists or not ...
        /// </summary>
        /// <param name="id"></param>
        /// <param name="ignoreSoftDeleteds"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        Task<bool> IsExistsAsync(
            TKey id,
            bool ignoreSoftDeleteds = true,
            CancellationToken cancellationToken = default
        );

        /// <summary>
        /// retrieve an Item by it's Id ...
        /// </summary>
        /// <param name="id"></param>
        /// <param name="ignoreSoftDeleteds"></param>
        /// <param name="includeBuilder"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        Task<TDto> GetAsync(
            TKey id,
            bool ignoreSoftDeleteds = true,
            Func<IQueryable<TEntity>, IIncludableQueryable<TEntity, object>> includeBuilder = null,
            CancellationToken cancellationToken = default
        );

        /// <summary>
        /// retrieve all exists Items ...
        /// </summary>
        /// <param name="ignoreSoftDeleteds"></param>
        /// <param name="orderBuilder"></param>
        /// <param name="includeBuilder"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        Task<IEnumerable<TDto>> GetAllAsync(
            bool ignoreSoftDeleteds = true,
            Func<IQueryable<TEntity>, IOrderedQueryable<TEntity>> orderBuilder = null,
            Func<IQueryable<TEntity>, IIncludableQueryable<TEntity, object>> includeBuilder = null,
            CancellationToken cancellationToken = default
        );

        /// <summary>
        /// retrieve all exists Dtos
        /// as Async Enumerable ...
        /// </summary>
        /// <param name="ignoreSoftDeleteds"></param>
        /// <param name="orderBuilder"></param>
        /// <param name="includeBuilder"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        IAsyncEnumerable<TDto> GetAllAsAsyncEnumerable(
            bool ignoreSoftDeleteds = true,
            Func<IQueryable<TEntity>, IOrderedQueryable<TEntity>> orderBuilder = null,
            Func<IQueryable<TEntity>, IIncludableQueryable<TEntity, object>> includeBuilder = null,
            CancellationToken cancellationToken = default
        );

        /// <summary>
        /// find an Item by providing a Conditional Expression ...
        /// </summary>
        /// <param name="predicate"></param>
        /// <param name="ignoreSoftDeleteds"></param>
        /// <param name="includeBuilder"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        Task<TDto> FindOneAsync(
            Expression<Func<TEntity, bool>> predicate,
            bool ignoreSoftDeleteds = true,
            Func<IQueryable<TEntity>, IIncludableQueryable<TEntity, object>> includeBuilder = null,
            CancellationToken cancellationToken = default
        );

        /// <summary>
        /// find a collection of Items by proving a Conditional Expression ...
        /// </summary>
        /// <param name="predicate"></param>
        /// <param name="ignoreSoftDeleteds"></param>
        /// <param name="orderBuilder"></param>
        /// <param name="includeBuilder"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        Task<IEnumerable<TDto>> FindManyAsync(
            Expression<Func<TEntity, bool>> predicate,
            bool ignoreSoftDeleteds = true,
            Func<IQueryable<TEntity>, IOrderedQueryable<TEntity>> orderBuilder = null,
            Func<IQueryable<TEntity>, IIncludableQueryable<TEntity, object>> includeBuilder = null,
            CancellationToken cancellationToken = default
        );

        /// <summary>
        /// retrieve Items based on XQuery Pagination structure ...
        /// </summary>
        /// <param name="query"></param>
        /// <param name="ignoreSoftDeleteds"></param>
        /// <param name="predicate"></param>
        /// <param name="orderBuilder"></param>
        /// <param name="includeBuilder"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        Task<XQueryResult<TDto>> QueryAsync(
            XQuery query,
            bool ignoreSoftDeleteds = true,
            Expression<Func<TEntity, bool>> predicate = null,
            Func<IQueryable<TEntity>, IOrderedQueryable<TEntity>> orderBuilder = null,
            Func<IQueryable<TEntity>, IIncludableQueryable<TEntity, object>> includeBuilder = null,
            CancellationToken cancellationToken = default
        );
        #endregion        

        //
        #region Hub Actions ...
        /// <summary>
        /// Send Custom Push Message ...
        /// </summary>
        /// <param name="action"></param>
        /// <param name="payLoad"></param>
        /// <param name="connectionId"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        Task SendPush(
            string action,
            string payLoad,
            string connectionId = null,
            CancellationToken cancellationToken = default
        );
        #endregion        
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xPushService\Interfaces\IXBaseEntityHub.cs

using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;
using xModels.Base;

namespace xPushService.Interfaces
{
    public interface IXBaseEntityHub<TEntity, TKey>
    where TEntity : XBaseEntity<TKey>
    {
        /// <summary>
        /// Notify a New Entity added ...
        /// </summary>
        /// <param name="entity"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        Task Add(
            TEntity entity,
            CancellationToken cancellationToken = default
        );

        /// <summary>
        /// Notify a New Entity added ...
        /// </summary>
        /// <param name="entity"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        Task AddOrUpdate(
            TEntity entity,
            CancellationToken cancellationToken = default
        );

        /// <summary>
        /// Notify Add Many Entities ...
        /// </summary>
        /// <param name="entities"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        Task AddMany(
            IEnumerable<TEntity> entities,
            CancellationToken cancellationToken = default
        );

        /// <summary>
        /// Notify an Entity Deleted ...
        /// </summary>
        /// <param name="entity"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        Task Delete(
            TEntity entity,
            CancellationToken cancellationToken = default
        );

        /// <summary>
        /// Notify Delete Many Entities ...
        /// </summary>
        /// <param name="entities"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        Task DeleteMany(
            IEnumerable<TEntity> entities,
            CancellationToken cancellationToken = default
        );

        /// <summary>
        /// Notify an Entity Updated ...
        /// </summary>
        /// <param name="entity"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        Task Update(
            TEntity entity,
            CancellationToken cancellationToken = default
        );

        /// <summary>
        /// Notify Update Many Entities ...
        /// </summary>
        /// <param name="entities"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        Task UpdateMany(
            IEnumerable<TEntity> entities,
            CancellationToken cancellationToken = default
        );
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xPushService\Interfaces\IXBaseEntityProvider.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.AspNetCore.SignalR;
using Microsoft.EntityFrameworkCore.Query;
using xDataService.Configuration;
using xDataService.Interfaces;
using xIdentityService.Interfaces;
using xModels.Base;
using xModels.Dtos;
using xPushService.Base;

namespace xPushService.Interfaces
{
    /// <summary>
    /// a Provider is a way to Manipulate Data using Repository or Services and Contains Push 
    /// notifications ability ...
    /// </summary>
    /// <typeparam name="TEntity"></typeparam>
    /// <typeparam name="TKey"></typeparam>
    public interface IXBaseEntityProvider<TEntity, TKey, THub>
    where TEntity : XBaseEntity<TKey>
    where THub : XBaseEntityHub<TEntity, TKey>
    {
        //
        #region Props ...
        IHubContext<THub> Hub { get; }
        IXIdentityProvider IdentityProvider { get; }
        IXBaseRepository<TEntity, TKey> Repository { get; }
        XDataServiceConfiguration DataConfiguration { get; }
        #endregion

        //
        #region Actions ...
        /// <summary>
        /// add a new Item ...
        /// </summary>
        /// <param name="item"></param>
        /// <param name="saveChanges"></param>
        /// <param name="connectionId"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        Task<TEntity> AddAsync(
            TEntity item,
            bool saveChanges = true,
            string connectionId = null,
            CancellationToken cancellationToken = default
        );

        /// <summary>
        /// Update an Item values ...
        /// </summary>
        /// <param name="id"></param>
        /// <param name="item"></param>
        /// <param name="saveChanges"></param>
        /// <param name="connectionId"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        Task<TEntity> UpdateAsync(
            TKey id,
            TEntity item,
            bool saveChanges = true,
            string connectionId = null,
            CancellationToken cancellationToken = default
        );

        /// <summary>
        /// remove an Item by it's Id ...
        /// </summary>
        /// <param name="id"></param>
        /// <param name="softDelete"></param>
        /// <param name="saveChanges"></param>
        /// <param name="connectionId"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        Task<TEntity> RemoveAsync(
            TKey id,
            bool softDelete = true,
            bool saveChanges = true,
            string connectionId = null,
            CancellationToken cancellationToken = default
        );

        /// <summary>
        /// count all exists Items ...
        /// </summary>
        /// <param name="ignoreSoftDeleteds"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        Task<int> CountAsync(
            bool ignoreSoftDeleteds = true,
            CancellationToken cancellationToken = default
        );

        /// <summary>
        /// Check an Item exists or not ...
        /// </summary>
        /// <param name="id"></param>
        /// <param name="ignoreSoftDeleteds"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        Task<bool> IsExistsAsync(
            TKey id,
            bool ignoreSoftDeleteds = true,
            CancellationToken cancellationToken = default
        );

        /// <summary>
        /// retrieve an Item by it's Id ...
        /// </summary>
        /// <param name="id"></param>
        /// <param name="ignoreSoftDeleteds"></param>
        /// <param name="includeBuilder"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        Task<TEntity> GetAsync(
            TKey id,
            bool ignoreSoftDeleteds = true,
            Func<IQueryable<TEntity>, IIncludableQueryable<TEntity, object>> includeBuilder = null,
            CancellationToken cancellationToken = default
        );

        /// <summary>
        /// retrieve all exists Items ...
        /// </summary>
        /// <param name="ignoreSoftDeleteds"></param>
        /// <param name="orderBuilder"></param>
        /// <param name="includeBuilder"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        Task<IEnumerable<TEntity>> GetAllAsync(
            bool ignoreSoftDeleteds = true,
            Func<IQueryable<TEntity>, IOrderedQueryable<TEntity>> orderBuilder = null,
            Func<IQueryable<TEntity>, IIncludableQueryable<TEntity, object>> includeBuilder = null,
            CancellationToken cancellationToken = default
        );

        /// <summary>
        /// find an Item by providing a Conditional Expression ...
        /// </summary>
        /// <param name="predicate"></param>
        /// <param name="ignoreSoftDeleteds"></param>
        /// <param name="includeBuilder"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        Task<TEntity> FindOneAsync(
            Expression<Func<TEntity, bool>> predicate,
            bool ignoreSoftDeleteds = true,
            Func<IQueryable<TEntity>, IIncludableQueryable<TEntity, object>> includeBuilder = null,
            CancellationToken cancellationToken = default
        );

        /// <summary>
        /// find a collection of Items by proving a Conditional Expression ...
        /// </summary>
        /// <param name="predicate"></param>
        /// <param name="ignoreSoftDeleteds"></param>
        /// <param name="orderBuilder"></param>
        /// <param name="includeBuilder"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        Task<IEnumerable<TEntity>> FindManyAsync(
            Expression<Func<TEntity, bool>> predicate,
            bool ignoreSoftDeleteds = true,
            Func<IQueryable<TEntity>, IOrderedQueryable<TEntity>> orderBuilder = null,
            Func<IQueryable<TEntity>, IIncludableQueryable<TEntity, object>> includeBuilder = null,
            CancellationToken cancellationToken = default
        );

        /// <summary>
        /// retrieve Items based on XQuery Pagination structure ...
        /// </summary>
        /// <param name="query"></param>
        /// <param name="ignoreSoftDeleteds"></param>
        /// <param name="predicate"></param>
        /// <param name="orderBuilder"></param>
        /// <param name="includeBuilder"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        Task<XQueryResult<TEntity>> QueryAsync(
            XQuery query,
            bool ignoreSoftDeleteds = true,
            Expression<Func<TEntity, bool>> predicate = null,
            Func<IQueryable<TEntity>, IOrderedQueryable<TEntity>> orderBuilder = null,
            Func<IQueryable<TEntity>, IIncludableQueryable<TEntity, object>> includeBuilder = null,
            CancellationToken cancellationToken = default
        );
        #endregion        

        //
        #region Hub Actions ...
        /// <summary>
        /// Send Custom Push Message ...
        /// </summary>
        /// <param name="action"></param>
        /// <param name="payLoad"></param>
        /// <param name="connectionId"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        Task SendPush(
            string action,
            string payLoad,
            string connectionId = null,
            CancellationToken cancellationToken = default
        );
        #endregion        
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xPushService\Interfaces\IXBaseHub.cs

using System.Threading;
using System.Threading.Tasks;

namespace xPushService.Interfaces
{
    public interface IXBaseHub
    {
        Task SendCustomAction(
            string actionName,
            string payLoad,
            CancellationToken cancellationToken = default
        );
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xPushService\Interfaces\IXBaseProvided.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.EntityFrameworkCore.Query;
using xIdentityModels.Models;
using xModels.Base;
using xModels.Dtos;
using xPushService.Base;

namespace xPushService.Interfaces
{
    /// <summary>
    /// a Provided Service Used for Providing Data Based on Validations of Users ...
    /// </summary>
    /// <typeparam name="TEntity"></typeparam>
    /// <typeparam name="TDto"></typeparam>
    /// <typeparam name="TKey"></typeparam>
    /// <typeparam name="THub"></typeparam>
    public interface IXBaseProvided<TEntity, TDto, TKey, THub>
    where TEntity : XBaseEntity<TKey>
    where TDto : XBaseEntityDto<TKey>
    where THub : XBaseDtoHub<TEntity, TDto, TKey>
    {
        /// <summary>
        /// Get Specified Item by ID ...
        /// </summary>
        /// <param name="id"></param>
        /// <param name="includeBuilder"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        Task<TDto> Get(
            TKey id,
            Func<IQueryable<TEntity>, IIncludableQueryable<TEntity, object>> includeBuilder = null,
            CancellationToken cancellationToken = default
        );

        /// <summary>
        /// Get All Exists Items ...
        /// </summary>
        /// <param name="orderBuilder"></param>
        /// <param name="includeBuilder"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        Task<IEnumerable<TDto>> GetAll(
            Func<IQueryable<TEntity>, IOrderedQueryable<TEntity>> orderBuilder = null,
            Func<IQueryable<TEntity>, IIncludableQueryable<TEntity, object>> includeBuilder = null,
            CancellationToken cancellationToken = default
        );

        /// <summary>
        /// Find an item by providing a Conditional Expression ...
        /// </summary>
        /// <param name="predicate"></param>
        /// <param name="includeBuilder"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        Task<TDto> FindOne(
            Expression<Func<TEntity, bool>> predicate,
            Func<IQueryable<TEntity>, IIncludableQueryable<TEntity, object>> includeBuilder = null,
            CancellationToken cancellationToken = default
        );

        /// <summary>
        /// Find a collection of Items by proving a Conditional Expression ...
        /// </summary>
        /// <param name="predicate"></param>
        /// <param name="orderBuilder"></param>
        /// <param name="includeBuilder"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        Task<IEnumerable<TDto>> FindMany(
            Expression<Func<TEntity, bool>> predicate,
            Func<IQueryable<TEntity>, IOrderedQueryable<TEntity>> orderBuilder = null,
            Func<IQueryable<TEntity>, IIncludableQueryable<TEntity, object>> includeBuilder = null,
            CancellationToken cancellationToken = default
        );

        /// <summary>
        /// Retrieve Items based on XQuery Pagination structure ...
        /// </summary>
        /// <param name="query"></param>
        /// <param name="predicate"></param>
        /// <param name="orderBuilder"></param>
        /// <param name="includeBuilder"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        Task<XQueryResult<TDto>> Query(
            XQuery query,
            Expression<Func<TEntity, bool>> predicate = null,
            Func<IQueryable<TEntity>, IOrderedQueryable<TEntity>> orderBuilder = null,
            Func<IQueryable<TEntity>, IIncludableQueryable<TEntity, object>> includeBuilder = null,
            CancellationToken cancellationToken = default
        );

        /// <summary>
        /// Retrieve Owned Items based on XQuery Pagination structure ...
        /// if supported ...
        /// </summary>
        /// <param name="query"></param>
        /// <param name="userInfo"></param>
        /// <param name="predicate"></param>
        /// <param name="orderBuilder"></param>
        /// <param name="includeBuilder"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        Task<XQueryResult<TDto>> QueryOwned(
            XQuery query,
            XUserClaimsInfoDto userInfo = null,
            Expression<Func<TEntity, bool>> predicate = null,
            Func<IQueryable<TEntity>, IOrderedQueryable<TEntity>> orderBuilder = null,
            Func<IQueryable<TEntity>, IIncludableQueryable<TEntity, object>> includeBuilder = null,
            CancellationToken cancellationToken = default
        );

        /// <summary>
        /// Add an item values ...
        /// </summary>
        /// <param name="item"></param>
        /// <param name="userInfo"></param>
        /// <param name="connectionId"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        Task<TDto> Add(
            TDto item,
            XUserClaimsInfoDto userInfo = null,
            string connectionId = null,
            CancellationToken cancellationToken = default
        );

        /// <summary>
        /// Update an item values ...
        /// </summary>
        /// <param name="id"></param>
        /// <param name="item"></param>
        /// <param name="userInfo"></param>
        /// <param name="connectionId"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        Task<TDto> Update(
            TKey id,
            TDto item,
            XUserClaimsInfoDto userInfo = null,
            string connectionId = null,
            CancellationToken cancellationToken = default
        );

        /// <summary>
        /// remove an Item ...
        /// </summary>
        /// <param name="id"></param>
        /// <param name="userInfo"></param>
        /// <param name="connectionId"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        Task<TDto> Remove(
            TKey id,
            XUserClaimsInfoDto userInfo = null,
            string connectionId = null,
            CancellationToken cancellationToken = default
        );

        /// <summary>
        /// count all exists Items ...
        /// </summary>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        Task<int> Count(
            CancellationToken cancellationToken = default
        );

        /// <summary>
        /// Check an Item exists or not ...
        /// </summary>
        /// <param name="id"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        Task<bool> IsExists(
            TKey id,
            CancellationToken cancellationToken = default
        );
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xPushService\Interfaces\IXBaseProvidedController.cs

using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
using xModels.Base;
using xModels.Dtos;
using xPushService.Base;

namespace xPushService.Interfaces
{
    /// <summary>
    /// a Provided Controller Used for Providing a Provided Service Actions ...
    /// </summary>
    /// <typeparam name="TEntity"></typeparam>
    /// <typeparam name="TDto"></typeparam>
    /// <typeparam name="TKey"></typeparam>
    /// <typeparam name="THub"></typeparam>
    public interface IXBaseProvidedController<TEntity, TDto, TKey, THub>
    where TEntity : XBaseEntity<TKey>
    where TDto : XBaseEntityDto<TKey>
    where THub : XBaseDtoHub<TEntity, TDto, TKey>
    {
        //
        #region Retrieve ...
        /// <summary>
        /// Get Specified Item by ID ...
        /// </summary>
        /// <param name="id"></param>
        /// <param name="useDefaultIncludes"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        [HttpGet("{id}")]
        Task<ActionResult<TDto>> Get(
            [FromRoute] TKey id,
            [FromQuery] bool useDefaultIncludes = false,
            CancellationToken cancellationToken = default
        );
        
        /// <summary>
        /// Get All Exists Items ...
        /// </summary>
        /// <param name="useDefaultOrders"></param>
        /// <param name="useDefaultIncludes"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        [HttpGet("")]
        Task<ActionResult<IEnumerable<TDto>>> GetAll(
            [FromQuery] bool useDefaultOrders = false,
            [FromQuery] bool useDefaultIncludes = false,
            CancellationToken cancellationToken = default
        );

        /// <summary>
        /// Find an item by providing a Conditional Expression ...
        /// </summary>
        /// <param name="query"></param>
        /// <param name="useDefaultIncludes"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        [HttpGet("Find/One")]
        Task<ActionResult<TDto>> FindOne(
            [FromQuery] string query,
            [FromQuery] bool useDefaultIncludes = false,
            CancellationToken cancellationToken = default
        ); 

        /// <summary>
        /// Find a collection of Items by proving a Query Search ...
        /// </summary>
        /// <param name="query"></param>
        /// <param name="useDefaultOrders"></param>
        /// <param name="useDefaultIncludes"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        [HttpGet("Find/Many")]
        Task<ActionResult<IEnumerable<TDto>>> FindMany(
            [FromQuery] string query,
            [FromQuery] bool useDefaultOrders = false,
            [FromQuery] bool useDefaultIncludes = false,
            CancellationToken cancellationToken = default
        );   

        /// <summary>
        /// Retrieve Items based on XQuery Pagination structure ...
        /// </summary>
        /// <param name="query"></param>
        /// <param name="useDefaultOrders"></param>
        /// <param name="useDefaultIncludes"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        [HttpGet("Query")]
        Task<ActionResult<XQueryResult<TDto>>> Query(
            [FromQuery] XQuery query,
            [FromQuery] bool useDefaultOrders = false,
            [FromQuery] bool useDefaultIncludes = false,
            CancellationToken cancellationToken = default
        );                                    

        /// <summary>
        /// Retrieve Owned Items based on XQuery Pagination structure ...
        /// </summary>
        /// <param name="query"></param>
        /// <param name="useDefaultOrders"></param>
        /// <param name="useDefaultIncludes"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        [HttpGet("Query/Owned")]
        Task<ActionResult<XQueryResult<TDto>>> QueryOwned(
            [FromQuery] XQuery query,
            [FromQuery] bool useDefaultOrders = false,
            [FromQuery] bool useDefaultIncludes = false,
            CancellationToken cancellationToken = default
        );  
        #endregion

        //
        #region Add/Update/Remove ...
        /// <summary>
        /// Add an item ...
        /// </summary>
        /// <param name="item"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        [HttpPost("")]
        Task<ActionResult<TDto>> Add(
            [FromBody] TDto item,
            CancellationToken cancellationToken = default
        );

        /// <summary>
        /// Update an item values ...
        /// </summary>
        /// <param name="id"></param>
        /// <param name="item"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        [HttpPut("{id}")]
        Task<ActionResult<TDto>> Update(
            [FromRoute] TKey id,
            [FromBody] TDto item,
            CancellationToken cancellationToken = default
        );        

        /// <summary>
        /// Remove an Item ...
        /// </summary>
        /// <param name="id"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        [HttpDelete("{id}")]
        Task<ActionResult<TDto>> Remove(
            [FromRoute] TKey id,
            CancellationToken cancellationToken = default
        );        
        #endregion                                  
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xPushService\Interfaces\IXBaseProvider.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.AspNetCore.SignalR;
using Microsoft.EntityFrameworkCore.Query;
using xDataService.Configuration;
using xDataService.Interfaces;
using xIdentityService.Interfaces;
using xModels.Base;
using xModels.Dtos;
using xPushService.Base;

namespace xPushService.Interfaces
{
    /// <summary>
    /// a Provider is a way to Manipulate Data using Repository or Services and Contains Push 
    /// notifications ability ...
    /// </summary>
    /// <typeparam name="TEntity"></typeparam>
    /// <typeparam name="TDto"></typeparam>
    /// <typeparam name="TKey"></typeparam>
    public interface IXBaseProvider<TEntity, TDto, TKey>
    where TEntity : XBaseEntity<TKey>
    where TDto : XBaseEntityDto<TKey>
    {
        //
        #region Props ...
        //
        IXIdentityProvider IdentityProvider { get; }
        XDataServiceConfiguration DataConfiguration { get; }
        IHubContext<XBaseEntityHub<TEntity, TKey>> Hub { get; }
        IXBaseRepositoryService<TEntity, TDto, TKey> RepositoryService { get; }
        #endregion

        //
        #region Actions ...
        /// <summary>
        /// add a new Dto ...
        /// </summary>
        /// <param name="item"></param>
        /// <param name="saveChanges"></param>
        /// <param name="connectionId"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        Task<TDto> AddAsync(
            TDto item,
            bool saveChanges = true,
            string connectionId = null,
            CancellationToken cancellationToken = default
        );

        /// <summary>
        /// Update an Dto values ...
        /// </summary>
        /// <param name="id"></param>
        /// <param name="item"></param>
        /// <param name="saveChanges"></param>
        /// <param name="connectionId"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        Task<TDto> UpdateAsync(
            TKey id,
            TDto item,
            bool saveChanges = true,
            string connectionId = null,
            CancellationToken cancellationToken = default
        );

        /// <summary>
        /// remove an Dto by it's Id ...
        /// </summary>
        /// <param name="id"></param>
        /// <param name="softDelete"></param>
        /// <param name="saveChanges"></param>
        /// <param name="connectionId"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        Task<TDto> RemoveAsync(
            TKey id,
            bool softDelete = true,
            bool saveChanges = true,
            string connectionId = null,
            CancellationToken cancellationToken = default
        );

        /// <summary>
        /// count all exists Dtos ...
        /// </summary>
        /// <param name="ignoreSoftDeleteds"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        Task<int> CountAsync(
            bool ignoreSoftDeleteds = true,
            CancellationToken cancellationToken = default
        );

        /// <summary>
        /// Check a Dto exists or not ...
        /// </summary>
        /// <param name="id"></param>
        /// <param name="ignoreSoftDeleteds"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        Task<bool> IsExistsAsync(
            TKey id,
            bool ignoreSoftDeleteds = true,
            CancellationToken cancellationToken = default
        );

        /// <summary>
        /// retrieve an Dto by it's Id ...
        /// </summary>
        /// <param name="id"></param>
        /// <param name="ignoreSoftDeleteds"></param>
        /// <param name="includeBuilder"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        Task<TDto> GetAsync(
            TKey id,
            bool ignoreSoftDeleteds = true,
            Func<IQueryable<TEntity>, IIncludableQueryable<TEntity, object>> includeBuilder = null,
            CancellationToken cancellationToken = default
        );

        /// <summary>
        /// retrieve all exists Dtos ...
        /// </summary>
        /// <param name="ignoreSoftDeleteds"></param>
        /// <param name="orderBuilder"></param>
        /// <param name="includeBuilder"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        Task<IEnumerable<TDto>> GetAllAsync(
            bool ignoreSoftDeleteds = true,
            Func<IQueryable<TEntity>, IOrderedQueryable<TEntity>> orderBuilder = null,
            Func<IQueryable<TEntity>, IIncludableQueryable<TEntity, object>> includeBuilder = null,
            CancellationToken cancellationToken = default
        );

        /// <summary>
        /// find an Dto by providing a Conditional Expression ...
        /// </summary>
        /// <param name="predicate"></param>
        /// <param name="ignoreSoftDeleteds"></param>
        /// <param name="includeBuilder"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        Task<TDto> FindOneAsync(
            Expression<Func<TEntity, bool>> predicate,
            bool ignoreSoftDeleteds = true,
            Func<IQueryable<TEntity>, IIncludableQueryable<TEntity, object>> includeBuilder = null,
            CancellationToken cancellationToken = default
        );

        /// <summary>
        /// find a collection of Dtos by proving a Conditional Expression ...
        /// </summary>
        /// <param name="predicate"></param>
        /// <param name="ignoreSoftDeleteds"></param>
        /// <param name="orderBuilder"></param>
        /// <param name="includeBuilder"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        Task<IEnumerable<TDto>> FindManyAsync(
            Expression<Func<TEntity, bool>> predicate,
            bool ignoreSoftDeleteds = true,
            Func<IQueryable<TEntity>, IOrderedQueryable<TEntity>> orderBuilder = null,
            Func<IQueryable<TEntity>, IIncludableQueryable<TEntity, object>> includeBuilder = null,
            CancellationToken cancellationToken = default
        );

        /// <summary>
        /// retrieve Dtos based on XQuery Pagination structure ...
        /// </summary>
        /// <param name="query"></param>
        /// <param name="ignoreSoftDeleteds"></param>
        /// <param name="predicate"></param>
        /// <param name="orderBuilder"></param>
        /// <param name="includeBuilder"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        Task<XQueryResult<TDto>> QueryAsync(
            XQuery query,
            bool ignoreSoftDeleteds = true,
            Expression<Func<TEntity, bool>> predicate = null,
            Func<IQueryable<TEntity>, IOrderedQueryable<TEntity>> orderBuilder = null,
            Func<IQueryable<TEntity>, IIncludableQueryable<TEntity, object>> includeBuilder = null,
            CancellationToken cancellationToken = default
        );
        #endregion

        //
        #region Hub Actions ...
        /// <summary>
        /// Send Custom Push Message ...
        /// </summary>
        /// <param name="action"></param>
        /// <param name="payLoad"></param>
        /// <param name="connectionId"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        Task SendPush(
            string action,
            string payLoad,
            string connectionId = null,
            CancellationToken cancellationToken = default
        );
        #endregion        
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xPushService\Interfaces\IXBaseRepositoryProviderController.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore.Query;
using xModels.Base;
using xModels.Dtos;
using xPushService.Base;

namespace xPushService.Interfaces
{
    public interface IXBaseRepositoryProviderController<TEntity, TKey, THub>
    where TEntity : XBaseEntity<TKey>
    where THub : XBaseEntityHub<TEntity, TKey>
    {
        //
        #region Properties ...
        IXBaseEntityProvider<TEntity, TKey, THub> Provider { get; }
        Func<IQueryable<TEntity>, IOrderedQueryable<TEntity>> DefaultOrderBuilder { get; }
        Func<IQueryable<TEntity>, IIncludableQueryable<TEntity, object>> DefaultIncludeBuilder { get; }
        #endregion

        //
        #region Actions ...
        /// <summary>
        /// add a new Item ...
        /// </summary>
        /// <param name="item"></param>
        /// <param name="saveChanges"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        [HttpPost]
        Task<ActionResult<TEntity>> Add(
            [FromBody] TEntity item,
            [FromQuery] bool saveChanges = true,
            CancellationToken cancellationToken = default
        );

        /// <summary>
        /// Update an Item values ...
        /// </summary>
        /// <param name="id"></param>
        /// <param name="item"></param>
        /// <param name="saveChanges"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        [HttpPut("{id}")]
        Task<ActionResult<TEntity>> Update(
            [FromRoute] TKey id,
            [FromBody] TEntity item,
            [FromQuery] bool saveChanges = true,
            CancellationToken cancellationToken = default
        );

        /// <summary>
        /// remove an Item by it's Id ...
        /// </summary>
        /// <param name="id"></param>
        /// <param name="softDelete"></param>
        /// <param name="saveChanges"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        [HttpDelete("{id}")]
        Task<ActionResult<TEntity>> Remove(
            [FromRoute] TKey id,
            [FromQuery] bool softDelete = true,
            [FromQuery] bool saveChanges = true,
            CancellationToken cancellationToken = default
        );

        /// <summary>
        /// Check an Item exists or not ...
        /// </summary>
        /// <param name="id"></param>
        /// <param name="ignoreSoftDeleteds"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        [HttpGet("{id}/[action]")]
        Task<ActionResult<bool>> IsExists(
            [FromRoute] TKey id,
            [FromQuery] bool ignoreSoftDeleteds = true,
            CancellationToken cancellationToken = default
        );

        /// <summary>
        /// count all exists Items ...
        /// </summary>
        /// <param name="ignoreSoftDeleteds"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        [HttpGet("Count")]
        Task<ActionResult<long>> Count(
            [FromQuery] bool ignoreSoftDeleteds = true,
            CancellationToken cancellationToken = default
        );

        /// <summary>
        /// retrieve an Item by it's Id ...
        /// </summary>
        /// <param name="id"></param>
        /// <param name="ignoreSoftDeleteds"></param>
        /// <param name="useDefaultIncludes"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        [HttpGet("{id}")]
        Task<ActionResult<TEntity>> Get(
            [FromRoute] TKey id,
            [FromQuery] bool ignoreSoftDeleteds = true,
            [FromQuery] bool useDefaultIncludes = false,
            CancellationToken cancellationToken = default
        );

        /// <summary>
        /// retrieve all exists Items ...
        /// </summary>
        /// <param name="ignoreSoftDeleteds"></param>
        /// <param name="useDefaultOrders"></param>
        /// <param name="useDefaultIncludes"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        [HttpGet]
        Task<ActionResult<IEnumerable<TEntity>>> GetAll(
            [FromQuery] bool ignoreSoftDeleteds = true,
            [FromQuery] bool useDefaultOrders = false,
            [FromQuery] bool useDefaultIncludes = false,
            CancellationToken cancellationToken = default
        );

        /// <summary>
        /// find an Item by providing a Conditional Expression ...
        /// </summary>
        /// <param name="query"></param>
        /// <param name="ignoreSoftDeleteds"></param>
        /// <param name="useDefaultIncludes"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        [HttpGet("FindOne")]
        Task<ActionResult<TEntity>> FindOne(
            [FromRoute] string query,
            [FromQuery] bool ignoreSoftDeleteds = true,
            [FromQuery] bool useDefaultIncludes = false,
            CancellationToken cancellationToken = default
        );

        /// <summary>
        /// find a collection of Items by proving a Conditional Expression ...
        /// </summary>
        /// <param name="query"></param>
        /// <param name="ignoreSoftDeleteds"></param>
        /// <param name="useDefaultOrders"></param>
        /// <param name="useDefaultIncludes"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        [HttpGet("FindMany")]
        Task<ActionResult<IEnumerable<TEntity>>> FindMany(
            [FromRoute] string query,
            [FromQuery] bool ignoreSoftDeleteds = true,
            [FromQuery] bool useDefaultOrders = false,
            [FromQuery] bool useDefaultIncludes = false,
            CancellationToken cancellationToken = default
        );

        /// <summary>
        /// retrieve Items based on XQuery Pagination structure ...
        /// </summary>
        /// <param name="query"></param>
        /// <param name="ignoreSoftDeleteds"></param>
        /// <param name="useDefaultOrders"></param>
        /// <param name="useDefaultIncludes"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        [HttpGet("Query")]
        Task<ActionResult<XQueryResult<TEntity>>> Query(
            [FromQuery] XQuery query,
            [FromQuery] bool ignoreSoftDeleteds = true,
            [FromQuery] bool useDefaultOrders = false,
            [FromQuery] bool useDefaultIncludes = false,
            CancellationToken cancellationToken = default
        );
        #endregion

        //
        #region Non Actions ...
        /// <summary>
        /// Send Custom Push Message ...
        /// </summary>
        /// <param name="action"></param>
        /// <param name="payLoad"></param>
        /// <param name="connectionId"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        [NonAction]
        Task SendPush(
            string action,
            string payLoad,
            string connectionId = null,
            CancellationToken cancellationToken = default
        );
        #endregion
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xPushService\Interfaces\IXBaseServiceProviderController.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore.Query;
using xModels.Base;
using xModels.Dtos;
using xPushService.Base;

namespace xPushService.Interfaces
{
    public interface IXBaseServiceProviderController<TEntity, TDto, TKey, THub>
    where TEntity : XBaseEntity<TKey>
    where TDto : XBaseEntityDto<TKey>
    where THub : XBaseDtoHub<TEntity, TDto, TKey>
    {
        //
        #region Properties ...
        IXBaseDtoProvider<TEntity, TDto, TKey, THub> Provider { get; }
        Func<IQueryable<TEntity>, IOrderedQueryable<TEntity>> DefaultOrderBuilder { get; }
        Func<IQueryable<TEntity>, IIncludableQueryable<TEntity, object>> DefaultIncludeBuilder { get; }
        #endregion

        //
        #region Actions ...
        /// <summary>
        /// add a new Item ...
        /// </summary>
        /// <param name="item"></param>
        /// <param name="saveChanges"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        [HttpPost]
        Task<ActionResult<TDto>> Add(
            [FromBody] TDto item,
            [FromQuery] bool saveChanges = true,
            CancellationToken cancellationToken = default
        );

        /// <summary>
        /// Update an Item values ...
        /// </summary>
        /// <param name="id"></param>
        /// <param name="item"></param>
        /// <param name="saveChanges"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        [HttpPut("{id}")]
        Task<ActionResult<TDto>> Update(
            [FromRoute] TKey id,
            [FromBody] TDto item,
            [FromQuery] bool saveChanges = true,
            CancellationToken cancellationToken = default
        );

        /// <summary>
        /// remove an Item by it's Id ...
        /// </summary>
        /// <param name="id"></param>
        /// <param name="softDelete"></param>
        /// <param name="saveChanges"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        [HttpDelete("{id}")]
        Task<ActionResult<TDto>> Remove(
            [FromRoute] TKey id,
            [FromQuery] bool softDelete = true,
            [FromQuery] bool saveChanges = true,
            CancellationToken cancellationToken = default
        );

        /// <summary>
        /// Check an Item exists or not ...
        /// </summary>
        /// <param name="id"></param>
        /// <param name="ignoreSoftDeleteds"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        [HttpGet("{id}/[action]")]
        Task<ActionResult<bool>> IsExists(
            [FromRoute] TKey id,
            [FromQuery] bool ignoreSoftDeleteds = true,
            CancellationToken cancellationToken = default
        );

        /// <summary>
        /// count all exists Items ...
        /// </summary>
        /// <param name="ignoreSoftDeleteds"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        [HttpGet("Count")]
        Task<ActionResult<long>> Count(
            [FromQuery] bool ignoreSoftDeleteds = true,
            CancellationToken cancellationToken = default
        );

        /// <summary>
        /// retrieve an Item by it's Id ...
        /// </summary>
        /// <param name="id"></param>
        /// <param name="ignoreSoftDeleteds"></param>
        /// <param name="useDefaultIncludes"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        [HttpGet("{id}")]
        Task<ActionResult<TDto>> Get(
            [FromRoute] TKey id,
            [FromQuery] bool ignoreSoftDeleteds = true,
            [FromQuery] bool useDefaultIncludes = false,
            CancellationToken cancellationToken = default
        );

        /// <summary>
        /// retrieve all exists Items ...
        /// </summary>
        /// <param name="ignoreSoftDeleteds"></param>
        /// <param name="useDefaultOrders"></param>
        /// <param name="useDefaultIncludes"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        [HttpGet]
        Task<ActionResult<IEnumerable<TDto>>> GetAll(
            [FromQuery] bool ignoreSoftDeleteds = true,
            [FromQuery] bool useDefaultOrders = false,
            [FromQuery] bool useDefaultIncludes = false,
            CancellationToken cancellationToken = default
        );

        /// <summary>
        /// find an Item by providing a Conditional Expression ...
        /// </summary>
        /// <param name="query"></param>
        /// <param name="ignoreSoftDeleteds"></param>
        /// <param name="useDefaultIncludes"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        [HttpGet("FindOne")]
        Task<ActionResult<TDto>> FindOne(
            [FromRoute] string query,
            [FromQuery] bool ignoreSoftDeleteds = true,
            [FromQuery] bool useDefaultIncludes = false,
            CancellationToken cancellationToken = default
        );

        /// <summary>
        /// find a collection of Items by proving a Conditional Expression ...
        /// </summary>
        /// <param name="query"></param>
        /// <param name="ignoreSoftDeleteds"></param>
        /// <param name="useDefaultOrders"></param>
        /// <param name="useDefaultIncludes"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        [HttpGet("FindMany")]
        Task<ActionResult<IEnumerable<TDto>>> FindMany(
            [FromRoute] string query,
            [FromQuery] bool ignoreSoftDeleteds = true,
            [FromQuery] bool useDefaultOrders = false,
            [FromQuery] bool useDefaultIncludes = false,
            CancellationToken cancellationToken = default
        );

        /// <summary>
        /// retrieve Items based on XQuery Pagination structure ...
        /// </summary>
        /// <param name="query"></param>
        /// <param name="ignoreSoftDeleteds"></param>
        /// <param name="useDefaultOrders"></param>
        /// <param name="useDefaultIncludes"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        [HttpGet("Query")]
        Task<ActionResult<XQueryResult<TDto>>> Query(
            [FromQuery] XQuery query,
            [FromQuery] bool ignoreSoftDeleteds = true,
            [FromQuery] bool useDefaultOrders = false,
            [FromQuery] bool useDefaultIncludes = false,
            CancellationToken cancellationToken = default
        );
        #endregion

        //
        #region Non Actions ...
        /// <summary>
        /// Send Custom Push Message ...
        /// </summary>
        /// <param name="action"></param>
        /// <param name="payLoad"></param>
        /// <param name="connectionId"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        [NonAction]
        Task SendPush(
            string action,
            string payLoad,
            string connectionId = null,
            CancellationToken cancellationToken = default
        );
        #endregion    
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xPushService\Interfaces\IXBaseWebRTCHub.cs

using System.Threading;
using System.Threading.Tasks;

namespace xPushService.Interfaces
{
    public interface IXBaseWebRTCHub : IXBaseHub
    {
        /// <summary>
        /// Sending WebRTC Offer To Specified Connection ...
        /// </summary>
        /// <param name="offer"></param>
        /// <param name="to"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        Task Offer(
            string offer,
            string to,
            CancellationToken cancellationToken = default
        );

        /// <summary>
        /// Sending WebRTC Answer to Specified Connection ...
        /// </summary>
        /// <param name="answer"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        Task Answer(
            string answer,
            CancellationToken cancellationToken = default
        );

        /// <summary>
        /// Sending WebRTC Candidate to Specified Connecton ...
        /// </summary>
        /// <param name="candidate"></param>
        /// <param name="to"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        Task Candidate(
            string candidate,
            string to,
            CancellationToken cancellationToken = default
        );
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xPushService\Interfaces\IXHubContextFactory.cs

using Microsoft.AspNetCore.SignalR;

namespace xPushService.Interfaces
{
    public interface IXHubContextFactory
    {
        IHubContext<THub> Create<THub>() where THub : Hub;
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xPushService\Models\XHubConnectionDto.cs

using xModels.Base;

namespace xPushService.Models
{
    public class XHubConnectionDto : XBaseDto
    {
        public string ConnectionId { get; set; }
        public string UserId { get; set; }
        public string Username { get; set; }
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xPushService\Models\XHubDescriptor.cs

using System;

namespace xPushService.Models {
    /// <summary>
    /// Describe a Hub to Register ...
    /// </summary>
    public class XHubDescriptor {
        /// <summary>
        /// Specified the Hub Route ...
        /// </summary>
        /// <value></value>
        public string Route { get; set; }

        /// <summary>
        /// Specified the Hub Class Type ...
        /// </summary>
        /// <value></value>
        public Type Hub { get; set; }
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xPushService\Models\XHubUserInfo.cs

using xModels.Base;
using xIdentityModels.Constants;
using System;
using System.Collections.Generic;

namespace xPushService.Models
{
    public class XHubUserInfo : XBaseDto
    {
        //
        #region Properties ...
        public string UserId { get; set; }
        public string UserName { get; set; }
        public string FirstName { get; set; }
        public string LastName { get; set; }
        public string Picture { get; set; }
        public string Email { get; set; }
        public string PhoneNumber { get; set; }
        public XGender Gender { get; set; }
        public bool IsBanned { get; set; }
        public bool IsEnabled { get; set; }
        public bool EmailConfirmed { get; set; }
        public bool PhoneNumberConfirmed { get; set; }
        public long? ExpiredOn { get; set; }
        public long? AuthenticatedOn { get; set; }
        public DateTime? BrithDate { get; set; }
        public IEnumerable<string> Issuers { get; set; } = new HashSet<string>();
        public IEnumerable<string> Audiences { get; set; } = new HashSet<string>();
        public IEnumerable<string> ClientIds { get; set; } = new HashSet<string>();
        public IEnumerable<string> Scopes { get; set; } = new HashSet<string>();
        public IEnumerable<string> Roles { get; set; } = new HashSet<string>();
        #endregion
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xPushService\Providers\XBaseProvided.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.EntityFrameworkCore.Query;
using xCommons.Extensions;
using xExceptions.Constants;
using xIdentityModels.Extensions;
using xIdentityModels.Models;
using xModels.Base;
using xModels.Dtos;
using xPushService.Base;
using xPushService.Interfaces;

namespace xPushService.Providers
{
    /// <summary>
    /// a Provided Service Used for Providing Data Based on Validations of Users ...
    /// </summary>
    /// <typeparam name="TEntity"></typeparam>
    /// <typeparam name="TDto"></typeparam>
    /// <typeparam name="TKey"></typeparam>
    /// <typeparam name="THub"></typeparam>
    public abstract class XBaseProvided<TEntity, TDto, TKey, THub> : IXBaseProvided<TEntity, TDto, TKey, THub>
    where TEntity : XBaseEntity<TKey>
    where TDto : XBaseEntityDto<TKey>
    where THub : XBaseDtoHub<TEntity, TDto, TKey>
    {
        //
        #region Props ...
        private readonly string[] permittedRoles;
        private readonly IXBaseDtoProvider<TEntity, TDto, TKey, THub> provider;
        #endregion

        //
        #region Constructor ...
        protected XBaseProvided(
            IXBaseDtoProvider<TEntity, TDto, TKey, THub> provider,
            string[] permittedRoles = null
        )
        {
            this.provider = provider;
            this.permittedRoles = permittedRoles;
        }
        #endregion

        /// <summary>
        /// Check an Items is Owned for User or not ...
        /// </summary>
        /// <param name="item"></param>
        /// <param name="userInfo"></param>
        /// <returns></returns>
        public abstract bool IsOwned(
            TDto item,
            XUserClaimsInfoDto userInfo
        );
        public abstract bool IsOwned(
            TEntity item,
            XUserClaimsInfoDto userInfo
        );

        /// <summary>
        /// Check User Has Permission for Manipulate Data or not ...
        /// </summary>
        /// <param name="userInfo"></param>
        /// <returns></returns>
        public bool HasPermision(
            XUserClaimsInfoDto userInfo
        )
        {
            //
            var result =
                !permittedRoles.HasChild() ||
                (!userInfo.IsNullOrDefault() &&
                userInfo.HasAccess(permittedRoles));

            //
            return result;
        }

        //
        #region Provided Actions ...
        /// <summary>
        /// Get Specified Item by ID ...
        /// </summary>
        /// <param name="id"></param>
        /// <param name="includeBuilder"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public virtual async Task<TDto> Get(
            TKey id,
            Func<IQueryable<TEntity>, IIncludableQueryable<TEntity, object>> includeBuilder = null,
            CancellationToken cancellationToken = default
        )
        {
            //
            var result = await provider.GetAsync(
                id: id,
                includeBuilder: null,
                ignoreSoftDeleteds: true,
                cancellationToken: cancellationToken
            );

            //
            return result;
        }

        /// <summary>
        /// Get All Exists Items ...
        /// </summary>
        /// <param name="orderBuilder"></param>
        /// <param name="includeBuilder"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public virtual async Task<IEnumerable<TDto>> GetAll(
            Func<IQueryable<TEntity>, IOrderedQueryable<TEntity>> orderBuilder = null,
            Func<IQueryable<TEntity>, IIncludableQueryable<TEntity, object>> includeBuilder = null,
            CancellationToken cancellationToken = default
        )
        {
            //
            var result = await provider.GetAllAsync(
                ignoreSoftDeleteds: true,
                orderBuilder: orderBuilder,
                includeBuilder: includeBuilder,
                cancellationToken: cancellationToken
            );

            //
            return result;
        }

        /// <summary>
        /// find an item by providing a Conditional Expression ...
        /// </summary>
        /// <param name="predicate"></param>
        /// <param name="includeBuilder"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public virtual async Task<TDto> FindOne(
            Expression<Func<TEntity, bool>> predicate,
            Func<IQueryable<TEntity>, IIncludableQueryable<TEntity, object>> includeBuilder = null,
            CancellationToken cancellationToken = default
        )
        {
            //
            var result = await provider.FindOneAsync(
                predicate: predicate,
                ignoreSoftDeleteds: true,
                includeBuilder: includeBuilder,
                cancellationToken: cancellationToken
            );

            //
            return result;
        }

        /// <summary>
        /// find a collection of Items by proving a Conditional Expression ...
        /// </summary>
        /// <param name="predicate"></param>
        /// <param name="orderBuilder"></param>
        /// <param name="includeBuilder"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public virtual async Task<IEnumerable<TDto>> FindMany(
            Expression<Func<TEntity, bool>> predicate,
            Func<IQueryable<TEntity>, IOrderedQueryable<TEntity>> orderBuilder = null,
            Func<IQueryable<TEntity>, IIncludableQueryable<TEntity, object>> includeBuilder = null,
            CancellationToken cancellationToken = default
        )
        {
            //
            var result = await provider.FindManyAsync(
                predicate: predicate,
                ignoreSoftDeleteds: true,
                orderBuilder: orderBuilder,
                includeBuilder: includeBuilder,
                cancellationToken: cancellationToken
            );

            //
            return result;
        }

        /// <summary>
        /// retrieve Items based on XQuery Pagination structure ...
        /// </summary>
        /// <param name="query"></param>
        /// <param name="predicate"></param>
        /// <param name="orderBuilder"></param>
        /// <param name="includeBuilder"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public virtual async Task<XQueryResult<TDto>> Query(
            XQuery query,
            Expression<Func<TEntity, bool>> predicate = null,
            Func<IQueryable<TEntity>, IOrderedQueryable<TEntity>> orderBuilder = null,
            Func<IQueryable<TEntity>, IIncludableQueryable<TEntity, object>> includeBuilder = null,
            CancellationToken cancellationToken = default
        )
        {
            //
            var result = await provider.QueryAsync(
                query: query,
                predicate: predicate,
                ignoreSoftDeleteds: true,
                orderBuilder: orderBuilder,
                includeBuilder: includeBuilder,
                cancellationToken: cancellationToken
            );

            //
            return result;
        }

        /// <summary>
        /// retrieve Owned Items based on XQuery Pagination structure ...
        /// if supported ...
        /// </summary>
        /// <param name="query"></param>
        /// <param name="userInfo"></param>
        /// <param name="predicate"></param>
        /// <param name="orderBuilder"></param>
        /// <param name="includeBuilder"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public virtual async Task<XQueryResult<TDto>> QueryOwned(
            XQuery query,
            XUserClaimsInfoDto userInfo = null,
            Expression<Func<TEntity, bool>> predicate = null,
            Func<IQueryable<TEntity>, IOrderedQueryable<TEntity>> orderBuilder = null,
            Func<IQueryable<TEntity>, IIncludableQueryable<TEntity, object>> includeBuilder = null,
            CancellationToken cancellationToken = default
        )
        {
            //
            Expression<Func<TEntity, bool>> predicateor = null;
            if (!predicate.IsNull())
            {
                //
                var predicateFnc = predicate.Compile();
                predicateor = x =>
                    predicateFnc(x) &&
                    IsOwned(x, userInfo);
            }
            else
            {
                predicateor = x => IsOwned(x, userInfo);
            }

            //
            var result = await provider.QueryAsync(
                query: query,
                predicate: predicateor,
                ignoreSoftDeleteds: true,
                orderBuilder: orderBuilder,
                includeBuilder: includeBuilder,
                cancellationToken: cancellationToken
            );

            //
            return result;
        }

        /// <summary>
        /// Add an item values ...
        /// </summary>
        /// <param name="item"></param>
        /// <param name="userInfo"></param>
        /// <param name="connectionId"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public virtual async Task<TDto> Add(
            TDto item,
            XUserClaimsInfoDto userInfo = null,
            string connectionId = null,
            CancellationToken cancellationToken = default
        )
        {
            //
            var result = await provider.AddAsync(
                item: item,
                saveChanges: true,
                connectionId: connectionId,
                cancellationToken: cancellationToken
            );

            //
            return result;
        }

        /// <summary>
        /// Update an item values ...
        /// </summary>
        /// <param name="id"></param>
        /// <param name="item"></param>
        /// <param name="userInfo"></param>
        /// <param name="connectionId"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public virtual async Task<TDto> Update(
            TKey id,
            TDto item,
            XUserClaimsInfoDto userInfo = null,
            string connectionId = null,
            CancellationToken cancellationToken = default
        )
        {
            //
            // Check Permission ...
            var hasPermission =
                IsOwned(item, userInfo) ||
                HasPermision(userInfo);
            if (!hasPermission)
            {
                XException.NotAllowed.Throw();
            }

            //
            var result = await provider.UpdateAsync(
                id: id,
                item: item,
                saveChanges: true,
                connectionId: connectionId,
                cancellationToken: cancellationToken
            );

            //
            return result;
        }

        /// <summary>
        /// remove an Item ...
        /// </summary>
        /// <param name="id"></param>
        /// <param name="userInfo"></param>
        /// <param name="connectionId"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public virtual async Task<TDto> Remove(
            TKey id,
            XUserClaimsInfoDto userInfo = null,
            string connectionId = null,
            CancellationToken cancellationToken = default
        )
        {
            //
            // Check Permission ...
            var item = await Get(
                id: id,
                cancellationToken: cancellationToken
            );
            var hasPermission =
                IsOwned(item, userInfo) ||
                HasPermision(userInfo);
            if (!hasPermission)
            {
                XException.NotAllowed.Throw();
            }

            //
            var result = await provider.RemoveAsync(
                id: id,
                saveChanges: true,
                softDelete: false,
                connectionId: connectionId,
                cancellationToken: cancellationToken
            );

            //
            return result;
        }

        /// <summary>
        /// count all exists Items ...
        /// </summary>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public virtual async Task<int> Count(
            CancellationToken cancellationToken = default
        )
        {
            //
            var result = await provider.CountAsync(
                ignoreSoftDeleteds: true,
                cancellationToken: cancellationToken
            );

            //
            return result;
        }

        /// <summary>
        /// Check an Item exists or not ...
        /// </summary>
        /// <param name="id"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public virtual async Task<bool> IsExists(
            TKey id,
            CancellationToken cancellationToken = default
        )
        {
            //
            var result = await provider.IsExistsAsync(
                id: id,
                cancellationToken: cancellationToken
            );

            //
            return result;
        }
        #endregion
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xPushService\Providers\XHubContextFactory.cs

using System;
using Microsoft.AspNetCore.SignalR;
using Microsoft.Extensions.DependencyInjection;
using xPushService.Interfaces;

namespace xPushService.Providers
{
    public class XHubContextFactory : IXHubContextFactory
    {
        private readonly IServiceProvider services;

        public XHubContextFactory(IServiceProvider services)
        {
            this.services = services;
        }

        public IHubContext<THub> Create<THub>()
        where THub : Hub
        {
            return services.GetRequiredService<IHubContext<THub>>();
        }
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xPushService\Providers\XPushServiceUserNameProvider.cs

using Microsoft.AspNetCore.SignalR;

namespace xPushService.Providers {
    public class XPushServiceUserNameProvider : IUserIdProvider {
        public string GetUserId (HubConnectionContext connection) {
            //
            var result = connection.User?.Identity?.Name;
            return result;
        }
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xServices\Base\IXBaseService.cs

namespace xServices.Base
{
    public interface IXBaseService
    { }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xServices\Base\XBaseService.cs

namespace xServices.Base
{
    public class XBaseService : IXBaseService
    { }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xServices\Base\XTestProviderControllerBase.cs

using System;
using System.Linq;
using Microsoft.EntityFrameworkCore.Query;
using Microsoft.Extensions.Logging;
using xCommons.Configurations;
using xCommons.Providers;
using xIdentityService.Interfaces;
using xPushService.Controllers;
using xServices.Interfaces;
using xServices.Models.Dtos;
using xServices.Models.Entities;
using xServices.Providers;

namespace xServices.Base
{
    /// <summary>
    /// an Abstract Implementation of Provided Actions for XTest ...
    /// </summary>
    public abstract class XTestProviderControllerBase : XBaseProvidedController<XTest, XTestDto, Guid, XTestDtoHub>, IXTestProviderController
    {
        protected XTestProviderControllerBase(
            ILogger<XTestProviderControllerBase> logger,
            XAppConfiguration appConfiguration,
            IXIdentityProvider identityProvider,
            XValidationProvider validationProvider,
            IXTestProvider provider,
            Func<IQueryable<XTest>, IOrderedQueryable<XTest>> defaultOrderBuilder = null,
            Func<IQueryable<XTest>, IIncludableQueryable<XTest, object>> defaultIncludeBuilder = null
        ) : base(
            logger,
            appConfiguration,
            identityProvider,
            validationProvider,
            provider,
            defaultOrderBuilder,
            defaultIncludeBuilder
        )
        { }
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xServices\Configurations\XServicesConfiguration.cs

namespace xServices.Configurations
{
    public partial class XServicesConfiguration
    { }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xServices\Configurations\XTestTypeConfiguration.cs

using System;
using Microsoft.EntityFrameworkCore.Metadata.Builders;
using xDataService.Providers;
using xServices.Models.Entities;

namespace xServices.Configurations
{
    public class XTestTypeConfiguration : XBaseEntityTypeConfiguration<XTest, Guid>
    {
        public override void Configure(EntityTypeBuilder<XTest> builder)
        { }
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xServices\Constants\ConfigurationNodeNames.cs

namespace xServices.Constants
{
    public partial struct ConfigurationNodeNames
    {
        public const string SERVICES_NODE = "ServicesConfiguration";
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xServices\Constants\xServicesConstancts.cs

using xExceptions.Attributes;

namespace xServices.Constants
{
    public class xServicesConstancts
    {
    }

    public enum XQueryServiceEndPoints
    {
        /// <summary>
        /// Specified Endpoint for Users Fetching as Query ...
        /// </summary>
        [StringValue("Account/Users/Query")]
        QueryUsers,

        /// <summary>
        /// Refresh Tokens ...
        /// </summary>
        [StringValue("Account/RefreshTokens")]
        RefreshTokens,
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xServices\Controllers\XCategoryProviderController.cs

using System;
using System.Linq;
using Microsoft.EntityFrameworkCore.Query;
using Microsoft.Extensions.Logging;
using xCategoryService.Controllers;
using xCategoryService.Interfaces;
using xCategoryService.Models.Entities;
using xCommons.Configurations;
using xCommons.Providers;
using xIdentityService.Interfaces;

namespace xServices.Controllers
{
    public class XCategoryProviderController : XCategoryProviderControllerBase, IXCategoryProviderController
    {
        public XCategoryProviderController(
            ILogger<XCategoryProviderController> logger,
            XAppConfiguration appConfiguration,
            IXIdentityProvider identityProvider,
            XValidationProvider validationProvider,
            IXCategoryProvider provider,
            Func<IQueryable<XCategory>, IOrderedQueryable<XCategory>> defaultOrderBuilder = null,
            Func<IQueryable<XCategory>, IIncludableQueryable<XCategory, object>> defaultIncludeBuilder = null
        ) : base(
            logger,
            appConfiguration,
            identityProvider,
            validationProvider,
            provider,
            defaultOrderBuilder,
            defaultIncludeBuilder
        )
        { }
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xServices\Controllers\XFileProviderController.cs

using System;
using System.Linq;
using Microsoft.EntityFrameworkCore.Query;
using Microsoft.Extensions.Logging;
using xCommons.Configurations;
using xCommons.Providers;
using xFileService.Controllers;
using xFileService.Interfaces;
using xFileService.Models.Entities;
using xIdentityService.Interfaces;

namespace xServices.Controllers
{
    public class XFileProviderController : XFileProviderControllerBase, IXFileProviderController
    {
        public XFileProviderController(
            ILogger<XFileProviderController> logger,
            XAppConfiguration appConfiguration,
            IXIdentityProvider identityProvider,
            XValidationProvider validationProvider,
            IXFileProvider provider,
            IXFileTagProvided tagProvided,
            Func<IQueryable<XFile>, IOrderedQueryable<XFile>> defaultOrderBuilder = null,
            Func<IQueryable<XFile>, IIncludableQueryable<XFile, object>> defaultIncludeBuilder = null
        ) : base(
            logger,
            appConfiguration,
            identityProvider,
            validationProvider,
            provider,
            tagProvided,
            defaultOrderBuilder,
            defaultIncludeBuilder
        )
        { }
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xServices\Controllers\XStringProviderController.cs

using System;
using System.Linq;
using Microsoft.EntityFrameworkCore.Query;
using Microsoft.Extensions.Logging;
using xCommons.Configurations;
using xCommons.Providers;
using xIdentityService.Interfaces;
using xStringService.Controllers;
using xStringService.Interfaces;
using xStringService.Models.Entities;

namespace xServices.Controllers
{
    public class XStringProviderController : XStringProviderControllerBase, IXStringProviderController
    {
        public XStringProviderController(
            ILogger<XStringProviderController> logger,
            XAppConfiguration appConfiguration,
            IXIdentityProvider identityProvider,
            XValidationProvider validationProvider,
            IXStringProvider provider,
            Func<IQueryable<XString>, IOrderedQueryable<XString>> defaultOrderBuilder = null,
            Func<IQueryable<XString>, IIncludableQueryable<XString, object>> defaultIncludeBuilder = null
        ) : base(
            logger,
            appConfiguration,
            identityProvider,
            validationProvider,
            provider,
            defaultOrderBuilder,
            defaultIncludeBuilder
        )
        { }
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xServices\Controllers\XSubCategoryProviderController.cs

using System;
using System.Linq;
using Microsoft.EntityFrameworkCore.Query;
using Microsoft.Extensions.Logging;
using xCategoryService.Controllers;
using xCategoryService.Interfaces;
using xCategoryService.Models.Entities;
using xCommons.Configurations;
using xCommons.Providers;
using xIdentityService.Interfaces;

namespace xServices.Controllers
{
    public class XSubCategoryProviderController : XSubCategoryProviderControllerBase, IXSubCategoryProviderController
    {
        public XSubCategoryProviderController(
            ILogger<XSubCategoryProviderController> logger,
            XAppConfiguration appConfiguration,
            IXIdentityProvider identityProvider,
            XValidationProvider validationProvider,
            IXSubCategoryProvider provider,
            Func<IQueryable<XSubCategory>, IOrderedQueryable<XSubCategory>> defaultOrderBuilder = null,
            Func<IQueryable<XSubCategory>, IIncludableQueryable<XSubCategory, object>> defaultIncludeBuilder = null
        ) : base(
            logger,
            appConfiguration,
            identityProvider,
            validationProvider,
            provider,
            defaultOrderBuilder,
            defaultIncludeBuilder
        )
        { }
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xServices\Controllers\XTagProviderController.cs

using System;
using System.Linq;
using Microsoft.EntityFrameworkCore.Query;
using Microsoft.Extensions.Logging;
using xCommons.Configurations;
using xCommons.Providers;
using xIdentityService.Interfaces;
using xTagService.Controllers;
using xTagService.Interfaces;
using xTagService.Models.Entities;

namespace xServices.Controllers
{
    public class XTagProviderController : XTagProviderControllerBase, IXTagProviderController
    {
        public XTagProviderController(
            ILogger<XTagProviderController> logger,
            XAppConfiguration appConfiguration,
            IXIdentityProvider identityProvider,
            XValidationProvider validationProvider,
            IXTagProvider provider,
            Func<IQueryable<XTag>, IOrderedQueryable<XTag>> defaultOrderBuilder = null,
            Func<IQueryable<XTag>, IIncludableQueryable<XTag, object>> defaultIncludeBuilder = null
        ) : base(
            logger,
            appConfiguration,
            identityProvider,
            validationProvider,
            provider,
            defaultOrderBuilder,
            defaultIncludeBuilder
        )
        { }
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xServices\Controllers\XTermsAndConditionsProviderController.cs

using Microsoft.Extensions.Logging;
using xCommons.Configurations;
using xCommons.Providers;
using xIdentityService.Interfaces;
using xTermsAndConditionsService.Controllers;
using xTermsAndConditionsService.Interfaces;
using xTermsAndConditionsService.Providers;

namespace xServices.Controllers
{
    public class XTermsAndConditionsProviderController : XTermsAndConditionsControllerBase, IXTermsAndConditionsController
    {
        public XTermsAndConditionsProviderController(
            ILogger<XTermsAndConditionsProviderController> logger,
            XAppConfiguration appConfiguration,
            IXIdentityProvider identityProvider,
            XValidationProvider validationProvider,
            IXTermsAndConditionsProvider provider
        ) : base(
            logger,
            appConfiguration,
            identityProvider,
            validationProvider,
            provider
        )
        { }
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xServices\Controllers\XTestProviderController.cs

using System;
using System.Linq;
using Microsoft.EntityFrameworkCore.Query;
using Microsoft.Extensions.Logging;
using xCommons.Configurations;
using xCommons.Providers;
using xIdentityService.Interfaces;
using xServices.Base;
using xServices.Interfaces;
using xServices.Models.Entities;

namespace xServices.Controllers
{
    public class XTestProviderController : XTestProviderControllerBase, IXTestProviderController
    {
        public XTestProviderController(
            ILogger<XTestProviderController> logger, 
            XAppConfiguration appConfiguration, 
            IXIdentityProvider identityProvider, 
            XValidationProvider validationProvider, 
            IXTestProvider provider, 
            Func<IQueryable<XTest>, IOrderedQueryable<XTest>> defaultOrderBuilder = null, 
            Func<IQueryable<XTest>, IIncludableQueryable<XTest, object>> defaultIncludeBuilder = null
        ) : base(
            logger, 
            appConfiguration, 
            identityProvider, 
            validationProvider, 
            provider, 
            defaultOrderBuilder, 
            defaultIncludeBuilder
        )
        { }
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xServices\Databases\XApiDatabaseDescriptor.cs

using System;
using System.Collections.Generic;
using GraphQL.Types;
using xDataService.Interfaces;
using xDataService.Models;
using xServices.Interfaces;
using xServices.Models.Entities;
using xServices.Models.GraphQL;
using xServices.Providers;

namespace xServices.Databases
{
    public class XApiDatabaseDescriptor : XDatabaseDescriptor<XApiDbContext>, IXDatabaseDescriptor<XApiDbContext>
    {
        public XApiDatabaseDescriptor() : base(
            name: "xApiDb",
            repositories: new List<XRepositoryDescriptor>
            {
                //
                // XTest Entity ...
                new XEFRepositoryDescriptor<
                    XTest, 
                    Guid, 
                    IXTestKeyGenerator, 
                    XTestKeyGenerator, 
                    IXTestRepositoryEvents, 
                    XTestRepositoryEvents, 
                    XTestGraphType, 
                    GuidGraphType, 
                    XTestGraphQuery, 
                    IXTestGraphQLTypeHelper, 
                    XTestGraphQLTypeHelper, 
                    XTestGraphSchema, 
                    IXTestRepository, 
                    XTestEFRepository, 
                    XApiDbContext,
                    IXTestSeeder,
                    XTestSeeder
                >
                {}
            }
        )
        {
            OptionsBuilder = b => b.MigrationsAssembly("xApi");
        }
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xServices\Databases\XApiDbContext.cs

using Microsoft.EntityFrameworkCore;
using xCategoryService.Providers;
using xDataService.Configuration;
using xDataService.Db;
using xDataService.Providers;
using xFileService.Providers;
using xServices.Models.Entities;
using xStringService.Providers;
using xTagService.Providers;
using xWebinarService.Providers;
// using xStringService.Models.Entities;

namespace xServices.Databases
{
    public class XApiDbContext : XDbContext
    {
        //
        #region DbSets ...
        public DbSet<XTest> Tests { get; set; }
        #endregion

        //
        #region Navigation Property Entities ...
        #endregion

        public XApiDbContext(
            DbContextOptions options,
            XDataServiceConfiguration config,
            XEntityRegisterarHandlerService dynamicEntityHandlers
        ) : base(
            "xApiDb",
            options,
            config,
            dynamicEntityHandlers,
            new string[] { 
                nameof(XTagEntityRegisterar), 
                nameof(XFileEntityRegisterar), 
                nameof(XStringEntityRegisterar), 
                nameof(XWebinarEntityRegisterar), 
                nameof(XCategoryEntityRegisterar), 
                nameof(XSubCategoryEntityRegisterar), 
                nameof(XWebinarSubscriberEntityRegisterar), 
            }
        )
        { }

        //
        public override void OnXModelCreating(ModelBuilder modelBuilder)
        { }

        //
        public override void OnXConfiguring(DbContextOptionsBuilder optionsBuilder)
        { }
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xServices\DI\XDIHelperExtension.cs

using System.Collections.Generic;
using System.Linq;
using Microsoft.AspNetCore.Builder;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using xCategoryService.DI;
using xCommons.Extensions;
using xDataService.DI;
using xDataService.Models;
using xFileService.DI;
using xIdentityService.DI;
using xMessageService.DI;
using xPushService.DI;
using xPushService.Helpers;
using xServices.Configurations;
using xServices.Constants;
using xServices.Databases;
using xServices.Interfaces;
using xServices.Providers;
using xStorageService.DI;
using xStringService.DI;
using xTagService.DI;
using xTermsAndConditionsService.DI;
using xWebinarService.DI;

namespace xServices.DI
{
    public static partial class XDIHelperExtension
    {
        /// <summary>
        /// Retrive Services Configurations ...
        /// </summary>
        /// <param name="source"></param>
        /// <returns></returns>
        public static XServicesConfiguration GetXServicesConfiguration(
            this IConfiguration source
        )
        {
            //
            var xConfig = source
                .GetSection(ConfigurationNodeNames.SERVICES_NODE);
            var result = xConfig.Get<XServicesConfiguration>();

            //
            return result;
        }

        /// <summary>
        /// Register Service Configuration ...
        /// </summary>
        /// <param name="services"></param>
        /// <param name="configuration"></param>
        public static void AddXServicesConfiguration(
            this IServiceCollection services,
            IConfiguration configuration
        )
        {
            //
            var config = configuration
                .GetXServicesConfiguration();
            if (config.IsNull())
            {
                config = new XServicesConfiguration();
            }

            //
            services.AddSingleton(config);
        }

        /// <summary>
        /// Register Service Configuration ...
        /// </summary>
        /// <param name="services"></param>
        /// <param name="configuration"></param>
        public static void AddXServicesConfiguration(
            this IServiceCollection services,
            XServicesConfiguration configuration
        )
        {
            //
            if (configuration.IsNull())
            {
                configuration = new XServicesConfiguration();
            }

            //
            services.AddSingleton(configuration);
        }

        /// <summary>
        /// Register Services ...
        /// </summary>
        /// <param name="services"></param>
        /// <param name="configuration"></param>
        /// <param name="databases"></param>
        /// <param name="lifeTime"></param>
        public static void AddXServices(
            this IServiceCollection services,
            IConfiguration configuration,
            IEnumerable<XDatabaseDescriptor> databases = null,
            ServiceLifetime lifeTime = ServiceLifetime.Scoped
        )
        {
            //
            var config = configuration.GetXServicesConfiguration();

            //
            AddServices(
                config: config,
                services: services,
                lifeTime: lifeTime,
                databases: databases,
                configuration: configuration
            );
        }

        /// <summary>
        /// Register Services ...
        /// </summary>
        /// <param name="services"></param>
        /// <param name="configuration"></param>
        /// <param name="config"></param>
        /// <param name="databases"></param>
        /// <param name="lifeTime"></param>
        public static void AddXServices(
            this IServiceCollection services,
            IConfiguration configuration,
            XServicesConfiguration config,
            IEnumerable<XDatabaseDescriptor> databases = null,
            ServiceLifetime lifeTime = ServiceLifetime.Scoped
        )
        {
            //
            AddServices(
                config: config,
                services: services,
                lifeTime: lifeTime,
                databases: databases,
                configuration: configuration
            );
        }

        /// <summary>
        /// Use All Required Middlewares ...
        /// </summary>
        /// <param name="app"></param>
        /// <param name="databases"></param>
        /// <param name="isDevelopmentEnvironment"></param>
        public static void UseXServices(
            this IApplicationBuilder app,
            IEnumerable<XDatabaseDescriptor> databases = null,
            bool isDevelopmentEnvironment = false
        )
        {
            //
            // Use Storage Service ...
            app.UseXStorageService();

            //
            #region Use Data Data Service ...
            if (databases.HasChild())
            {
                //
                databases
                    .ToList()
                    .ForEach(database =>
                    {
                        //
                        app.UseXDatabase(
                            descriptor: database,
                            isDevelopmentEnvironment: isDevelopmentEnvironment
                        );
                    });
            }
            #endregion

            //
            #region Use Hubs ...
            //
            var pushHelper = new XPushServiceHelper();

            //
            pushHelper.AddHub<XTestDtoHub>("testDto");
            pushHelper.AddHub<XTestEntityHub>("testEntity");

            //
            app.UseXPushService(pushHelper);
            #endregion

            //
            // Using String Service ...
            app.UseXStringService(
                isDevelopmentEnvironment: isDevelopmentEnvironment
            );

            //
            // Using Terms and Conditions Service ...
            app.UseXTermsAndConditionsService();

            //
            // Using Tag Service ...
            app.UseXTagService(
                isDevelopmentEnvironment: isDevelopmentEnvironment
            );

            //
            // Using File Service ...
            app.UseXFileService(
                isDevelopmentEnvironment: isDevelopmentEnvironment
            );

            //
            // Using Category Service ...
            app.UseXCategoryService(
                isDevelopmentEnvironment: isDevelopmentEnvironment
            );

            //
            // Using XWebinar Service ...
            app.UsexWebinarService(
                isDevelopmentEnvironment: isDevelopmentEnvironment
            );
        }

        //
        #region Private ...
        /// <summary>
        /// Register Required Services ...
        /// </summary>
        /// <param name="services"></param>
        /// <param name="config"></param>
        /// <param name="configuration"></param>
        /// <param name="databases"></param>
        /// <param name="lifeTime"></param>
        private static void AddServices(
            this IServiceCollection services,
            IConfiguration configuration,
            XServicesConfiguration config = null,
            IEnumerable<XDatabaseDescriptor> databases = null,
            ServiceLifetime lifeTime = ServiceLifetime.Scoped
        )
        {
            //
            // Check config ...
            if (config.IsNull())
            {
                config = new XServicesConfiguration();
            }

            //
            // Storage Service ...
            services.AddXStorageService(configuration);

            //
            // Message Service ...
            services.AddXMessageService(config: configuration);

            //
            #region Register Identity Service ...
            services.AddXIdentityService(
                configuration: configuration,
                lifeTime: ServiceLifetime.Scoped
            );
            #endregion

            //
            #region Register Data Service ...
            //
            if (databases.HasChild())
            {
                //
                databases
                    .ToList()
                    .ForEach(database =>
                    {
                        //
                        // Register DataBase ...
                        services.AddXDatabase(
                            lifeTime: lifeTime,
                            descriptor: database,
                            configuration: configuration
                        );
                    });
            }

            //
            // Register Repository Services ...
            services.AddScoped<IXTestProvider, XTestProvider>();
            services.AddScoped<IXTestRepositoryService, XTestRepositoryService>();
            #endregion

            //
            #region Register Push Service ...
            //
            // Push Service ...
            services.AddXPushService(
                config: configuration,
                lifeTime: ServiceLifetime.Scoped
            );

            //
            // Register Provider Services ...
            // since Hubs required Identity Provider, you Have to Register IdentityService as Requirements ...
            // a Provider Service, Provides Repository (Entity) or Service (Dto) based
            // Data Manipulation Actions by Supporting Hub Contexts Events ...
            services.AddScoped<IXTestServiceProvider, XTestServiceProvider>();
            services.AddScoped<IXTestRepositoryProvider, XTestRepositoryProvider>();
            #endregion

            //
            var repositoryType = xDataService.Constants.XRepositoryType.EF;

            //
            // Register String Service ...
            services.AddXStringService<XApiDbContext>(
                lifeTime: lifeTime,
                repositoryType: repositoryType
            );

            //
            // Register Terms and Conditions Service ...
            services.AddXTermsConditionsService(
                lifeTime: lifeTime,
                configuration: configuration
            );

            //
            // Register Tag Service ...
            services.AddXTagService<XApiDbContext>(
                lifeTime: lifeTime,
                repositoryType: repositoryType
            );

            //
            // Register File Service ...
            services.AddXFileService<XApiDbContext>(
                lifeTime: lifeTime,
                repositoryType: repositoryType
            );

            //
            // Register Category Service ...
            services.AddXCategoryServiceConfiguration(configuration);
            services.AddXCategoryService<XApiDbContext>(
                lifeTime: lifeTime,
                repositoryType: repositoryType
            );

            //
            // Register Webinar Service ...
            services.AddXWebinarService<XApiDbContext>(
                lifeTime: lifeTime,
                repositoryType: repositoryType
            );
        }
        #endregion        
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xServices\Extensions\xServicesExtensions.cs

namespace xServices.Extensions
{
    public static class xServicesExtensions
    { }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xServices\Interfaces\IXTestDtoHub.cs

using System;
using xPushService.Interfaces;
using xServices.Models.Dtos;
using xServices.Models.Entities;

namespace xServices.Interfaces
{
    public interface IXTestDtoHub : IXBaseDtoHub<XTest, XTestDto, Guid>
    { }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xServices\Interfaces\IXTestEntityHub.cs

using System;
using xPushService.Interfaces;
using xServices.Models.Entities;

namespace xServices.Interfaces
{
    public interface IXTestEntityHub : IXBaseEntityHub<XTest, Guid>
    { }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xServices\Interfaces\IXTestGraphQLTypeHelper.cs

using System;
using xDataService.Interfaces;
using xServices.Models.Entities;

namespace xServices.Interfaces
{
    public interface IXTestGraphQLTypeHelper : IXBaseGraphQLTypeHelper<XTest, Guid>
    { }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xServices\Interfaces\IXTestGraphQuery.cs

using System;
using GraphQL.Types;
using xDataService.Interfaces;
using xServices.Models.Entities;
using xServices.Models.GraphQL;

namespace xServices.Interfaces
{
    public interface IXTestGraphQuery : IXBaseGraphQLQuery<XTest, Guid, XTestGraphType, GuidGraphType>
    {}
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xServices\Interfaces\IXTestKeyGenerator.cs

using System;
using xDataService.Interfaces;
using xServices.Models.Entities;

namespace xServices.Interfaces
{
    public interface IXTestKeyGenerator : IXKeyGenerator<XTest, Guid>
    { }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xServices\Interfaces\IXTestProvider.cs

using System;
using xPushService.Interfaces;
using xServices.Models.Dtos;
using xServices.Models.Entities;
using xServices.Providers;

namespace xServices.Interfaces
{
    public interface IXTestProvider : IXBaseProvided<XTest, XTestDto, Guid, XTestDtoHub>
    {}
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xServices\Interfaces\IXTestProviderController.cs

using System;
using xPushService.Interfaces;
using xServices.Models.Dtos;
using xServices.Models.Entities;
using xServices.Providers;

namespace xServices.Interfaces
{
    public interface IXTestProviderController : IXBaseProvidedController<XTest, XTestDto, Guid, XTestDtoHub>
    { }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xServices\Interfaces\IXTestRepository.cs

using System;
using xDataService.Interfaces;
using xServices.Models.Entities;

namespace xServices.Interfaces
{
    public interface IXTestRepository : IXBaseRepository<XTest, Guid>
    { }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xServices\Interfaces\IXTestRepositoryEvents.cs

using xDataService.Interfaces;
using xServices.Models.Entities;

namespace xServices.Interfaces
{
    public interface IXTestRepositoryEvents : IXBaseRepositoryEvents<XTest>
    { }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xServices\Interfaces\IXTestRepositoryProvider.cs

using System;
using xPushService.Interfaces;
using xServices.Models.Entities;
using xServices.Providers;

namespace xServices.Interfaces
{
    public interface IXTestRepositoryProvider : IXBaseEntityProvider<XTest, Guid, XTestEntityHub>
    { }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xServices\Interfaces\IXTestRepositoryService.cs

using System;
using xDataService.Interfaces;
using xServices.Models.Dtos;
using xServices.Models.Entities;

namespace xServices.Interfaces
{
    public interface IXTestRepositoryService : IXBaseRepositoryService<XTest, XTestDto, Guid>
    { }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xServices\Interfaces\IXTestSeeder.cs

using System;
using xDataService.Interfaces;
using xServices.Models.Entities;

namespace xServices.Interfaces
{
    public interface IXTestSeeder : IXBaseDbSeeder<XTest, Guid>
    { }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xServices\Interfaces\IXTestServiceProvider.cs

using System;
using xPushService.Interfaces;
using xServices.Models.Dtos;
using xServices.Models.Entities;
using xServices.Providers;

namespace xServices.Interfaces
{
    public interface IXTestServiceProvider : IXBaseDtoProvider<XTest, XTestDto, Guid, XTestDtoHub>
    { }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xServices\Models\Dtos\XTestDto.cs

using System;
using xModels.Base;

namespace xServices.Models.Dtos
{
    public class XTestDto : XBaseEntityDto<Guid>
    {
        public string Firstname { get; set; }
        public string Lastname { get; set; }
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xServices\Models\Entities\XTest.cs

using System;
using xModels.Base;

namespace xServices.Models.Entities
{
    public class XTest : XBaseEntity<Guid>
    {
        public string Firstname { get; set; }
        public string Lastname { get; set; }
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xServices\Models\GraphQL\XTestGraphType.cs

using System;
using xDataService.GraphQL;
using xServices.Models.Entities;

namespace xServices.Models.GraphQL
{
    public class XTestGraphType : XBaseGraphObjectType<XTest, Guid>
    {
        public XTestGraphType() : base()
        {
            Field(x => x.Firstname);
            Field(x => x.Lastname);
        }
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xServices\Models\XGroupedData.cs

using System;
using System.Collections.Generic;
using xModels.Base;

namespace xServices.Models
{
    public class XGroupedDataEntity<T, TKey, TGroupedKey>
    where T : XBaseEntity<TKey>
    {
        public TGroupedKey GroupedBy { set; get; }
        public IEnumerable<T> Members { set; get; }
        public DateTime TimeStamp { set; get; }
    }

    public class XGroupedDataDto<T, TGroupedKey>
    where T : XBaseDto
    {
        public TGroupedKey GroupedBy { set; get; }
        public IEnumerable<T> Members { set; get; }
        public DateTime TimeStamp { set; get; }
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xServices\Providers\XTestDtoHub.cs

using System;
using Microsoft.Extensions.Logging;
using xPushService.Base;
using xServices.Interfaces;
using xServices.Models.Dtos;
using xServices.Models.Entities;

namespace xServices.Providers
{
    public class XTestDtoHub : XBaseDtoHub<XTest, XTestDto, Guid>, IXTestDtoHub
    {
        public XTestDtoHub(ILogger<XTestDtoHub> logger) : base(logger)
        { }
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xServices\Providers\XTestEFRepository.cs

using System;
using xDataService.Configuration;
using xDataService.Providers;
using xDataService.Interfaces;
using xServices.Databases;
using xServices.Interfaces;
using xServices.Models.Entities;

namespace xServices.Providers
{
    public class XTestEFRepository : XBaseEFRepository<XTest, Guid, XApiDbContext>, IXTestRepository
    {
        public XTestEFRepository(
            IXUnitOfWorks<XApiDbContext> unitOfWorks, 
            XDataServiceConfiguration configuration, 
            IXTestKeyGenerator keyGenerator = null, 
            IXTestRepositoryEvents baseRepositoryEvents = null
        ) : base(
            unitOfWorks, 
            configuration, 
            keyGenerator, 
            baseRepositoryEvents
        )
        { }
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xServices\Providers\XTestEntityHub.cs

using System;
using Microsoft.Extensions.Logging;
using xPushService.Base;
using xServices.Interfaces;
using xServices.Models.Entities;

namespace xServices.Providers
{
    public class XTestEntityHub : XBaseEntityHub<XTest, Guid>, IXTestEntityHub
    {
        public XTestEntityHub(ILogger<XBaseHub> logger) : base(logger)
        { }
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xServices\Providers\XTestGraphQLTypeHelper.cs

using System;
using xDataService.Configuration;
using xDataService.GraphQL;
using xServices.Interfaces;
using xServices.Models.Entities;

namespace xServices.Providers
{
    public class XTestGraphQLTypeHelper : XBaseGraphQLTypeHelper<XTest, Guid>, IXTestGraphQLTypeHelper
    {
        public XTestGraphQLTypeHelper(
            XDataServiceConfiguration configuration
        ) : base(configuration)
        {
        }

        public override string GetInQueryCollectionName()
        {
            return "tests";
        }

        public override string GetInQuerySingleName()
        {
            return "test";
        }
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xServices\Providers\XTestGraphQuery.cs

using System;
using GraphQL.Types;
using xDataService.Configuration;
using xDataService.GraphQL;
using xServices.Interfaces;
using xServices.Models.Entities;
using xServices.Models.GraphQL;

namespace xServices.Providers
{
    public class XTestGraphQuery : XBaseGraphQLQuery<XTest, Guid, XTestGraphType, GuidGraphType>
    {
        public XTestGraphQuery(
            XDataServiceConfiguration configuration,
            IXTestRepository repository,
            IXTestGraphQLTypeHelper helper
        ) : base(
            configuration,
            repository,
            helper
        )
        { }
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xServices\Providers\XTestGraphSchema.cs

using System;
using GraphQL.Types;

namespace xServices.Providers
{
    public class XTestGraphSchema : Schema
    {
        public XTestGraphSchema(IServiceProvider services) : base(services)
        {
            Query = (XTestGraphQuery)services.GetService(typeof(XTestGraphQuery));
        }
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xServices\Providers\XTestInMemoryRepository.cs

using System;
using xDataService.Configuration;
using xDataService.Providers;
using xServices.Interfaces;
using xServices.Models.Entities;

namespace xServices.Providers
{
    public class XTestInMemoryRepository : XBaseInMemoryRepository<XTest, Guid>
    {
        public XTestInMemoryRepository(
            XDataServiceConfiguration configuration, 
            IXTestKeyGenerator keyGenerator = null, 
            IXTestRepositoryEvents baseRepositoryEvents = null
        ) : base(
            configuration, 
            keyGenerator, 
            baseRepositoryEvents
        )
        { }
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xServices\Providers\XTestKeyGenerator.cs

using xDataService.Providers;
using xServices.Interfaces;
using xServices.Models.Entities;

namespace xServices.Providers
{
    public class XTestKeyGenerator : XGuidKeyGenerator<XTest>, IXTestKeyGenerator
    { }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xServices\Providers\XTestMongoRepository.cs

using System;
using xDataService.Configuration;
using xDataService.Providers;
using xServices.Interfaces;
using xServices.Models.Entities;

namespace xServices.Providers
{
    public class XTestMongoRepository : XBaseMongoRepository<XTest, Guid>
    {
        public XTestMongoRepository(
            XDataBaseConfiguration dbConfiguration, 
            XDataServiceConfiguration configuration, 
            string collectionName = null, 
            IXTestKeyGenerator keyGenerator = null, 
            IXTestRepositoryEvents baseRepositoryEvents = null
        ) : base(
            dbConfiguration, 
            configuration, 
            collectionName, 
            keyGenerator, 
            baseRepositoryEvents
        )
        { }
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xServices\Providers\XTestProvider.cs

using System;
using xCommons.Extensions;
using xIdentityModels.Models;
using xPushService.Providers;
using xServices.Interfaces;
using xServices.Models.Dtos;
using xServices.Models.Entities;

namespace xServices.Providers
{
    public class XTestProvider : XBaseProvided<XTest, XTestDto, Guid, XTestDtoHub>, IXTestProvider
    {
        public XTestProvider(
            IXTestServiceProvider provider
        ) : base(
            provider,
            permittedRoles: new string[] { }
        )
        { }

        public override bool IsOwned(
            XTestDto item,
            XUserClaimsInfoDto userInfo
        )
        {
            return !item.IsNullOrDefault();
        }

        public override bool IsOwned(
            XTest item,
            XUserClaimsInfoDto userInfo
        )
        {
            return item.IsNullOrDefault();
        }
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xServices\Providers\XTestRepositoryEvents.cs

using xDataService.Providers;
using xServices.Interfaces;
using xServices.Models.Entities;

namespace xServices.Providers
{
    public class XTestRepositoryEvents : XBaseRepositoryEvents<XTest>, IXTestRepositoryEvents
    { }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xServices\Providers\XTestRepositoryProvider.cs

using System;
using Microsoft.AspNetCore.SignalR;
using xDataService.Configuration;
using xIdentityService.Interfaces;
using xPushService.Base;
using xServices.Interfaces;
using xServices.Models.Entities;

namespace xServices.Providers
{
    public class XTestRepositoryProvider : XBaseEntityProvider<XTest, Guid, XTestEntityHub>, IXTestRepositoryProvider
    {
        public XTestRepositoryProvider(
            IXTestRepository repository,
            IHubContext<XTestEntityHub> hub,
            XDataServiceConfiguration dataConfiguration,
            IXIdentityProvider identityProvider = null
        ) : base(
            hub: hub,
            repository: repository,
            identityProvider: identityProvider,
            dataConfiguration: dataConfiguration
        )
        { }
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xServices\Providers\XTestRepositoryService.cs

using System;
using System.Collections.Generic;
using AutoMapper;
using xDataService.Providers;
using xServices.Interfaces;
using xServices.Models.Dtos;
using xServices.Models.Entities;

namespace xServices.Providers
{
    public class XTestRepositoryService : XBaseRepositoryService<XTest, XTestDto, Guid>, IXTestRepositoryService
    {
        public XTestRepositoryService(
            IXTestRepository repository,
            IEnumerable<Profile> mapperProfiles = null
        ) : base(repository, mapperProfiles)
        { }
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xServices\Providers\XTestSeeder.cs

using System;
using xDataService.Configuration;
using xDataService.Providers;
using xServices.Interfaces;
using xServices.Models.Entities;

namespace xServices.Providers
{
    public class XTestSeeder : XBaseDbSeeder<XTest, Guid>, IXTestSeeder
    {
        public XTestSeeder(
            IXTestRepository repository,
            XDataServiceConfiguration dataServiceConfiguration
        ) : base(
            database: "xApiDb",
            entity: nameof(XTest),
            repository: repository,
            dataServiceConfiguration: dataServiceConfiguration
        )
        { }
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xServices\Providers\XTestServiceProvider.cs

using System;
using Microsoft.AspNetCore.SignalR;
using xDataService.Configuration;
using xIdentityService.Interfaces;
using xPushService.Base;
using xServices.Interfaces;
using xServices.Models.Dtos;
using xServices.Models.Entities;

namespace xServices.Providers
{
    public class XTestServiceProvider : XBaseDtoProvider<XTest, XTestDto, Guid, XTestDtoHub>, IXTestServiceProvider
    {
        public XTestServiceProvider(
            IHubContext<XTestDtoHub> hub,
            IXTestRepositoryService service,
            XDataServiceConfiguration dataConfiguration,
            IXIdentityProvider identityProvider = null
        ) : base(
            hub: hub,
            service: service,
            identityProvider: identityProvider,
            dataConfiguration: dataConfiguration
        )
        { }
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xStorageService\Constants\ConfigurationNodeNames.cs

namespace xStorageService.Constants {
    public partial struct ConfigurationNodeNames {
        public const string STORAGE_SERVICE_NODE_NAME = "StorageConfiguration";
    }

}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xStorageService\Constants\FileExtensions.cs

using xExceptions.Attributes;

namespace xStorageService.Constants {
    public enum FileExtensions {
        //
        // Document
        [StringValue (".txt")]
        TEXT = 100,

        [StringValue (".pdf")]
        PDF = 101,

        [StringValue (".ppt")]
        PPT = 102,

        [StringValue (".pptx")]
        PPTX = 103,

        [StringValue (".odp")]
        ODP = 104,

        [StringValue (".pps")]
        PPS = 105,

        [StringValue (".ods")]
        ODS = 106,

        [StringValue (".xlr")]
        XLR = 107,

        [StringValue (".xls")]
        XLS = 108,

        [StringValue (".xlsx")]
        XLSX = 109,

        [StringValue (".xml")]
        XML = 110,

        [StringValue (".doc")]
        DOC = 111,

        [StringValue (".docx")]
        DOCX = 112,

        [StringValue (".odt")]
        ODT = 113,

        [StringValue (".rtf")]
        RTF = 114,

        [StringValue (".tex")]
        TEX = 115,

        [StringValue (".wpd")]
        WPD = 116,

        [StringValue (".md")]
        MD = 117,

        //
        // Archive
        [StringValue (".zip")]
        ZIP = 200,

        //
        // Internal Supports 
        [StringValue (".ttf")]
        TTF = 300,

        [StringValue (".js")]
        JAVASCRIPT = 301,

        [StringValue (".css")]
        CSS = 302,

        [StringValue (".htm")]
        HTM = 303,

        [StringValue (".html")]
        HTML = 304,

        [StringValue (".sdw")]
        SAHER_DASHBOARD_WIDGET = 305,

        [StringValue (".sdwmanifest")]
        SAHER_DASHBOARD_WIDGET_MANIFEST = 306,

        //
        // Video
        [StringValue (".mp4")]
        MP4 = 400,

        [StringValue (".avi")]
        AVI = 401,

        [StringValue (".mpg")]
        MPG = 402,

        [StringValue (".mpeg")]
        MPEG = 403,

        [StringValue (".wmv")]
        WMV = 404,

        //
        // Audio
        [StringValue (".mp3")]
        MP3 = 500,

        [StringValue (".ogg")]
        OGG = 501,

        [StringValue (".wav")]
        WAV = 502,

        [StringValue (".wma")]
        WMA = 503,

        //
        // Image
        [StringValue (".png")]
        PNG = 600,

        [StringValue (".jpeg")]
        JPEG = 601,

        [StringValue (".jpg")]
        JPG = 602,

        // [StringValue (".ico")]
        // ICON = 603,

        [StringValue (".gif")]
        GIF = 604,

        [StringValue (".bmp")]
        BITMAP = 605,
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xStorageService\DI\XDIHelperExtension.cs

using System.IO;
using Microsoft.AspNetCore.Builder;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.FileProviders;
using xCommons.Extensions;
using xExceptions.Constants;
using xStorageService.Constants;
using xStorageService.Helpers;
using xStorageService.Interfaces;
using xStorageService.Models;
using xStorageService.Providers;

namespace xStorageService.DI {
    public static partial class XDIHelperExtension {
        /// <summary>
        /// Retrieve XStorage Configuration from AppSettings 
        /// </summary>
        /// <param name="configuration"></param>
        /// <returns></returns>
        public static XStorageConfiguration GetXStorageConfiguration (this IConfiguration configuration) {
            //
            var storageConfigurationSection = configuration.GetSection (ConfigurationNodeNames.STORAGE_SERVICE_NODE_NAME);
            return storageConfigurationSection.Get<XStorageConfiguration> ();
        }

        /// <summary>
        /// Register XStorage Configuration 
        /// </summary>
        /// <param name="services"></param>
        /// <param name="configuration"></param>
        public static void AddXStorageConfiguration (
            this IServiceCollection services,
            IConfiguration configuration
        ) {
            //
            // Check wwwroot Folder ...
            if (!Directory.Exists ("wwwroot")) {
                Directory.CreateDirectory ("wwwroot");
            }

            //
            // Retrieve and Register XStorage Configurations ...
            var xStorageConfiguration = configuration.GetXStorageConfiguration ();
            if (xStorageConfiguration.IsNull ()) {
                XException.InvalidConfiguration.Throw ();
            }

            //
            xStorageConfiguration.BaseFolder = Path.Combine (Directory.GetCurrentDirectory (), "wwwroot");
            xStorageConfiguration.RootFolder = Directory.GetDirectoryRoot (xStorageConfiguration.BaseFolder);

            //
            services.AddSingleton<XStorageConfiguration> (xStorageConfiguration);
        }

        /// <summary>
        /// Register XStorage Service 
        /// </summary>
        /// <param name="services"></param>
        /// <param name="config"></param>
        public static void AddXStorageService (
            this IServiceCollection services,
            IConfiguration configuration
        ) {
            //
            // Register and Retrieve XStorage Configuration
            services.AddXStorageConfiguration (configuration);
            var xStorageConfiguration = services.GetRegisteredService<XStorageConfiguration> ();

            //
            // Add File Provider ...
            services.AddSingleton<IFileProvider> (
                new PhysicalFileProvider (xStorageConfiguration.BaseFolder)
            );

            //
            // Register XStorageHelper Service ...
            services.AddSingleton<XStorageHelper> ();

            //
            // Register ThumbnailHelper ... 
            services.AddSingleton<IXThumbnailProvider, XThumbnailProvider> ();

            //
            // Register Storage Provider ...
            services.AddScoped<IXStorageProvider, XStorageProvider> ();

            //
            // StorageService Preperation...
            var xStorageService = services.GetRegisteredService<IXStorageProvider> ();
            xStorageService.Prepare ();
        }

        /// <summary>
        /// Use XStorage Service 
        /// </summary>
        /// <param name="app"></param>
        public static void UseXStorageService (this IApplicationBuilder app) {
            //
            // Get Instance of Scope and Service and Prepare Folder Structure ...
            using (var scope = app.ApplicationServices.CreateScope ()) {
                //
                var storageProvider = scope.ServiceProvider.GetService<IXStorageProvider> ();

                //
                storageProvider.Prepare ();
            }

            //
            // available Static Files ...
            app.UseStaticFiles ();
        }
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xStorageService\Helpers\XStorageHelper.cs

using System;
using System.IO;
using System.Linq;
using xCommons.Constants;
using xCommons.Extensions;
using xExceptions.Constants;
using xStorageService.Constants;

namespace xStorageService.Helpers {
    public partial class XStorageHelper {

        private int[] DocumentTypeThreshold = new int[] { 99, 307 };
        private int[] ImageTypeThreshold = new int[] { 599, 606 };
        private int[] AudioTypeThreshold = new int[] { 499, 504 };
        private int[] VideoTypeThreshold = new int[] { 399, 405 };

        public XStorageHelper () { }

        /// <summary>
        /// Retrieve FileType
        /// </summary>
        /// <param name="fileExtension"></param>
        /// <returns></returns>
        public XFileType GetType (int fileExtension) {
            //
            // Compare File Extension Integer Value and 
            // Find Propper Type for it ...
            if (fileExtension > DocumentTypeThreshold[0] && fileExtension < DocumentTypeThreshold[1]) {
                return XFileType.Document;
            } else if (fileExtension > VideoTypeThreshold[0] && fileExtension < VideoTypeThreshold[1]) {
                return XFileType.Video;
            } else if (fileExtension > AudioTypeThreshold[0] && fileExtension < AudioTypeThreshold[1]) {
                return XFileType.Audio;
            } else if (fileExtension > ImageTypeThreshold[0] && fileExtension < ImageTypeThreshold[1]) {
                return XFileType.Image;
            } else {
                //
                // if not in case return Document Type
                return XFileType.Document;
            }
        }

        /// <summary>
        /// Retrieve a File Type 
        /// </summary>
        /// <param name="fileName"></param>
        /// <returns></returns>
        public XFileType GetType (string fileName) {
            //
            if (fileName.IsNullOrEmpty ()) {
                XException.InavlidFile.Throw ();
            }

            //
            var ext = GetFileExtension (fileName);
            var extType = GetExtensionType (ext);
            return GetType (extType);
        }

        /// <summary>
        ///     used for validating Extension in Widget Upload ...
        /// </summary>
        /// <returns>an string array</returns>
        public string[] GetAllowedExtensionsForWidgetUpload () {
            return new [] {
                FileExtensions.SAHER_DASHBOARD_WIDGET.GetStringValue ()
            };
        }

        /// <summary>
        /// Get a Files Extension string
        /// </summary>
        /// <param name="fileName"></param>
        /// <returns></returns>
        public string GetFileExtension (string fileName) {
            //
            // Validate Args ...
            if (fileName.IsNullOrEmpty ()) {
                return null;
            }

            //
            var fileExt = "";
            try {
                fileExt = Path.GetExtension (fileName);
            } catch { }

            //
            return fileExt;
        }

        /// <summary>
        /// Get a File Name Without it's Extension
        /// </summary>
        /// <param name="fileName"></param>
        /// <returns></returns>
        public string GetFileNameWithoutExtension (string fileName) {
            //
            // Validate Args ...
            if (fileName.IsNullOrEmpty ()) {
                return null;
            }

            //
            var fileNameWithoutExt = "";
            try {
                fileNameWithoutExt = Path
                    .GetFileNameWithoutExtension (fileName);
            } catch { }

            //
            return fileNameWithoutExt;
        }

        /// <summary>
        /// Get File Extension Type
        /// </summary>
        /// <param name="fileExtension"></param>
        /// <returns></returns>
        public int GetExtensionType (string fileExtension) {
            //
            foreach (var extItem in Enum
                    .GetValues (typeof (FileExtensions))
                    .Cast<FileExtensions> ()) {
                if (extItem.GetStringValue ()
                    .Contains (fileExtension.ToLower ())) {
                    return (int) extItem;
                }
            }

            //
            return -1;
        }
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xStorageService\Interfaces\IXStorageProvider.cs

using System;
using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.FileProviders;
using xCommons.Constants;
using xModels.Dtos;
using xStorageService.Constants;
using xStorageService.Helpers;
using xStorageService.Models;

namespace xStorageService.Interfaces
{
    public partial interface IXStorageProvider
    {
        XStorageConfiguration Configuration { get; }
        XStorageHelper StorageHelper { get; }
        IFileProvider FileProvider { get; }
        IXThumbnailProvider ThumbnailProvider { get; }

        //
        #region Special Folders Path Getter (s) ...
        string GetStorageFolderPath();
        string GetTempFolderPath();
        string GetThumbFolderPath();
        string GetUploadsFolderPath();
        string GetWidgetsFolderPath();
        string GetImageFolderPath();
        string GetAudioFolderPath();
        string GetVideoFolderPath();
        string GetDocumentFolderPath();
        string FilePathResolver(string fullPath);
        string ConvertToFileUrl(string fullPath);
        #endregion

        //
        #region Prepare Storage Structure ...
        void Prepare();
        #endregion

        //
        #region Validators ...
        bool IsFolderExists(string path);
        bool IsFileExists(string filePath);
        bool IsSupportThumb(string fileName);
        bool IsSupportThumb(XFileType type);
        void ValidateFileExists(string filePath);
        void ValidateFileModel(XFileDto file);
        void ValidateFile(IFormFile file);
        void ValidateProfileImage(IFormFile file);
        #endregion

        //
        #region Generators ...
        string NewFileName();
        string GenerateThumbName(string fileName);
        string GetNewFileName(string fileName);
        #endregion

        //
        #region Tools Actions ...

        string GetFileExtension(string fileName);
        string GetFileNameWithoutExtension(string fileName);
        FileExtensions GetFileExtensionType(string fileName);
        XFileType GetFileType(string fileName);
        XFileType GetFileType(FileExtensions fileExtension);
        string GetThumbnailFileFullPath(string thumFileName);
        string GetRelatedThumbnailFullPath(string fileName);
        string GetFileTypeFolderPath(XFileType type);
        string GetFileFolderPath(
            string fileName,
            bool isTemp = false,
            bool isWidget = false
        );
        string GetFileFullPath(
            string fileName,
            bool isTemp = false,
            bool isWidget = false
        );
        Task<string> SaveFileAsync(
            IFormFile file,
            bool isTemp = false,
            bool isWidget = false,
            CancellationToken cancellationToken = default
        );
        void DeleteFile(
            string fileFullPath,
            bool forceFileExists = true,
            Exception exception = null
        );
        ICollection<string> DeleteFiles(
            ICollection<string> fileFullPaths,
            bool forceFileExists = true,
            Exception exception = null
        );
        // Task CreateThumbnail (XFile file);
        Task CreateThumbnail(
            XFileDto file,
            CancellationToken cancellationToken = default
        );
        Task CreateThumbnail(
            string fileName,
            CancellationToken cancellationToken = default
        );
        Task<XFileResult> HandleProfileImageSave(
            IFormFile file,
            CancellationToken cancellationToken = default
        );
        Task<XFileResult> HandleFileSave(
            IFormFile file,
            CancellationToken cancellationToken = default
        );
        Task<IEnumerable<XFileResult>> HandleFilesSave(
            IFormFileCollection files,
            CancellationToken cancellationToken = default
        );
        #endregion    
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xStorageService\Interfaces\IXThumbnailProvider.cs

using xStorageService.Models;

namespace xStorageService.Interfaces {
    public partial interface IXThumbnailProvider {
        void SetTempFolder (string folder);
        XImageInfo GetImageInfo (string filePath);
        void ResizeImage (
            string filePath,
            string resizedFilePath,
            int size,
            int quality
        );
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xStorageService\Models\XFileResult.cs

namespace xStorageService.Models {
    public partial class XFileResult {
        public string Name { get; set; }
        public string FileName { get; set; }
        public string FilePath { get; set; }
        public string Thmbnail { get; set; }
        public string ThmbnailPath { get; set; }
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xStorageService\Models\XImageInfo.cs

using ImageMagick;

namespace xStorageService.Models {
    public partial class XImageInfo {
        public Interlace Interlace { get; }
        public int Height { get; }
        public MagickFormat Format { get; }
        public string FileName { get; }
        public Density Density { get; }
        public CompressionMethod Compression { get; }
        public ColorSpace ColorSpace { get; }
        public int Width { get; }
        public int Quality { get; }
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xStorageService\Models\XStorageConfiguration.cs

namespace xStorageService.Models {
    public partial class XStorageConfiguration {
        /// <summary>
        /// Base Path of Identity Host Server
        /// </summary>
        /// <value></value>
        public string IdentityAuthority { get; set; }

        /// <summary>
        /// Base Path of Host Server
        /// </summary>
        /// <value></value>
        public string Authority { get; set; }

        /// <summary>
        /// Root Directory Of File Storage
        /// </summary>
        /// <value></value>        
        public string RootFolder { get; set; }

        /// <summary>
        /// Base Root of Usable Folder for Files
        /// </summary>
        /// <value></value>
        public string BaseFolder { get; set; }

        /// <summary>
        /// Storage Folder Label
        /// </summary>
        /// <value></value>
        public string Storage { get; set; }

        /// <summary>
        /// Temp Folder Label
        /// </summary>
        /// <value></value>
        public string Temp { get; set; }

        /// <summary>
        /// Thumb Folder Label
        /// </summary>
        /// <value></value>
        public string Thumb { get; set; }

        /// <summary>
        /// Uploads Folder Label
        /// </summary>
        /// <value></value>
        public string Uploads { get; set; }

        /// <summary>
        /// Widgets Folder Label
        /// </summary>
        /// <value></value>
        public string Widgets { get; set; }

        /// <summary>
        /// Images Folder Label
        /// </summary>
        /// <value></value>
        public string Image { get; set; }

        /// <summary>
        /// Audios Folder Label
        /// </summary>
        /// <value></value>
        public string Audio { get; set; }

        /// <summary>
        /// Videos Folder Label
        /// </summary>
        /// <value></value>
        public string Video { get; set; }

        /// <summary>
        /// Documents Folder Label
        /// </summary>
        /// <value></value>
        public string Document { get; set; }

        /// <summary>
        /// new Files Prefix
        /// </summary>
        /// <value></value>
        public string FilePrefix { get; set; }

        /// <summary>
        /// Thumb Files Prefix
        /// </summary>
        /// <value></value>
        public string ThumbPrefix { get; set; }

        /// <summary>
        /// Thumbnail File Sizes
        /// </summary>
        /// <value></value>
        public int ThumbSize { get; set; }

        /// <summary>
        /// Thumbnail File Quality
        /// </summary>
        /// <value></value>
        public int ThumbQuality { get; set; }

        /// <summary>
        /// Max File Size 
        /// </summary>
        /// <value></value>
        public long MaxFileSize { get; set; }
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xStorageService\Providers\XStorageProvider.cs

using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.IO;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.FileProviders;
using xCommons.Constants;
using xCommons.Extensions;
using xExceptions.Constants;
using xModels.Dtos;
using xStorageService.Constants;
using xStorageService.Helpers;
using xStorageService.Interfaces;
using xStorageService.Models;

namespace xStorageService.Providers
{
    public partial class XStorageProvider : IXStorageProvider
    {

        public readonly string BasePath;
        private readonly XFileType[] ThumbSupprtedTypes = new XFileType[] {
            XFileType.Image, XFileType.CoverImage, XFileType.ProfileImasge
        };

        public IFileProvider FileProvider { get; }
        public XStorageHelper StorageHelper { get; }
        public IXThumbnailProvider ThumbnailProvider { get; }
        public XStorageConfiguration Configuration { get; }

        public XStorageProvider(
            IFileProvider fileProvider,
            XStorageHelper storageHelper,
            IXThumbnailProvider thumbnailProvider,
            XStorageConfiguration configuration
        )
        {
            //
            FileProvider = fileProvider;
            Configuration = configuration;
            StorageHelper = storageHelper;
            ThumbnailProvider = thumbnailProvider;

            //
            BasePath = Path
                .Combine(Directory
                    .GetCurrentDirectory(), Configuration.BaseFolder);
        }

        //
        #region Special Folders Path Getter (s) ...
        /// <summary>
        /// Get Storage Folder Path
        /// </summary>
        /// <returns></returns>
        public string GetStorageFolderPath()
        {
            return Path.Combine(BasePath, Configuration.Storage);
        }

        /// <summary>
        /// Get Temp Folder Path
        /// </summary>
        /// <returns></returns>
        public string GetTempFolderPath()
        {
            return Path.Combine(GetStorageFolderPath(), Configuration.Temp);
        }

        /// <summary>
        /// Get Uploads Folder Path
        /// </summary>
        /// <returns></returns>
        public string GetUploadsFolderPath()
        {
            return Path.Combine(GetStorageFolderPath(), Configuration.Uploads);
        }

        /// <summary>
        /// Get Widgets Folder Path
        /// </summary>
        /// <returns></returns>
        public string GetWidgetsFolderPath()
        {
            return Path.Combine(GetStorageFolderPath(), Configuration.Widgets);
        }

        /// <summary>
        /// Get Thumb Folder Path
        /// </summary>
        /// <returns></returns>
        public string GetThumbFolderPath()
        {
            return Path.Combine(GetUploadsFolderPath(), Configuration.Thumb);
        }

        /// <summary>
        /// Get Images Folder Path
        /// </summary>
        /// <returns></returns>
        public string GetImageFolderPath()
        {
            return Path.Combine(GetUploadsFolderPath(), Configuration.Image);
        }

        /// <summary>
        /// Get Audios Folder Path
        /// </summary>
        /// <returns></returns>
        public string GetAudioFolderPath()
        {
            return Path.Combine(GetUploadsFolderPath(), Configuration.Audio);
        }

        /// <summary>
        /// Get Videos Folder Path
        /// </summary>
        /// <returns></returns>
        public string GetVideoFolderPath()
        {
            return Path.Combine(GetUploadsFolderPath(), Configuration.Video);
        }

        /// <summary>
        /// Get Documents Folder Path
        /// </summary>
        /// <returns></returns>
        public string GetDocumentFolderPath()
        {
            return Path.Combine(GetUploadsFolderPath(), Configuration.Document);
        }

        /// <summary>
        /// Prepare Full Path to Use for Static Files
        /// </summary>
        /// <param name="fullPath"></param>
        /// <returns></returns>
        public string FilePathResolver(string fullPath)
        {
            return fullPath.Replace(BasePath, "");
        }

        /// <summary>
        /// Convert a File Path to Url 
        /// </summary>
        /// <param name="fullPath"></param>
        /// <returns></returns>        
        public string ConvertToProfileImageUrl(string fullPath)
        {
            //
            var authority = !Configuration.IdentityAuthority.IsNullOrEmpty() &&
                Configuration.IdentityAuthority.EndsWith("/") ?
                Configuration.IdentityAuthority.Substring(0, Configuration.IdentityAuthority.Length - 1) :
                Configuration.IdentityAuthority;

            //
            return $"{authority}{FilePathResolver(fullPath)}";
        }

        /// <summary>
        /// Convert a File Path to Url 
        /// </summary>
        /// <param name="fullPath"></param>
        /// <returns></returns>        
        public string ConvertToFileUrl(string fullPath)
        {
            //
            var authority = !Configuration.Authority.IsNullOrEmpty() &&
                Configuration.Authority.EndsWith("/") ?
                Configuration.Authority.Substring(0, Configuration.Authority.Length - 1) :
                Configuration.Authority;

            //
            return $"{authority}/{FilePathResolver(fullPath)}";
        }
        #endregion

        //
        #region Prepare Storage Structure ...
        /// <summary>
        /// Check Folder Structure of Storage Area
        /// and Create them if not Exists
        /// </summary>
        public void Prepare()
        {
            //
            try
            {
                //
                // Storage Folder Path Check ...
                if (!IsFolderExists(GetStorageFolderPath()))
                {
                    Directory.CreateDirectory(GetStorageFolderPath());
                }

                //
                // Temp Folder Path Check ...
                if (!IsFolderExists(GetTempFolderPath()))
                {
                    Directory.CreateDirectory(GetTempFolderPath());
                }

                //
                // Temp Folder Path Check ...
                if (!IsFolderExists(GetThumbFolderPath()))
                {
                    Directory.CreateDirectory(GetThumbFolderPath());
                }

                //
                // Widgets Folder Path Chekc ...
                if (!IsFolderExists(GetWidgetsFolderPath()))
                {
                    Directory.CreateDirectory(GetWidgetsFolderPath());
                }

                //
                // Uploads Folder Path Chekc ...
                if (!IsFolderExists(GetUploadsFolderPath()))
                {
                    Directory.CreateDirectory(GetUploadsFolderPath());
                }

                //
                // Image Folder Path Chekc ...
                if (!IsFolderExists(GetImageFolderPath()))
                {
                    Directory.CreateDirectory(GetImageFolderPath());
                }

                //
                // Music Folder Path Chekc ...
                if (!IsFolderExists(GetAudioFolderPath()))
                {
                    Directory.CreateDirectory(GetAudioFolderPath());
                }

                //
                // Video Folder Path Chekc ...
                if (!IsFolderExists(GetVideoFolderPath()))
                {
                    Directory.CreateDirectory(GetVideoFolderPath());
                }

                //
                // Document Folder Path Chekc ...
                if (!IsFolderExists(GetDocumentFolderPath()))
                {
                    Directory.CreateDirectory(GetDocumentFolderPath());
                }
            }
            catch
            {
                XException.StorageServiceInitialFailed.Throw();
            }

            //
            // Set Temp Folder for Actions ...
            ThumbnailProvider.SetTempFolder(GetTempFolderPath());
        }
        #endregion

        //
        #region Validators ...
        /// <summary>
        /// Detrmines a Path Exists or not 
        /// </summary>
        /// <param name="path"></param>
        /// <returns></returns>
        public bool IsFolderExists(string path)
        {
            return Directory.Exists(path);
        }

        /// <summary>
        /// Check a File Exists or not
        /// </summary>
        /// <param name="filePath"></param>
        /// <returns></returns>
        public bool IsFileExists(string filePath)
        {
            return File.Exists(filePath);
        }

        /// <summary>
        /// Check a File Name Support Thumbnail or not
        /// </summary>
        /// <param name="fileName"></param>
        /// <returns></returns>
        public bool IsSupportThumb(string fileName)
        {
            //
            if (!fileName.StartsWith(Configuration.FilePrefix))
            {
                XException.InavlidFile.Throw();
            }

            //
            var fileType = StorageHelper.GetType(fileName);
            return IsSupportThumb(fileType);
        }

        /// <summary>
        /// Check a FileType Support Thumbnail or not
        /// </summary>
        /// <param name="type"></param>
        /// <returns></returns>
        public bool IsSupportThumb(XFileType type)
        {
            return ThumbSupprtedTypes.Contains(type);
        }

        /// <summary>
        /// Validate a File Exists or not
        /// </summary>
        /// <param name="filePath"></param>
        public void ValidateFileExists(string filePath)
        {
            //
            if (!IsFileExists(filePath))
            {
                XException.NotFound.Throw();
            }
        }

        /// <summary>
        /// Validate a File Model with it's Related Physical File
        /// </summary>
        /// <param name="file"></param>
        public void ValidateFileModel(XFileDto file)
        {
            //
            // Validate Args ...
            if (file == null)
            {
                XException.InvalidArgs.Throw();
            }

            //
            // Retrieve Full File Path ...
            var fileFullPath = file.Path;
            if (fileFullPath.IsNullOrEmpty())
            {
                XException.InavlidFile.Throw();
            }

            //
            // Retrieve is File Exists or not ...
            var isPhysicalFileExists = IsFileExists(file.Path);
            if (!isPhysicalFileExists)
            {
                XException.NotFound.Throw();
            }
        }

        /// <summary>
        /// Validate File for Upload
        /// </summary>
        /// <param name="file"></param>
        public void ValidateFile(IFormFile file)
        {
            //
            // Validate Args ...
            if (file == null)
            {
                XException.InvalidArgs.Throw();
            }

            //
            // Check File Size not Zero ...
            if (file.Length == 0)
            {
                XException.EmptyFile.Throw();
            }

            //
            // Check File Max Size ...
            if (file.Length > Configuration.MaxFileSize)
            {
                XException.MaxFileSizeExceeded.Throw();
            }
        }

        /// <summary>
        /// Validate a Collection of IFormFile
        /// </summary>
        /// <param name="files"></param>
        public void ValidateFiles(IFormFileCollection files)
        {
            //
            // Validate Args ...
            if (!files.HasChild())
            {
                XException.InvalidArgs.Throw();
            }

            //
            files.ToList()
                .ForEach(f => ValidateFile(f));
        }

        /// <summary>
        /// Validate File for Profile Image
        /// </summary>
        /// <param name="file"></param>
        public void ValidateProfileImage(IFormFile file)
        {
            //
            // Check File Validation ...
            // since Args Checked in File Validation, there is no need to
            // double check it ...
            ValidateFile(file);

            //
            // Check File Type ...
            var fileType = GetFileType(file.FileName);
            if (fileType != XFileType.Image)
            {
                XException.UnsupportedFileType.Throw();
            }
        }
        #endregion

        //
        #region Generators ...
        /// <summary>
        /// Generate New File
        /// </summary>
        /// <returns></returns>
        public string NewFileName()
        {
            return Configuration.FilePrefix + Guid.NewGuid().ToString().ToLower();
        }

        /// <summary>
        /// Retrieve Related Thumnail File
        /// </summary>
        /// <param name="fileName"></param>
        /// <returns></returns>
        public string GenerateThumbName(string fileName)
        {
            //
            if (!IsSupportThumb(fileName))
            {
                XException.UnsupportedFileType.Throw();
            }

            //
            return fileName.Replace(Configuration.FilePrefix, Configuration.ThumbPrefix);
        }

        /// <summary>
        /// Get a New FileName with Extension based on Given fileName
        /// </summary>
        /// <param name="fileName"></param>
        /// <returns></returns>
        public string GetNewFileName(string fileName)
        {
            //
            // Validate Args ...
            if (fileName.IsNullOrEmpty())
            {
                XException.InvalidArgs.Throw();
            }

            //
            var fileExt = GetFileExtension(fileName);
            var newFileNameWithoutExt = NewFileName();

            //
            // Generate New File Name ...
            var newFileName = string.Format("{0}{1}", newFileNameWithoutExt, fileExt);

            //
            return newFileName;
        }
        #endregion

        //
        #region Tools Actions ...
        /// <summary>
        /// Extract a FileName's Extension
        /// </summary>
        /// <param name="fileName"></param>
        /// <returns></returns>
        public string GetFileExtension(string fileName)
        {
            //
            var result = StorageHelper.GetFileExtension(fileName);
            if (result.IsNullOrEmpty())
            {
                XException.InvalidArgs.Throw();
            }

            //
            return result;
        }

        /// <summary>
        /// Extract a FileName's Without it's Extension
        /// </summary>
        /// <param name="fileName"></param>
        /// <returns></returns>
        public string GetFileNameWithoutExtension(string fileName)
        {
            //
            var result = StorageHelper.GetFileNameWithoutExtension(fileName);
            if (result.IsNullOrEmpty())
            {
                XException.InvalidArgs.Throw();
            }

            //
            return result;
        }

        /// <summary>
        /// Get file Extension of Specified File Name
        /// </summary>
        /// <param name="fileName"></param>
        /// <returns></returns>
        public FileExtensions GetFileExtensionType(string fileName)
        {
            //
            var fileExt = GetFileExtension(fileName);
            if (fileExt.IsNullOrEmpty())
            {
                XException.InvalidData.Throw();
            }

            //
            var result = StorageHelper.GetExtensionType(fileExt);
            if (result == -1)
            {
                XException.UnsupportedFileType.Throw();
            }

            //
            return (FileExtensions)result;
        }

        /// <summary>
        /// Return File Type of Specific File Name
        /// </summary>
        /// <param name="fileName"></param>
        /// <returns></returns>
        public XFileType GetFileType(string fileName)
        {
            //
            var fileExtension = GetFileExtensionType(fileName);
            return GetFileType(fileExtension);
        }

        /// <summary>
        /// Return File Type of Specific Extension
        /// </summary>
        /// <param name="fileExtension"></param>
        /// <returns></returns>
        public XFileType GetFileType(FileExtensions fileExtension)
        {
            return StorageHelper.GetType((int)fileExtension);
        }

        /// <summary>
        /// Retrieve Full Path of thumbnail File
        /// </summary>
        /// <param name="thumFileName"></param>
        /// <returns></returns>
        public string GetThumbnailFileFullPath(string thumFileName)
        {
            //
            if (!thumFileName.StartsWith(Configuration.ThumbPrefix))
            {
                XException.InavlidFile.Throw();
            }

            //
            return Path.Combine(GetThumbFolderPath(), thumFileName);
        }

        /// <summary>
        /// Retrieve a File Thumbnail Path if Supported
        /// </summary>
        /// <param name="fileName"></param>
        /// <returns></returns>
        public string GetRelatedThumbnailFullPath(string fileName)
        {
            //
            var thumbName = GenerateThumbName(fileName);
            return GetThumbnailFileFullPath(thumbName);
        }

        /// <summary>
        /// Retrieve Special File Type's Folder Path
        /// </summary>
        /// <param name="type"></param>
        /// <returns></returns>
        public string GetFileTypeFolderPath(XFileType type)
        {
            //
            // Retrieve Folder Path Based on file ...
            switch (type)
            {
                case XFileType.Image:
                case XFileType.CoverImage:
                case XFileType.ProfileImasge:
                    return GetImageFolderPath();

                case XFileType.Audio:
                    return GetAudioFolderPath();

                case XFileType.Video:
                    return GetVideoFolderPath();

                case XFileType.Document:
                default:
                    return GetDocumentFolderPath();
            }
        }

        /// <summary>
        /// Retrieve a File's Folder path
        /// </summary>
        /// <param name="fileName"></param>
        /// <param name="isTemp"></param>
        /// <param name="isWidget"></param>
        /// <returns></returns>
        public string GetFileFolderPath(
            string fileName,
            bool isTemp = false,
            bool isWidget = false
        )
        {
            //
            // Validate Args ...
            if (fileName.IsNullOrEmpty())
            {
                XException.InvalidArgs.Throw();
            }

            //
            var fileType = GetFileType(fileName);

            //
            var folderPath = "";

            //
            // if isTemp equals true
            // ignore file type and return Temp Folder ...
            if (isTemp)
            {
                folderPath = GetTempFolderPath();
            }

            //
            // if isWidget equals true and isTemp equals false
            // ignore file type and return Widget's Folder ...
            if (isWidget && !isTemp)
            {
                folderPath = GetWidgetsFolderPath();
            }

            //
            // if both isTemp and isWidget equals false 
            // which is the default state, retrieve proper folder path
            // based on file type and return it ...
            if (!isTemp && !isWidget)
            {
                folderPath = GetFileTypeFolderPath(fileType);
            }

            //
            // Check folderPath restrict to have Value ...
            if (folderPath.IsNullOrEmpty())
            {
                XException.InvalidData.Throw();
            }

            //
            // return result ...
            return folderPath;
        }

        /// <summary>
        /// Retrieve a Full path of a File
        /// </summary>
        /// <param name="fileName"></param>
        /// <param name="isTemp"></param>
        /// <param name="isWidget"></param>
        /// <returns></returns>
        public string GetFileFullPath(
            string fileName,
            bool isTemp = false,
            bool isWidget = false
        )
        {
            //
            var folderPath = GetFileFolderPath(
                fileName,
                isTemp: isTemp,
                isWidget: isWidget
            );

            //
            if (folderPath.IsNullOrEmpty())
            {
                XException.ActionFailed.Throw();
            }

            //
            return Path.Combine(folderPath, fileName);
        }

        /// <summary>
        /// Save a File into Storage Based on it's Type
        /// </summary>
        /// <param name="file"></param>
        /// <param name="isTemp"></param>
        /// <param name="isWidget"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public async Task<string> SaveFileAsync(
            IFormFile file,
            bool isTemp = false,
            bool isWidget = false,
            CancellationToken cancellationToken = default
        )
        {
            //
            // Validate Args ...
            ValidateFile(file);

            //
            // Extract and Generate required Data ...
            var fileName = GetNewFileName(file.FileName);
            var folderPath = GetFileFolderPath(file.FileName, isTemp, isWidget);
            var fileFullPath = Path.Combine(folderPath, fileName);

            //
            // Save File ...
            using (var stream = new FileStream(fileFullPath, FileMode.Create))
            {
                //
                await file.CopyToAsync(
                    stream,
                    cancellationToken
                );
            }

            //
            // Since all Required data can be Generated based on 
            // a simple file Name, there is no need to return additional 
            // data as result ...
            return fileName;
        }

        /// <summary>
        /// Delete a Physical File by Validate it's Exists
        /// </summary>
        /// <param name="fileFullPath"></param>
        /// <param name="forceFileExists"></param>
        /// <param name="exception"></param>
        public void DeleteFile(
            string fileFullPath,
            bool forceFileExists = true,
            Exception exception = null
        )
        {
            //
            // Validate Args ...
            if (!forceFileExists &&
                fileFullPath.IsNullOrEmpty())
            {
                XException.InvalidArgs.Throw();
            }

            //
            // Prepare Default Exception ...
            if (exception == null)
            {
                exception = XException.NotFound.ToException();
            }

            //
            // Check File Exists ...
            var isFileExists = File.Exists(fileFullPath);
            if (forceFileExists &&
                !isFileExists)
            {
                XException.NotFound.Throw();
            }

            //
            // Handle Prevent Error when forceFileExists false
            // and File doesn't Exists ...
            if (!forceFileExists &&
                !isFileExists)
            {
                return;
            }

            //
            File.Delete(fileFullPath);
        }

        /// <summary>
        /// Remove a List of Physical Files Path 
        /// and return Un Removable Files ...
        /// </summary>
        /// <param name="fileFullPaths"></param>
        /// <param name="forceFileExists"></param>
        /// <param name="exception"></param>
        /// <returns></returns>
        public ICollection<string> DeleteFiles(
            ICollection<string> fileFullPaths,
            bool forceFileExists = true,
            Exception exception = null
        )
        {
            //
            if (exception.IsNull())
            {
                exception = XException.NotFound.ToException();
            }

            //
            var result = fileFullPaths.Where(f => !IsFileExists(GetFileFullPath(f))).ToList();
            if (forceFileExists && result.HasChild())
            {
                throw exception;
            }

            //
            var existsFile = fileFullPaths.Where(f => IsFileExists(f)).ToList();
            existsFile.ForEach(f =>
            {
                DeleteFile(
                    f,
                    forceFileExists: forceFileExists,
                    exception: exception
                );
            });

            //
            return fileFullPaths.Except(existsFile).ToList();
        }

        /// <summary>
        /// Create Thumbnail based on FileName.Ext
        /// </summary>
        /// <param name="fileName"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public async Task CreateThumbnail(
            string fileName,
            CancellationToken cancellationToken = default
        )
        {
            //
            if (fileName.IsNullOrEmpty())
            {
                return;
            }

            //
            await Task.Run(() =>
            {
                //
                var fileFullPath = GetFileFullPath(fileName);
                if (!IsFileExists(fileFullPath))
                {
                    XException.NotFound.Throw();
                }

                //
                var thumbFileName = GenerateThumbName(fileName);
                var thumbFullPath = GetThumbnailFileFullPath(thumbFileName);

                //
                ThumbnailProvider.ResizeImage(
                    fileFullPath,
                    thumbFullPath,
                    Configuration.ThumbSize,
                    Configuration.ThumbQuality
                );
            }, cancellationToken);
        }

        /// <summary>
        /// Create Thumbnail based on XFile model
        /// </summary>
        /// <param name="file"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public async Task CreateThumbnail(
            XFileDto file,
            CancellationToken cancellationToken = default
        )
        {
            //
            await CreateThumbnail(
                file.Name,
                cancellationToken
            );
        }

        /// <summary>
        /// Save and Create a Thumbnail For Profile Image
        /// </summary>
        /// <param name="file"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public async Task<XFileResult> HandleProfileImageSave(
            IFormFile file,
            CancellationToken cancellationToken = default
        )
        {
            //
            ValidateProfileImage(file);

            //
            var savedFileName = await SaveFileAsync(
                file,
                isTemp: false,
                isWidget: false,
                cancellationToken: cancellationToken
            );
            var thumbFileName = GenerateThumbName(savedFileName);

            //
            var savedFileFullPath = GetFileFullPath(savedFileName);
            var thumbFullPath = GetThumbnailFileFullPath(thumbFileName);

            //
            await CreateThumbnail(
                savedFileName,
                cancellationToken
            );

            //
            return new XFileResult
            {
                Name = file.Name,
                FileName = savedFileName,
                FilePath = ConvertToProfileImageUrl(savedFileFullPath),
                Thmbnail = thumbFileName,
                ThmbnailPath = ConvertToProfileImageUrl(thumbFullPath)
            };
        }

        /// <summary>
        /// Handle File Upload with Support of Thumbnails ...
        /// </summary>
        /// <param name="file"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public async Task<XFileResult> HandleFileSave(
            IFormFile file,
            CancellationToken cancellationToken = default
        )
        {
            //
            ValidateFile(file);

            //
            var savedFileName = await SaveFileAsync(file, isTemp: false, isWidget: false);

            //
            var savedFileFullPath = GetFileFullPath(savedFileName);

            //
            var thumbFileName = "";
            var thumbFullPath = "";
            var fileType = GetFileType(savedFileName);
            if (fileType.IsImageKind())
            {
                //
                thumbFileName = GenerateThumbName(savedFileName);
                thumbFullPath = GetThumbnailFileFullPath(thumbFileName);

                //
                await CreateThumbnail(savedFileName);
            }

            //
            var result =
                new XFileResult
                {
                    Name = file.FileName,
                    FileName = savedFileName,
                    FilePath = ConvertToFileUrl(savedFileFullPath),
                    Thmbnail = thumbFileName,
                    ThmbnailPath = ConvertToFileUrl(thumbFullPath),
                };

            //
            return result;
        }

        /// <summary>
        /// Handle File Upload with Support of Thumbnails ...
        /// </summary>
        /// <param name="files"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public async Task<IEnumerable<XFileResult>> HandleFilesSave(
            IFormFileCollection files,
            CancellationToken cancellationToken = default
        )
        {
            //
            ValidateFiles(files);

            //
            var result = new Collection<XFileResult>();
            foreach (var file in files)
            {
                //
                var savedFileName = await SaveFileAsync(
                    file, 
                    isTemp: false, 
                    isWidget: false,
                    cancellationToken: cancellationToken
                );

                //
                var savedFileFullPath = GetFileFullPath(savedFileName);

                //
                var thumbFileName = "";
                var thumbFullPath = "";
                var fileType = GetFileType(savedFileName);
                if (fileType.IsImageKind())
                {
                    //
                    thumbFileName = GenerateThumbName(savedFileName);
                    thumbFullPath = GetThumbnailFileFullPath(thumbFileName);

                    //
                    await CreateThumbnail(
                        savedFileName,
                        cancellationToken
                    );
                }

                //
                result.Add(
                    new XFileResult
                    {
                        Name = file.FileName,
                        FileName = savedFileName,
                        FilePath = ConvertToFileUrl(savedFileFullPath),
                        Thmbnail = thumbFileName,
                        ThmbnailPath = ConvertToFileUrl(thumbFullPath),
                    });
            }

            //
            return result;
        }
        #endregion
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xStorageService\Providers\XThumbnailProvider.cs

using ImageMagick;
using xCommons.Extensions;
using xStorageService.Interfaces;
using xStorageService.Models;

namespace xStorageService.Providers {
    public partial class XThumbnailProvider : IXThumbnailProvider {
        public void SetTempFolder (string folder) {
            MagickNET.SetTempDirectory (folder);
        }

        public XImageInfo GetImageInfo (string filePath) {
            //
            MagickImageInfo info = new MagickImageInfo (filePath);
            return info.MapConvert<XImageInfo, MagickImageInfo> ();
        }

        public void ResizeImage (
            string filePath,
            string resizedFilePath,
            int size,
            int quality
        ) {
            //
            using (var image = new MagickImage (filePath)) {
                //
                image.Resize (size, size);
                image.Strip ();
                image.Quality = quality;
                image.Write (resizedFilePath);
            }
        }
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xStringService\Configurations\Entities\XStringEntityConfiguration.cs

using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Metadata.Builders;
using xDataService.Providers;
using xStringService.Constants;
using xStringService.Models.Entities;

namespace xStringService.Configurations.Entities
{
    public class XStringEntityConfiguration : XBaseEntityTypeConfiguration<XString, int>
    {
        public override void Configure(EntityTypeBuilder<XString> builder)
        {
            builder.ToTable(XStringServiceConstants.XStringTable);
        }
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xStringService\Constants\XStringServiceConstants.cs

namespace xStringService.Constants
{
    public struct XStringServiceConstants
    {
        //
        // Service Extensions Log Tag ...
        public const string XStringServiceDILogTag = "XStringService";

        //
        // Table Mapping Identifiers ...
        public const string XStringTable = "Strings";

        //
        // GraphQL Collection Mappings ...
        public const string XStringSingleName = "string";
        public const string XStringCollectionName = "strings";

        //
        // Hubs ...
        public const string XStringDtoHub = "stringDto";
        public const string XStringEntityHub = "stringEntity";

        //
        // Custome Constants ...

        //
        // EF Repositories Helper Extensions ...
        public const string GetXStringEFRepositoryDescriptor = "GetXStringEFRepositoryDescriptor";        
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xStringService\Controllers\XBaseItemResourceProviderControllerBase.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Logging;
using xCommons.Configurations;
using xCommons.Extensions;
using xCommons.Providers;
using xExceptions.Constants;
using xIdentityService.Controllers;
using xIdentityService.Interfaces;
using xModels.Dtos;
using xStringService.Interfaces;
using xStringService.Models.Dtos;

namespace xStringService.Controllers
{
    public abstract class XBaseItemResourceProviderControllerBase : XBaseIdentityApiV1Controller, IXBaseItemResourceProviderController
    {
        private readonly IXItemResourceProvider provider;

        protected XBaseItemResourceProviderControllerBase(
            ILogger<XBaseItemResourceProviderControllerBase> logger,
            XAppConfiguration appConfiguration,
            IXIdentityProvider identityProvider,
            XValidationProvider validationProvider,
            IXItemResourceProvider provider
        ) : base(
            logger,
            appConfiguration,
            identityProvider,
            validationProvider
        )
        {
            this.provider = provider;
        }

        //
        #region Actions ...
        /// <summary>
        /// Retrieve a List of Exists Languages ...
        /// </summary>
        /// <param name="identifier">if null or empty, check all languages in Item Side</param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        [HttpGet("Languages")]
        public virtual async Task<ActionResult<IEnumerable<string>>> GetLanguages(
            [FromQuery] object identifier,
            CancellationToken cancellationToken = default
        )
        {
            //
            try
            {
                //
                var result = Enumerable.Empty<string>();
                if (!identifier.IsNull())
                {
                    //
                    result = await provider.GetLanguages(
                        identifier: identifier,
                        cancellationToken: cancellationToken
                    );
                }
                else
                {
                    //
                    result = await provider.GetLanguages(
                        cancellationToken: cancellationToken
                    );
                }

                //
                return Ok(result.ToDynamicObject());
            }
            catch (Exception ex)
            {
                //
                var result = GetExceptionActionResult(ex);
                return result;
            }
        }

        /// <summary>
        /// Retrieve all Exists Items ...
        /// </summary>
        /// <param name="resource">Specified Resource Title</param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        [HttpGet("ResourceLocales")]
        public virtual async Task<ActionResult<IEnumerable<XStringDto>>> GetResourceLocales(
            [FromQuery] object identifier,
            CancellationToken cancellationToken = default
        )
        {
            //
            try
            {
                //
                var result = Enumerable.Empty<XStringDto>();
                if (!identifier.IsNull())
                {
                    //
                    result = await provider.GetResourceLocales(
                        identifier: identifier,
                        cancellationToken: cancellationToken
                    );
                }
                else
                {
                    //
                    result = await provider.GetResourceLocales(
                        cancellationToken: cancellationToken
                    );
                }

                //
                return Ok(result.ToDynamicObject());
            }
            catch (Exception ex)
            {
                //
                var result = GetExceptionActionResult(ex);
                return result;
            }
        }

        /// <summary>
        /// Get all Exists Items for Specified identitifer ...
        /// </summary>
        /// <param name="identifier"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        [HttpGet("Locales/{identifier}")]
        public virtual async Task<ActionResult<IEnumerable<XLocaleResourceDto>>> GetLocales(
            [FromRoute] object identifier,
            CancellationToken cancellationToken = default
        )
        {
            //
            try
            {
                //

                //
                return Ok();
            }
            catch (Exception ex)
            {
                var result = GetExceptionActionResult(ex);
                return result;
            }
        }

        /// <summary>
        /// Remove Specified Language Locale of Specified Identifier ...
        /// </summary>
        /// <param name="identifier"></param>
        /// <param name="language">if null or empty Remove all Locales</param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        [HttpDelete("Locales/{identifier}")]
        public virtual async Task<ActionResult<XResourceDto>> RemoveLocale(
            [FromRoute] object identifier,
            [FromQuery] string language,
            CancellationToken cancellationToken = default
        )
        {
            //
            try
            {
                //
                // Validate ...
                var isValid = !identifier.IsNull();
                if (!isValid)
                {
                    XException.InvalidArgs.Throw();
                }

                //
                // Retrieve Connection ID ...
                var connectionId = GetConnectionId();

                //
                XResourceDto result = null;
                if (!language.IsNullOrEmpty())
                {
                    //
                    result = await provider.RemoveLocale(
                        language: language,
                        identifier: identifier,
                        connectionId: connectionId,
                        cancellationToken: cancellationToken
                    );
                }
                else
                {
                    //
                    await provider.RemoveLocales(
                        identifier: identifier,
                        connectionId: connectionId,
                        cancellationToken: cancellationToken
                    );
                }

                //
                return Ok(result.ToDynamicObject());
            }
            catch (Exception ex)
            {
                //
                var result = GetExceptionActionResult(ex);
                return result;
            }
        }

        /// <summary>
        /// Check Specified ocale Exists for Specified Identifier ...
        /// </summary>
        /// <param name="identifier"></param>
        /// <param name="language"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        [HttpGet("Locales/{identifier}/{language}/Has")]
        public virtual async Task<ActionResult<bool>> HasLocale(
            [FromRoute] object identifier,
            [FromRoute] string language,
            CancellationToken cancellationToken = default
        )
        {
            //
            try
            {
                //
                // Validate ...
                await ValidationProvider
                    .GroupValidationBuilder()
                    .AddNotEmpty(language)
                    .AddNotNull(identifier)
                    .ValidateGroupAsync();

                //
                // Calculate Result ...
                var result = await provider.HasLocale(
                    language: language,
                    identifier: identifier,
                    cancellationToken: cancellationToken
                );

                //
                return Ok(result);
            }
            catch (Exception ex)
            {
                //
                var result = GetExceptionActionResult(ex);
                return result;
            }
        }

        /// <summary>
        /// Get all Exists Locales Representaion based on Specified Identitifer
        /// as XResourceDto ...
        /// </summary>
        /// <param name="identifier"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        [HttpGet("Resource/{identifier}")]
        public virtual async Task<ActionResult<XResourceDto>> GetResource(
            [FromRoute] object identifier,
            CancellationToken cancellationToken = default
        )
        {
            //
            try
            {
                //
                // Validate ...
                ValidationProvider.NotNull(identifier);

                //
                var result = await provider.GetResource(
                    identifier: identifier,
                    cancellationToken: cancellationToken
                );

                //
                return Ok(result.ToDynamicObject());
            }
            catch (Exception ex)
            {
                //
                var result = GetExceptionActionResult(ex);
                return result;
            }
        }

        /// <summary>
        /// Add Or Update Locale for Specified Identitifer ...
        /// </summary>
        /// <param name="identifier"></param>
        /// <param name="locale"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        [HttpPost("Locales/{identifier}")]
        public virtual async Task<ActionResult<XResourceDto>> AddOrUpdateLocale(
            [FromRoute] object identifier,
            [FromBody] XLocaleResourceDto locale,
            CancellationToken cancellationToken = default
        )
        {
            //
            try
            {
                //
                // Validate ...
                await ValidationProvider
                    .GroupValidationBuilder()
                    .AddNotNull(identifier)
                    .AddNotNull(locale)
                    .AddNotEmpty(locale.Value)
                    .AddNotEmpty(locale.Language)
                    .ValidateGroupAsync();

                //
                // Retrieve Connection ID ...
                var connectionId = GetConnectionId();

                //
                var result = await provider.AddOrUpdateLocale(
                    locale: locale,
                    identifier: identifier,
                    connectionId: connectionId,
                    cancellationToken: cancellationToken
                );

                //
                return Ok(result.ToDynamicObject());
            }
            catch (Exception ex)
            {
                var result = GetExceptionActionResult(ex);
                return result;
            }
        }

        /// <summary>
        /// Update a Resource State ...
        /// </summary>
        /// <param name="identifier"></param>
        /// <param name="resource"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        [HttpPost("Resource/{identifier}")]
        public virtual async Task<ActionResult<XResourceDto>> AddOrUpdateResource(
            [FromRoute] object identifier,
            [FromBody] XResourceDto resource,
            CancellationToken cancellationToken = default
        )
        {
            //
            try
            {
                //
                // Validate ...
                await ValidationProvider
                    .GroupValidationBuilder()
                    .AddNotNull(identifier)
                    .AddNotNull(resource)
                    .ValidateGroupAsync();

                //
                // Retrieve Connection ID ...
                var connectionId = GetConnectionId();

                //
                var result = await provider.AddOrUpdateResource(
                    resource: resource,
                    identifier: identifier,
                    connectionId: connectionId,
                    cancellationToken: cancellationToken
                );

                //
                return Ok(result.ToDynamicObject());
            }
            catch (Exception ex)
            {
                //
                var result = GetExceptionActionResult(ex);
                return result;
            }
        }
        #endregion
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xStringService\Controllers\XBaseResourceProviderControllerBase.cs

using System;
using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Logging;
using xCommons.Configurations;
using xCommons.Extensions;
using xCommons.Providers;
using xIdentityService.Controllers;
using xIdentityService.Interfaces;
using xModels.Dtos;
using xStringService.Interfaces;
using xStringService.Models.Dtos;

namespace xStringService.Controllers
{
    public abstract class XBaseResourceProviderControllerBase<TResourceProvider> : XBaseIdentityApiV1Controller, IXBaseResourceProviderController
    where TResourceProvider : IXResourceProvider
    {
        private readonly TResourceProvider provider;

        protected XBaseResourceProviderControllerBase(
            ILogger<XBaseResourceProviderControllerBase<TResourceProvider>> logger,
            XAppConfiguration appConfiguration,
            IXIdentityProvider identityProvider,
            XValidationProvider validationProvider,
            TResourceProvider provider
        ) : base(
            logger,
            appConfiguration,
            identityProvider,
            validationProvider
        )
        {
            this.provider = provider;
        }

        #region Actions ...
        /// <summary>
        /// Retrieve a List of Exists Languages ...
        /// </summary>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        [HttpGet("Languages")]
        public virtual async Task<ActionResult<IEnumerable<string>>> GetLanguages(
            CancellationToken cancellationToken = default
        )
        {
            //
            try
            {
                //
                var result = await provider
                    .GetLanguages(cancellationToken);

                //
                return Ok(result.ToDynamicObject());
            }
            catch (Exception ex)
            {
                //
                var result = GetExceptionActionResult(ex);
                return result;
            }
        }

        /// <summary>
        /// Retrieve all Exists Items ...
        /// </summary>
        /// <param name="resource">Specified Resource Title</param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        [HttpGet("LocalesResource")]
        public virtual async Task<ActionResult<IEnumerable<XStringDto>>> GetResourceLocales(
            CancellationToken cancellationToken = default
        )
        {
            //
            try
            {
                //
                var result = await provider
                    .GetResourceLocales(cancellationToken);

                //
                return Ok(result.ToDynamicObject());
            }
            catch (Exception ex)
            {
                //
                var result = GetExceptionActionResult(ex);
                return result;
            }
        }

        /// <summary>
        /// Extract Translation of in Specified Language ...
        /// </summary>
        /// <param name="language">Specified Language ...</param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        [HttpGet("{language}/Translation")]
        public virtual async Task<ActionResult<string>> GetResourceTranslation(
            [FromRoute] string language,
            CancellationToken cancellationToken = default
        )
        {
            //
            try
            {
                //
                var result = await provider
                    .GetResourceTranslation(
                        language: language,
                        cancellationToken: cancellationToken
                    );

                //
                return Ok(result);
            }
            catch (Exception ex)
            {
                //
                var result = GetExceptionActionResult(ex);
                return result;
            }
        }

        /// <summary>
        /// Check Has Specified Translation or not ...
        /// </summary>
        /// <param name="language">Specified Language ...</param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        [HttpGet("{language}/Has")]
        public virtual async Task<ActionResult<bool>> HasLocale(
            [FromRoute] string language,
            CancellationToken cancellationToken = default
        )
        {
            //
            try
            {
                //
                var result = await provider
                    .HasLocale(
                        language: language,
                        cancellationToken: cancellationToken
                    );

                //
                return Ok(result);
            }
            catch (Exception ex)
            {
                //
                var result = GetExceptionActionResult(ex);
                return result;
            }
        }

        /// <summary>
        /// Retrieve as Locale Model ...
        /// </summary>
        /// <param name="language">Specified Language ...</param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        [HttpGet("{language}/Locale")]
        public virtual async Task<ActionResult<XLocaleResourceDto>> GetLocale(
            [FromRoute] string language,
            CancellationToken cancellationToken = default
        )
        {
            //
            try
            {
                //
                var result = await provider
                    .GetLocale(
                        language: language,
                        cancellationToken: cancellationToken
                    );

                //
                return Ok(result);
            }
            catch (Exception ex)
            {
                //
                var result = GetExceptionActionResult(ex);
                return result;
            }
        }

        /// <summary>
        /// Retrieve all Exists Locale Models ...
        /// </summary>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        [HttpGet("Locales")]
        public virtual async Task<ActionResult<IEnumerable<XLocaleResourceDto>>> GetLocales(
            CancellationToken cancellationToken = default
        )
        {
            //
            try
            {
                //
                var result = await provider
                    .GetLocales(cancellationToken);

                //
                return Ok(result.ToDynamicObject());
            }
            catch (Exception ex)
            {
                //
                var result = GetExceptionActionResult(ex);
                return result;
            }
        }

        /// <summary>
        /// Retrieve as XResourceDto ...
        /// </summary>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        [HttpGet("Resource")]
        public virtual async Task<ActionResult<XResourceDto>> GetResource(
            CancellationToken cancellationToken = default
        )
        {
            //
            try
            {
                //
                var result = await provider
                    .GetResource(cancellationToken);

                //
                return Ok(result.ToDynamicObject());
            }
            catch (Exception ex)
            {
                //
                var result = GetExceptionActionResult(ex);
                return result;
            }
        }

        /// <summary>
        /// Add or Update a Resource Model ...
        /// </summary>
        /// <param name="resource">a XResourceDto Model ...</param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        [HttpPost("")]
        public virtual async Task<ActionResult<XResourceDto>> AddOrUpdateResource(
            [FromBody] XResourceDto resource,
            CancellationToken cancellationToken = default
        )
        {
            //
            try
            {
                //
                var result = await provider
                    .AddOrUpdateResource(
                        resource: resource,
                        cancellationToken: cancellationToken
                    );

                //
                return Ok(result.ToDynamicObject());
            }
            catch (Exception ex)
            {
                //
                var result = GetExceptionActionResult(ex);
                return result;
            }
        }

        /// <summary>
        /// Add Or Update Locale ...
        /// </summary>
        /// <param name="locale"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        [HttpPost("Locales")]
        public virtual async Task<ActionResult<XResourceDto>> AddOrUpdateLocale(
            [FromBody] XLocaleResourceDto locale,
            CancellationToken cancellationToken = default
        )
        {
            //
            try
            {
                //
                var result = await provider
                    .AddOrUpdateLocale(
                        locale: locale,
                        cancellationToken: cancellationToken
                    );

                //
                return Ok(result);
            }
            catch (Exception ex)
            {
                //
                var result = GetExceptionActionResult(ex);
                return result;
            }
        }

        /// <summary>
        /// Remove Locale ...
        /// </summary>
        /// <param name="locale"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        [HttpPost("Locale/Remove")]
        public virtual async Task<ActionResult<XResourceDto>> RemoveLocale(
            [FromBody] XLocaleResourceDto locale,
            CancellationToken cancellationToken = default
        )
        {
            //
            try
            {
                //
                var result = await provider
                    .RemoveLocale(
                        locale: locale,
                        cancellationToken: cancellationToken
                    );

                //
                return Ok(result.ToDynamicObject());
            }
            catch (Exception ex)
            {
                //
                var result = GetExceptionActionResult(ex);
                return result;
            }
        }

        /// <summary>
        /// Remove Specified Resource Model ...
        /// </summary>
        /// <param name="resource">a XResourceDto Model ...</param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        [HttpPost("Resource/Remove")]
        public virtual async Task<ActionResult> RemoveResource(
            [FromBody] XResourceDto resource,
            CancellationToken cancellationToken = default
        )
        {
            //
            try
            {
                //
                await provider
                    .RemoveResource(
                        resource: resource,
                        cancellationToken: cancellationToken
                    );

                //
                return Ok();
            }
            catch (Exception ex)
            {
                //
                var result = GetExceptionActionResult(ex);
                return result;
            }
        }
        #endregion
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xStringService\Controllers\XStringProviderControllerBase.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore.Query;
using Microsoft.Extensions.Logging;
using xCommons.Configurations;
using xCommons.Extensions;
using xCommons.Providers;
using xExceptions.Constants;
using xIdentityService.Interfaces;
using xModels.Dtos;
using xPushService.Controllers;
using xStringService.Interfaces;
using xStringService.Models.Dtos;
using xStringService.Models.Entities;
using xStringService.Providers.Dtos;

namespace xStringService.Controllers
{
    public abstract class XStringProviderControllerBase : XBaseProvidedController<XString, XStringDto, int, XStringDtoHub>, IXStringProviderController
    {
        private readonly IXStringProvider provider;

        protected XStringProviderControllerBase(
            ILogger<XStringProviderControllerBase> logger,
            XAppConfiguration appConfiguration,
            IXIdentityProvider identityProvider,
            XValidationProvider validationProvider,
            IXStringProvider provider,
            Func<IQueryable<XString>, IOrderedQueryable<XString>> defaultOrderBuilder = null,
            Func<IQueryable<XString>, IIncludableQueryable<XString, object>> defaultIncludeBuilder = null
        ) : base(
            logger,
            appConfiguration,
            identityProvider,
            validationProvider,
            provider,
            defaultOrderBuilder,
            defaultIncludeBuilder
        )
        {
            this.provider = provider;
        }

        //
        #region Tools ...
        /// <summary>
        /// Retrieve a List of Exists Languages ...
        /// </summary>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        [HttpGet("Languages")]
        public virtual async Task<ActionResult<IEnumerable<string>>> GetLanguages(
            CancellationToken cancellationToken = default
        )
        {
            //
            try
            {
                //
                var result = await provider
                    .GetLanguages(cancellationToken);

                //
                return Ok(result.ToDynamicObject());
            }
            catch (Exception ex)
            {
                //
                var result = GetExceptionActionResult(ex);
                return result;
            }
        }

        /// <summary>
        /// Retrieve a List of Resource Titles ...
        /// </summary>
        /// <param name="language">if provided, returns all language Specified resource titles, if not, all Resource Titles</param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        [HttpGet("ResourceTitles")]
        public virtual async Task<ActionResult<IEnumerable<string>>> GetResourceTitles(
            [FromQuery] string language = null,
            CancellationToken cancellationToken = default
        )
        {
            //
            try
            {
                //
                var result = await provider
                    .GetResourceTitles(
                        language: language,
                        cancellationToken: cancellationToken
                    );

                //
                return Ok(result.ToDynamicObject());
            }
            catch (Exception ex)
            {
                //
                var result = GetExceptionActionResult(ex);
                return result;
            }
        }

        /// <summary>
        /// Retrieve all Exists Items which belongs to Specified Resource Title ...
        /// </summary>
        /// <param name="resource">Specified Resource Title</param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        [HttpGet("ResourceLocales")]
        public virtual async Task<ActionResult<IEnumerable<XStringDto>>> GetResourceLocales(
            [FromQuery] string resource,
            CancellationToken cancellationToken = default
        )
        {
            //
            try
            {
                //
                var result = await provider
                    .GetResourceLocales(
                        resource: resource,
                        cancellationToken: cancellationToken
                    );

                //
                return Ok(result.ToDynamicObject());
            }
            catch (Exception ex)
            {
                //
                var result = GetExceptionActionResult(ex);
                return result;
            }
        }

        /// <summary>
        /// Extract Translation of a Resource in Specified Language ...
        /// </summary>
        /// <param name="language">Specified Language ...</param>
        /// <param name="resource">Specified Resource Title ...</param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        [HttpGet("Translation")]
        public virtual async Task<ActionResult<string>> GetResourceTranslation(
            [FromQuery] string language,
            [FromQuery] string resource,
            CancellationToken cancellationToken = default
        )
        {
            //
            try
            {
                //
                var result = await provider
                    .GetResourceTranslation(
                        language: language,
                        resource: resource,
                        cancellationToken: cancellationToken
                    );

                //
                return Ok(result);
            }
            catch (Exception ex)
            {
                //
                var result = GetExceptionActionResult(ex);
                return result;
            }
        }

        /// <summary>
        /// Retrieve a Resource as Locale Model ...
        /// </summary>
        /// <param name="language">Specified Language ...</param>
        /// <param name="resource">Specified Resource Title ...</param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        [HttpGet("Locale")]
        public virtual async Task<ActionResult<XLocaleResourceDto>> GetLocale(
            [FromQuery] string language,
            [FromQuery] string resource,
            CancellationToken cancellationToken = default
        )
        {
            //
            try
            {
                //
                var result = await provider
                    .GetLocale(
                        language: language,
                        resource: resource,
                        cancellationToken: cancellationToken
                    );

                //
                return Ok(result.ToDynamicObject());
            }
            catch (Exception ex)
            {
                //
                var result = GetExceptionActionResult(ex);
                return result;
            }
        }

        /// <summary>
        /// Retrieve all Exists Resource Instances as Locale Models ...
        /// </summary>
        /// <param name="resource"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        [HttpGet("Locales")]
        public virtual async Task<ActionResult<IEnumerable<XLocaleResourceDto>>> GetLocales(
            [FromQuery] string resource,
            CancellationToken cancellationToken = default
        )
        {
            //
            try
            {
                //
                var result = await provider
                    .GetLocales(
                        resource: resource,
                        cancellationToken: cancellationToken
                    );

                //
                return Ok(result.ToDynamicObject());
            }
            catch (Exception ex)
            {
                //
                var result = GetExceptionActionResult(ex);
                return result;
            }
        }

        /// <summary>
        /// Retrieve all Locales of Specified Resource and Represent as XResourceDto ...
        /// </summary>
        /// <param name="resource"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        [HttpGet("GetResource")]
        public virtual async Task<ActionResult<XResourceDto>> GetResource(
            [FromQuery] string resource,
            CancellationToken cancellationToken = default
        )
        {
            //
            try
            {
                //
                var result = await provider
                    .GetResource(
                        resource: resource,
                        cancellationToken: cancellationToken
                    );

                //
                return Ok(result.ToDynamicObject());
            }
            catch (Exception ex)
            {
                //
                var result = GetExceptionActionResult(ex);
                return result;
            }
        }

        /// <summary>
        /// Add or Update a Resource Model ...
        /// </summary>
        /// <param name="resource">a XResourceDto Model ...</param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        [HttpPost("AddOrUpdateResource")]
        public virtual async Task<ActionResult<XResourceDto>> AddOrUpdateResource(
            [FromBody] XResourceDto resource,
            CancellationToken cancellationToken = default
        )
        {
            //
            try
            {
                //
                // Validate ...
                if (!ModelState.IsValid)
                {
                    XException.InvalidArgs.Throw();
                }
                await ValidationProvider
                    .GroupValidationBuilder()
                    .AddNotNull(resource)
                    .AddNotEmpty(resource.Resource)
                    .ValidateGroupAsync();

                //
                var userInfo = await GetUserInfo();
                var connectionId = GetConnectionId();

                //
                var result = await provider
                    .AddOrUpdateResource(
                        resource: resource,
                        userInfo: userInfo,
                        connectionId: connectionId,
                        cancellationToken: cancellationToken
                    );

                //
                return Ok(result.ToDynamicObject());
            }
            catch (Exception ex)
            {
                //
                var result = GetExceptionActionResult(ex);
                return result;
            }
        }

        /// <summary>
        /// Remove Specified Resource Model ...
        /// </summary>
        /// <param name="resource">a XResourceDto Model ...</param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        [HttpPost("RemoveResource")]
        public virtual async Task<ActionResult> RemoveResource(
            [FromBody] XResourceDto resource,
            CancellationToken cancellationToken = default
        )
        {
            //
            try
            {
                //
                // Validate ...
                if (!ModelState.IsValid)
                {
                    XException.InvalidArgs.Throw();
                }
                await ValidationProvider
                    .GroupValidationBuilder()
                    .AddNotNull(resource)
                    .AddNotEmpty(resource.Resource)
                    .ValidateGroupAsync();

                //
                var userInfo = await GetUserInfo();
                var connectionId = GetConnectionId();

                //
                await provider
                    .RemoveResource(
                        resource: resource,
                        userInfo: userInfo,
                        connectionId: connectionId,
                        cancellationToken: cancellationToken
                    );

                //
                return Ok();
            }
            catch (Exception ex)
            {
                //
                var result = GetExceptionActionResult(ex);
                return result;
            }
        }
        #endregion
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xStringService\Controllers\XStringRepositoryControllerBase.cs

using System;
using System.Linq;
using Microsoft.EntityFrameworkCore.Query;
using Microsoft.Extensions.Logging;
using xCommons.Configurations;
using xCommons.Providers;
using xDataService.Controllers;
using xDataService.Interfaces;
using xStringService.Interfaces.Entities;
using xStringService.Models.Entities;

namespace xStringService.Controllers
{
    public abstract class XStringRepositoryControllerBase : XBaseRepositoryController<XString, int>, IXBaseRepositoryController<XString, int>
    {
        protected XStringRepositoryControllerBase(
            ILogger<XStringRepositoryControllerBase> logger,
            XAppConfiguration appConfiguration,
            XValidationProvider validationProvider,
            IXStringRepository repository,
            Func<IQueryable<XString>, IOrderedQueryable<XString>> defaultOrderBuilder = null,
            Func<IQueryable<XString>, IIncludableQueryable<XString, object>> defaultIncludeBuilder = null
        ) : base(
            logger,
            appConfiguration,
            validationProvider,
            repository,
            defaultOrderBuilder,
            defaultIncludeBuilder
        )
        { }
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xStringService\Controllers\XStringRepositoryProviderControllerBase.cs

using System;
using System.Linq;
using Microsoft.EntityFrameworkCore.Query;
using Microsoft.Extensions.Logging;
using xCommons.Configurations;
using xCommons.Providers;
using xIdentityService.Interfaces;
using xPushService.Controllers;
using xPushService.Interfaces;
using xStringService.Interfaces.Entities;
using xStringService.Models.Entities;
using xStringService.Providers.Entities;

namespace xStringService.Controllers
{
    public abstract class XStringRepositoryProviderControllerBase : XBaseRepositoryProviderController<XString, int, XStringEntityHub>, IXBaseRepositoryProviderController<XString, int, XStringEntityHub>
    {
        protected XStringRepositoryProviderControllerBase(
            ILogger<XStringRepositoryProviderControllerBase> logger, 
            XAppConfiguration appConfiguration, 
            IXIdentityProvider identityProvider, 
            XValidationProvider validationProvider, 
            IXStringRepositoryProvider provider, 
            Func<IQueryable<XString>, IOrderedQueryable<XString>> defaultOrderBuilder = null, 
            Func<IQueryable<XString>, IIncludableQueryable<XString, object>> defaultIncludeBuilder = null
        ) : base(
            logger, 
            appConfiguration, 
            identityProvider, 
            validationProvider, 
            provider, 
            defaultOrderBuilder, 
            defaultIncludeBuilder
        )
        { }
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xStringService\Controllers\XStringServiceControllerBase.cs

using System;
using System.Linq;
using Microsoft.EntityFrameworkCore.Query;
using Microsoft.Extensions.Logging;
using xCommons.Configurations;
using xCommons.Providers;
using xDataService.Controllers;
using xDataService.Interfaces;
using xStringService.Interfaces.Dtos;
using xStringService.Models.Dtos;
using xStringService.Models.Entities;

namespace xStringService.Controllers
{
    public abstract class XStringServiceControllerBase : XBaseServiceController<XString, XStringDto, int>, IXBaseServiceController<XString, XStringDto, int>
    {
        protected XStringServiceControllerBase(
            ILogger<XStringServiceControllerBase> logger,
            XAppConfiguration appConfiguration,
            XValidationProvider validationProvider,
            IXStringRepositoryService repositoryService,
            Func<IQueryable<XString>, IOrderedQueryable<XString>> defaultOrderBuilder = null,
            Func<IQueryable<XString>, IIncludableQueryable<XString, object>> defaultIncludeBuilder = null
        ) : base(
            logger,
            appConfiguration,
            validationProvider,
            repositoryService,
            defaultOrderBuilder,
            defaultIncludeBuilder
        )
        { }
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xStringService\Controllers\XStringServiceProviderControllerBase.cs

using System;
using System.Linq;
using Microsoft.EntityFrameworkCore.Query;
using Microsoft.Extensions.Logging;
using xCommons.Configurations;
using xCommons.Providers;
using xIdentityService.Interfaces;
using xPushService.Controllers;
using xPushService.Interfaces;
using xStringService.Interfaces.Dtos;
using xStringService.Models.Dtos;
using xStringService.Models.Entities;
using xStringService.Providers.Dtos;

namespace xStringService.Controllers
{
    public abstract class XStringServiceProviderControllerBase : XBaseServiceProviderController<XString, XStringDto, int, XStringDtoHub>, IXBaseServiceProviderController<XString, XStringDto, int, XStringDtoHub>
    {
        protected XStringServiceProviderControllerBase(
            ILogger<XStringServiceProviderControllerBase> logger,
            XAppConfiguration appConfiguration,
            IXIdentityProvider identityProvider,
            XValidationProvider validationProvider,
            IXStringServiceProvider provider,
            Func<IQueryable<XString>, IOrderedQueryable<XString>> defaultOrderBuilder = null,
            Func<IQueryable<XString>, IIncludableQueryable<XString, object>> defaultIncludeBuilder = null
        ) : base(
            logger,
            appConfiguration,
            identityProvider,
            validationProvider,
            provider,
            defaultOrderBuilder,
            defaultIncludeBuilder
        )
        { }
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xStringService\DI\XDIHelperExtension.cs

using System;
using Microsoft.Extensions.DependencyInjection;
using xExceptions.Constants;
using xCommons.Extensions;
using xDataService.Constants;
using xDataService.Db;
using xDataService.DI;
using xDataService.Models;
using xStringService.Helpers;
using xCommons.Helpers;
using Microsoft.AspNetCore.Builder;
using xStringService.Interfaces.Dtos;
using xStringService.Providers.Dtos;
using xStringService.Interfaces.Entities;
using xStringService.Providers.Entities;
using xPushService.Helpers;
using xPushService.DI;
using xStringService.Interfaces;
using xStringService.Providers;
using xStringService.Constants;

namespace xStringService.DI
{
    public static class XDIHelperExtension
    {
        /// <summary>
        /// Register Service ...
        /// </summary>
        /// <param name="services"></param>
        /// <param name="repositoryType"></param>
        /// <param name="lifeTime"></param>
        public static void AddXStringService(
            this IServiceCollection services,
            XRepositoryType repositoryType,
            ServiceLifetime lifeTime = ServiceLifetime.Scoped
        )
        {
            AddStringService(
                contextType: null,
                services: services,
                lifeTime: lifeTime,
                repositoryType: repositoryType
            );
        }

        /// <summary>
        /// Register Service ...
        /// </summary>
        /// <typeparam name="TContext"></typeparam>
        /// <param name="services"></param>
        /// <param name="repositoryType"></param>
        /// <param name="lifeTime"></param>
        public static void AddXStringService<TContext>(
            this IServiceCollection services,
            XRepositoryType repositoryType,
            ServiceLifetime lifeTime = ServiceLifetime.Scoped
        )
        where TContext : XDbContext
        {
            AddStringService(
                services: services,
                lifeTime: lifeTime,
                contextType: typeof(TContext),
                repositoryType: repositoryType
            );
        }

        /// <summary>
        /// Use XStringService Middleware ... 
        /// </summary>
        /// <param name="app"></param>
        /// <param name="isDevelopmentEnvironment"></param>
        public static void UseXStringService(
            this IApplicationBuilder app,
            bool isDevelopmentEnvironment = false
        )
        {
            //
            #region  Using XString Hubs ...
            //
            var pushHelper = new XPushServiceHelper();

            //
            pushHelper.AddHub<XStringDtoHub>(XStringServiceConstants.XStringDtoHub);
            pushHelper.AddHub<XStringEntityHub>(XStringServiceConstants.XStringEntityHub);

            //
            app.UseXPushService(pushHelper);
            #endregion

            //
            // Using XString Repository Descriptor ...
            if (!descriptor.IsNull())
            {
                //
                app.UseXRepository(
                    descriptor: descriptor,
                    isDevelopmentEnvironment: isDevelopmentEnvironment
                );
            }
        }

        //
        #region Private ...
        private static XRepositoryDescriptor descriptor = null;

        /// <summary>
        /// a LogTag for Service ...
        /// </summary>
        private static string XLogTag = XStringServiceConstants.XStringServiceDILogTag;

        /// <summary>
        /// print a log in Console ...
        /// </summary>
        /// <param name="message"></param>
        private static void Log(string message)
        {
            Console.WriteLine($"{XLogTag} => {message}");
        }

        /// <summary>
        /// Register Service ...
        /// </summary>
        /// <param name="services"></param>
        /// <param name="repositoryType"></param>
        /// <param name="contextType"></param>
        /// <param name="lifeTime"></param>
        private static void AddStringService(
            IServiceCollection services,
            XRepositoryType repositoryType,
            Type contextType = null,
            ServiceLifetime lifeTime = ServiceLifetime.Scoped
        )
        {
            //
            var exception = XException.InvalidArgs.ToException(); ;

            //
            // Services ...
            var isServicesExists = !services.IsNull();
            if (!isServicesExists)
            {
                //
                Log("Service Registration failed, services not provided ...");
                throw exception;
            }

            //
            // Lifetime ...
            var isLifetimeExists = !lifeTime.IsNull();
            if (!isLifetimeExists)
            {
                //
                Log("Service Registration failed, lifetime not provided ...");
                throw exception;
            }

            //
            // Validate Repository Type ...
            var isRepositoryTypeValid =
                (repositoryType == XRepositoryType.EF &&
                !contextType.IsNull()) ||
                ((repositoryType == XRepositoryType.Mongo || 
                    repositoryType == XRepositoryType.InMemory) &&
                contextType.IsNull());
            if (!isRepositoryTypeValid)
            {
                //
                Log("Service Registration failed, Invalid Repository Type and Context Type ...");
                throw exception;                
            }

            //
            // Maske Instance of Repository Descriptor 
            // Based on Provided Type ...
            switch(repositoryType)
            {
                //
                case XRepositoryType.EF:
                //
                descriptor = typeof(XStringServiceHelper)
                    .InvokeGenericMethod<XRepositoryDescriptor>(
                        args: null,
                        runtimeType: contextType,
                        methodName: XStringServiceConstants.GetXStringEFRepositoryDescriptor
                );
                break;

                //
                case XRepositoryType.Mongo:
                descriptor = XStringServiceHelper.GetXStringMongoRepositoryDescriptor();
                break;

                //
                case XRepositoryType.InMemory:
                descriptor = XStringServiceHelper.GetXStringInMemoryRepositoryDescriptor();
                break;
            }

            //
            // Register XString Repository Descriptor ...
            services.AddXRepository(
                lifeTime: lifeTime,
                descriptor: descriptor
            );

            //
            // Register Dto Services ...
            services.Add(
                new ServiceDescriptor(typeof(IXStringServiceProvider), typeof(XStringServiceProvider), lifeTime)
            );
            services.Add(
                new ServiceDescriptor(typeof(IXStringRepositoryService), typeof(XStringRepositoryService), lifeTime)
            );
            services.Add(
                new ServiceDescriptor(typeof(IXStringRepositoryProvider), typeof(XStringRepositoryProvider), lifeTime)
            );

            //
            // Register XString Provider ...
            services.Add(
                new ServiceDescriptor(typeof(IXStringProvider), typeof(XStringProvider), lifeTime)
            );

            //
            Log("Service Regitration Succeed ...");
        }
        #endregion
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xStringService\Extensions\XModelExtensions.cs

using System.Collections.Generic;
using System.Linq;
using xCommons.Extensions;
using xModels.Dtos;
using xStringService.Models.Dtos;
using xStringService.Models.Entities;

namespace xStringService.Extensions
{
    public static class XModelExtensions
    {
        /// <summary>
        /// Converts an Entity to LocaleResource Dto ...
        /// </summary>
        /// <param name="source"></param>
        /// <returns></returns>
        public static XLocaleResourceDto ToXLocaleResourceDto(this XString source)
        {
            //
            var result = new XLocaleResourceDto
            {
                Language = source.IsNull() ? "" : source.Language,
                Value = source.IsNull() ? "" : source.TranslatedValue,
            };

            //
            return result;
        }

        /// <summary>
        /// Converts an Dto to LocaleResource Dto ...
        /// </summary>
        /// <param name="source"></param>
        /// <returns></returns>
        public static XLocaleResourceDto ToXLocaleResourceDto(this XStringDto source)
        {
            //
            var result = new XLocaleResourceDto
            {
                Language = source.IsNull() ? "" : source.Language,
                Value = source.IsNull() ? "" : source.TranslatedValue,
            };

            //
            return result;
        }

        /// <summary>
        /// Converts a Collection of Entities to Locale Resource Presentation ...
        /// </summary>
        /// <param name="source"></param>
        /// <returns></returns>
        public static IEnumerable<XLocaleResourceDto> ToXLocaleResourceDtos(this IEnumerable<XString> source)
        {
            //
            var result = source.Select(e => ToXLocaleResourceDto(e));
            return result;
        }

        /// <summary>
        /// Converts a Collection of Dtos to Locale Resource Presentation ...
        /// </summary>
        /// <param name="source"></param>
        /// <returns></returns>
        public static IEnumerable<XLocaleResourceDto> ToXLocaleResourceDtos(this IEnumerable<XStringDto> source)
        {
            //
            var result = source.Select(e => ToXLocaleResourceDto(e));
            return result;
        }
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xStringService\Helpers\XStringServiceHelper.cs

using GraphQL.Types;
using xDataHelper.Providers.GraphQL;
using xDataService.Db;
using xDataService.Models;
using xDataService.Providers;
using xStringService.Interfaces;
using xStringService.Interfaces.Entities;
using xStringService.Models.Entities;
using xStringService.Providers.Entities;
using xStringService.Providers.GraphQL;

namespace xStringService.Helpers
{
    public static class XStringServiceHelper
    {
        //
        #region EF Repository Descriptor Provider(s) ...
        public static XEFRepositoryDescriptor<
            XString,
            int,
            IXStringKeyGenerator,
            XStringKeyGenerator,
            IXStringRepositoryEvents,
            XStringRepositoryEvents,
            XStringGraphType,
            IntGraphType,
            XStringGraphQuery,
            IXStringGraphQLTypeHelper,
            XStringGraphQLTypeHelper,
            XStringGraphSchema,
            IXStringRepository,
            XStringEFRepository<TContext>,
            TContext
        > GetXStringEFRepositoryDescriptor<TContext>()
        where TContext : XDbContext
        {
            //
            var result = new XEFRepositoryDescriptor<
                XString,
                int,
                IXStringKeyGenerator,
                XStringKeyGenerator,
                IXStringRepositoryEvents,
                XStringRepositoryEvents,
                XStringGraphType,
                IntGraphType,
                XStringGraphQuery,
                IXStringGraphQLTypeHelper,
                XStringGraphQLTypeHelper,
                XStringGraphSchema,
                IXStringRepository,
                XStringEFRepository<TContext>,
                TContext
            >();

            //
            return result;
        }

        public static XEFRepositoryDescriptor<
            XString,
            int,
            IXStringKeyGenerator,
            XStringKeyGenerator,
            IXStringRepositoryEvents,
            XStringRepositoryEvents,
            XStringGraphType,
            IntGraphType,
            XStringGraphQuery,
            IXStringGraphQLTypeHelper,
            XStringGraphQLTypeHelper,
            XStringGraphSchema,
            IXStringRepository,
            XStringEFRepository<TContext>,
            TContext,
            IXStringSeeder,
            TSeederImplementation
        > GetXStringEFRepositoryDescriptor<TContext, TSeederImplementation>()
        where TContext : XDbContext
        where TSeederImplementation : XBaseDbSeeder<XString, int>
        {
            //
            var result = new XEFRepositoryDescriptor<
                XString,
                int,
                IXStringKeyGenerator,
                XStringKeyGenerator,
                IXStringRepositoryEvents,
                XStringRepositoryEvents,
                XStringGraphType,
                IntGraphType,
                XStringGraphQuery,
                IXStringGraphQLTypeHelper,
                XStringGraphQLTypeHelper,
                XStringGraphSchema,
                IXStringRepository,
                XStringEFRepository<TContext>,
                TContext,
                IXStringSeeder,
                TSeederImplementation
            >();

            //
            return result;
        }
        #endregion

        //
        #region Mongo Repository Descriptor Provider(s) ...
        public static XMongoRepositoryDescriptor<
            XString,
            int,
            IXStringKeyGenerator,
            XStringKeyGenerator,
            IXStringRepositoryEvents,
            XStringRepositoryEvents,
            XStringGraphType,
            IntGraphType,
            XStringGraphQuery,
            IXStringGraphQLTypeHelper,
            XStringGraphQLTypeHelper,
            XStringGraphSchema,
            IXStringRepository,
            XStringMongoRepository
        > GetXStringMongoRepositoryDescriptor()
        {
            //
            var result = new XMongoRepositoryDescriptor<
                XString,
                int,
                IXStringKeyGenerator,
                XStringKeyGenerator,
                IXStringRepositoryEvents,
                XStringRepositoryEvents,
                XStringGraphType,
                IntGraphType,
                XStringGraphQuery,
                IXStringGraphQLTypeHelper,
                XStringGraphQLTypeHelper,
                XStringGraphSchema,
                IXStringRepository,
                XStringMongoRepository
            >();

            //
            return result;
        }

        public static XMongoRepositoryDescriptor<
            XString,
            int,
            IXStringKeyGenerator,
            XStringKeyGenerator,
            IXStringRepositoryEvents,
            XStringRepositoryEvents,
            XStringGraphType,
            IntGraphType,
            XStringGraphQuery,
            IXStringGraphQLTypeHelper,
            XStringGraphQLTypeHelper,
            XStringGraphSchema,
            IXStringRepository,
            XStringMongoRepository,
            IXStringSeeder,
            TSeederImplementation
        > GetXStringMongoRepositoryDescriptor<TSeederImplementation>()
        where TSeederImplementation : XBaseDbSeeder<XString, int>
        {
            //
            var result = new XMongoRepositoryDescriptor<
                XString,
                int,
                IXStringKeyGenerator,
                XStringKeyGenerator,
                IXStringRepositoryEvents,
                XStringRepositoryEvents,
                XStringGraphType,
                IntGraphType,
                XStringGraphQuery,
                IXStringGraphQLTypeHelper,
                XStringGraphQLTypeHelper,
                XStringGraphSchema,
                IXStringRepository,
                XStringMongoRepository,
                IXStringSeeder,
                TSeederImplementation
            >();

            //
            return result;
        }
        #endregion

        //
        #region InMemory Repository Descriptor Provider(s) ...
        public static XInMemoryRepositoryDescriptor<
            XString,
            int,
            IXStringKeyGenerator,
            XStringKeyGenerator,
            IXStringRepositoryEvents,
            XStringRepositoryEvents,
            XStringGraphType,
            IntGraphType,
            XStringGraphQuery,
            IXStringGraphQLTypeHelper,
            XStringGraphQLTypeHelper,
            XStringGraphSchema,
            IXStringRepository,
            XStringInMemoryRepository
        > GetXStringInMemoryRepositoryDescriptor()
        {
            //
            var result = new XInMemoryRepositoryDescriptor<
                XString,
                int,
                IXStringKeyGenerator,
                XStringKeyGenerator,
                IXStringRepositoryEvents,
                XStringRepositoryEvents,
                XStringGraphType,
                IntGraphType,
                XStringGraphQuery,
                IXStringGraphQLTypeHelper,
                XStringGraphQLTypeHelper,
                XStringGraphSchema,
                IXStringRepository,
                XStringInMemoryRepository
            >();

            //
            return result;
        }

        public static XInMemoryRepositoryDescriptor<
            XString,
            int,
            IXStringKeyGenerator,
            XStringKeyGenerator,
            IXStringRepositoryEvents,
            XStringRepositoryEvents,
            XStringGraphType,
            IntGraphType,
            XStringGraphQuery,
            IXStringGraphQLTypeHelper,
            XStringGraphQLTypeHelper,
            XStringGraphSchema,
            IXStringRepository,
            XStringInMemoryRepository,
            IXStringSeeder,
            TSeederImplementation
        > GetXStringInMemoryRepositoryDescriptor<TSeederImplementation>()
        where TSeederImplementation : XBaseDbSeeder<XString, int>
        {
            //
            var result = new XInMemoryRepositoryDescriptor<
                XString,
                int,
                IXStringKeyGenerator,
                XStringKeyGenerator,
                IXStringRepositoryEvents,
                XStringRepositoryEvents,
                XStringGraphType,
                IntGraphType,
                XStringGraphQuery,
                IXStringGraphQLTypeHelper,
                XStringGraphQLTypeHelper,
                XStringGraphSchema,
                IXStringRepository,
                XStringInMemoryRepository,
                IXStringSeeder,
                TSeederImplementation
            >();

            //
            return result;
        }
        #endregion
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xStringService\Interfaces\Dtos\IXStringDtoHub.cs

using xPushService.Interfaces;
using xStringService.Models.Dtos;
using xStringService.Models.Entities;

namespace xStringService.Interfaces.Dtos
{
    public interface IXStringDtoHub : IXBaseDtoHub<XString, XStringDto, int>
    { }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xStringService\Interfaces\Dtos\IXStringRepositoryService.cs

using System;
using System.Collections.Generic;
using System.Linq.Expressions;
using System.Threading;
using System.Threading.Tasks;
using xDataService.Interfaces;
using xModels.Dtos;
using xStringService.Models.Dtos;
using xStringService.Models.Entities;

namespace xStringService.Interfaces.Dtos
{
    public interface IXStringRepositoryService : IXBaseRepositoryService<XString, XStringDto, int>
    { }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xStringService\Interfaces\Dtos\IXStringServiceProvider.cs

using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;
using xCommons.Configurations;
using xModels.Dtos;
using xPushService.Interfaces;
using xStringService.Models.Dtos;
using xStringService.Models.Entities;
using xStringService.Providers.Dtos;

namespace xStringService.Interfaces.Dtos
{
    public interface IXStringServiceProvider : IXBaseDtoProvider<XString, XStringDto, int, XStringDtoHub>
    {
        /// <summary>
        /// Application Configuration ...
        /// </summary>
        XAppConfiguration AppConfiguration { get; }

        //
        #region Retrievers ...
        /// <summary>
        /// Retrieve all Exists Languages ...
        /// </summary>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        Task<IEnumerable<string>> GetLanguages(
            CancellationToken cancellationToken = default
        );

        /// <summary>
        /// Check Specified Resource Exists or not ...
        /// </summary>
        /// <param name="resource"></param>
        /// <param name="language"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        Task<bool> IsResourceExists(
            string resource,
            string language = null,
            CancellationToken cancellationToken = default
        );

        /// <summary>
        /// Retrieve Specified Resource ...
        /// </summary>
        /// <param name="resource"></param>
        /// <param name="language"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        Task<XStringDto> Get(
            string resource,
            string language = null,
            CancellationToken cancellationToken = default
        );

        /// <summary>
        /// Retrieve Specified Translation of Specified Resource ...
        /// </summary>
        /// <param name="resource"></param>
        /// <param name="language"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        Task<string> GetResourceValue(
            string resource,
            string language = null,
            CancellationToken cancellationToken = default
        );

        /// <summary>
        /// Retrieve an Specified Resource Items ...
        /// </summary>
        /// <param name="resource"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        Task<IEnumerable<XStringDto>> GetResources(
            string resource,
            CancellationToken cancellationToken = default
        );

        /// <summary>
        /// Retrieve Specified Resource Items as XResourceDto Presentation ...
        /// </summary>
        /// <param name="resource"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        Task<XResourceDto> GetResource(
            string resource,
            CancellationToken cancellationToken = default
        );
        #endregion

        //
        #region Query ...
        /// <summary>
        /// Query Resource IDs ...
        /// </summary>
        /// <param name="query"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        Task<XQueryResult<string>> QueryResourceIds(
            XQuery query,
            CancellationToken cancellationToken = default
        );

        /// <summary>
        /// Query Specified Language Resources ...
        /// </summary>
        /// <param name="query"></param>
        /// <param name="language"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        Task<XQueryResult<XStringDto>> QueryLanguageResources(
            XQuery query,
            string language = null,
            CancellationToken cancellationToken = default            
        );

        /// <summary>
        /// Query Locale Resources ...
        /// </summary>
        /// <param name="query"></param>
        /// <param name="language"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        Task<XQueryResult<XLocaleResourceDto>> QueryLocaleResources(
            XQuery query,
            string language = null,
            CancellationToken cancellationToken = default            
        );
        #endregion

        //
        #region Add/Update Actions ...
        /// <summary>
        /// Add Specified Resource ...
        /// </summary>
        /// <param name="resource"></param>
        /// <param name="value"></param>
        /// <param name="language"></param>
        /// <param name="connectionId"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        Task<bool> Add(
            string resource,
            string value,
            string language = null,
            string connectionId = null,
            CancellationToken cancellationToken = default            
        );

        /// <summary>
        /// Update Resource ...
        /// </summary>
        /// <param name="resource"></param>
        /// <param name="value"></param>
        /// <param name="language"></param>
        /// <param name="connectionId"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        Task<bool> Update(
            string resource,
            string value,
            string language = null,
            string connectionId = null,
            CancellationToken cancellationToken = default            
        );

        /// <summary>
        /// Add Or Update Resource ...
        /// </summary>
        /// <param name="resource"></param>
        /// <param name="value"></param>
        /// <param name="language"></param>
        /// <param name="connectionId"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        Task<bool> AddOrUpdate(
            string resource,
            string value,
            string language = null,
            string connectionId = null,
            CancellationToken cancellationToken = default            
        );

        /// <summary>
        /// Add Specified Locale Resource ...
        /// </summary>
        /// <param name="item"></param>
        /// <param name="resource"></param>
        /// <param name="connectionId"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        Task<XStringDto> AddByLocaleResource(
            XLocaleResourceDto item,
            string resource,
            string connectionId = null,
            CancellationToken cancellationToken = default            
        );

        /// <summary>
        /// Update Specified Locale Resource ...
        /// </summary>
        /// <param name="item"></param>
        /// <param name="resource"></param>
        /// <param name="connectionId"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        Task<XStringDto> UpdateByLocaleResource(
            XLocaleResourceDto item,
            string resource,
            string connectionId = null,
            CancellationToken cancellationToken = default            
        );

        /// <summary>
        /// Add Or Update Resource By Locale ...
        /// </summary>
        /// <param name="item"></param>
        /// <param name="resource"></param>
        /// <param name="connectionId"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        Task<XStringDto> AddOrUpdateByLocaleResource(
            XLocaleResourceDto item,
            string resource,
            string connectionId = null,
            CancellationToken cancellationToken = default            
        );

        /// <summary>
        /// Add Or Update all XResourceDto(s) Locales ...
        /// </summary>
        /// <param name="item"></param>
        /// <param name="connectionId"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        Task<IEnumerable<XStringDto>> AddByResource(
            XResourceDto item,
            string connectionId = null,
            CancellationToken cancellationToken = default            
        );
        #endregion

        //
        #region Remove Actions ...
        /// <summary>
        /// Remove all Specified Language's Resources ...
        /// </summary>
        /// <param name="language"></param>
        /// <param name="connectionId"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        Task RemoveLanguageResources(
            string language,
            string connectionId = null,
            CancellationToken cancellationToken = default            
        );

        /// <summary>
        /// Remove all Specified Resource Ids instances ... 
        /// </summary>
        /// <param name="resource"></param>
        /// <param name="connectionId"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        Task<IEnumerable<XStringDto>> RemoveResource(
            string resource,
            string connectionId = null,
            CancellationToken cancellationToken = default            
        );

        /// <summary>
        /// Remove Specified Resource ...
        /// </summary>
        /// <param name="resource"></param>
        /// <param name="language"></param>
        /// <param name="connectionId"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        Task<bool> Remove(
            string resource,
            string language = null,
            string connectionId = null,
            CancellationToken cancellationToken = default            
        );

        /// <summary>
        /// Remove all Resource of Specified XResourceDto ...
        /// </summary>
        /// <param name="item"></param>
        /// <param name="connectionId"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        Task RemoveByResource(
            XResourceDto item,
            string connectionId = null,
            CancellationToken cancellationToken = default            
        );
        #endregion
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xStringService\Interfaces\Entities\IXStringEntityHub.cs

using xPushService.Interfaces;
using xStringService.Models.Entities;

namespace xStringService.Interfaces.Entities
{
    public interface IXStringEntityHub : IXBaseEntityHub<XString, int>
    { }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xStringService\Interfaces\Entities\IXStringGraphQLTypeHelper.cs

using xDataService.Interfaces;
using xStringService.Models.Entities;

namespace xStringService.Interfaces.Entities
{
    public interface IXStringGraphQLTypeHelper : IXBaseGraphQLTypeHelper<XString, int>
    { }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xStringService\Interfaces\Entities\IXStringKeyGenerator.cs

using xDataService.Interfaces;
using xStringService.Models.Entities;

namespace xStringService.Interfaces.Entities
{
    public interface IXStringKeyGenerator : IXKeyGenerator<XString, int>
    { }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xStringService\Interfaces\Entities\IXStringRepository.cs

using xDataService.Interfaces;
using xStringService.Models.Entities;

namespace xStringService.Interfaces.Entities
{
    public interface IXStringRepository : IXBaseRepository<XString, int>
    { }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xStringService\Interfaces\Entities\IXStringRepositoryEvents.cs

using xDataService.Interfaces;
using xStringService.Models.Entities;

namespace xStringService.Interfaces.Entities
{
    public interface IXStringRepositoryEvents : IXBaseRepositoryEvents<XString>
    { }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xStringService\Interfaces\Entities\IXStringRepositoryProvider.cs

using xPushService.Interfaces;
using xStringService.Models.Entities;
using xStringService.Providers.Entities;

namespace xStringService.Interfaces.Entities
{
    public interface IXStringRepositoryProvider : IXBaseEntityProvider<XString, int, XStringEntityHub>
    { }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xStringService\Interfaces\Entities\IXStringSeeder.cs

using xDataService.Interfaces;
using xStringService.Models.Entities;

namespace xStringService.Interfaces.Entities
{
    public interface IXStringSeeder : IXBaseDbSeeder<XString, int>
    {}
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xStringService\Interfaces\IXBaseItemResourceProviderController.cs

using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
using xModels.Dtos;
using xStringService.Models.Dtos;

namespace xStringService.Interfaces
{
    public interface IXBaseItemResourceProviderController
    {
        /// <summary>
        /// Retrieve a List of Exists Languages ...
        /// </summary>
        /// <param name="identifier">if null or empty, check all languages in Item Side</param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        [HttpGet("Languages")]
        Task<ActionResult<IEnumerable<string>>> GetLanguages(
            [FromQuery] object identifier,
            CancellationToken cancellationToken = default
        );

        /// <summary>
        /// Retrieve all Exists Items ...
        /// </summary>
        /// <param name="resource">Specified Resource Title</param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        [HttpGet("ResourceLocales")]
        Task<ActionResult<IEnumerable<XStringDto>>> GetResourceLocales(
            [FromQuery] object identifier,
            CancellationToken cancellationToken = default
        );

        /// <summary>
        /// Get all Exists Items for Specified identitifer ...
        /// </summary>
        /// <param name="identifier"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        [HttpGet("Locales/{identifier}")]
        Task<ActionResult<IEnumerable<XLocaleResourceDto>>> GetLocales(
            [FromRoute] object identifier,
            CancellationToken cancellationToken = default
        );

        /// <summary>
        /// Remove Specified Language Locale of Specified Identifier ...
        /// </summary>
        /// <param name="identifier"></param>
        /// <param name="language">if null or empty Remove all Locales</param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        [HttpDelete("Locales/{identifier}")]
        Task<ActionResult<XResourceDto>> RemoveLocale(
            [FromRoute] object identifier,
            [FromQuery] string language,
            CancellationToken cancellationToken = default
        );

        /// <summary>
        /// Check Specified ocale Exists for Specified Identifier ...
        /// </summary>
        /// <param name="identifier"></param>
        /// <param name="language"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        [HttpGet("Locales/{identifier}/{language}/Has")]
        Task<ActionResult<bool>> HasLocale(
            [FromRoute] object identifier,
            [FromRoute] string language,
            CancellationToken cancellationToken = default
        );

        /// <summary>
        /// Get all Exists Locales Representaion based on Specified Identitifer
        /// as XResourceDto ...
        /// </summary>
        /// <param name="identifier"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        [HttpGet("Resource/{identifier}")]
        Task<ActionResult<XResourceDto>> GetResource(
            [FromRoute] object identifier,
            CancellationToken cancellationToken = default
        );

        /// <summary>
        /// Add Or Update Locale for Specified Identitifer ...
        /// </summary>
        /// <param name="identifier"></param>
        /// <param name="locale"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        [HttpPost("Locales/{identifier}")]
        Task<ActionResult<XResourceDto>> AddOrUpdateLocale(
            [FromRoute] object identifier,
            [FromBody] XLocaleResourceDto locale,
            CancellationToken cancellationToken = default
        );

        /// <summary>
        /// Update a Resource State ...
        /// </summary>
        /// <param name="identifier"></param>
        /// <param name="resource"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        [HttpPost("Resource/{identifier}")]
        Task<ActionResult<XResourceDto>> AddOrUpdateResource(
            [FromRoute] object identifier,
            [FromBody] XResourceDto resource,
            CancellationToken cancellationToken = default
        );
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xStringService\Interfaces\IXBaseResourceProviderController.cs

using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
using xModels.Dtos;
using xStringService.Models.Dtos;

namespace xStringService.Interfaces
{
    public interface IXBaseResourceProviderController
    {
        /// <summary>
        /// Retrieve a List of Exists Languages ...
        /// </summary>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        [HttpGet("Languages")]
        Task<ActionResult<IEnumerable<string>>> GetLanguages(
            CancellationToken cancellationToken = default
        );

        /// <summary>
        /// Retrieve all Exists Items ...
        /// </summary>
        /// <param name="resource">Specified Resource Title</param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        [HttpGet("LocalesResource")]
        Task<ActionResult<IEnumerable<XStringDto>>> GetResourceLocales(
            CancellationToken cancellationToken = default
        );

        /// <summary>
        /// Extract Translation of in Specified Language ...
        /// </summary>
        /// <param name="language">Specified Language ...</param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        [HttpGet("{language}/Translation")]
        Task<ActionResult<string>> GetResourceTranslation(
            [FromRoute] string language,
            CancellationToken cancellationToken = default
        );

        /// <summary>
        /// Check Has Specified Translation or not ...
        /// </summary>
        /// <param name="language">Specified Language ...</param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        [HttpGet("{language}/Has")]
        Task<ActionResult<bool>> HasLocale(
            [FromRoute] string language,
            CancellationToken cancellationToken = default
        );

        /// <summary>
        /// Retrieve as Locale Model ...
        /// </summary>
        /// <param name="language">Specified Language ...</param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        [HttpGet("{language}/Locale")]
        Task<ActionResult<XLocaleResourceDto>> GetLocale(
            [FromRoute] string language,
            CancellationToken cancellationToken = default
        );

        /// <summary>
        /// Retrieve all Exists Locale Models ...
        /// </summary>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        [HttpGet("Locales")]
        Task<ActionResult<IEnumerable<XLocaleResourceDto>>> GetLocales(
            CancellationToken cancellationToken = default
        );

        /// <summary>
        /// Retrieve as XResourceDto ...
        /// </summary>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        [HttpGet("Resource")]
        Task<ActionResult<XResourceDto>> GetResource(
            CancellationToken cancellationToken = default
        );

        /// <summary>
        /// Add or Update a Resource Model ...
        /// </summary>
        /// <param name="resource">a XResourceDto Model ...</param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        [HttpPost("")]
        Task<ActionResult<XResourceDto>> AddOrUpdateResource(
            [FromBody] XResourceDto resource,
            CancellationToken cancellationToken = default
        );

        /// <summary>
        /// Add Or Update Locale ...
        /// </summary>
        /// <param name="locale"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        [HttpPost("Locales")]
        Task<ActionResult<XResourceDto>> AddOrUpdateLocale(
            [FromBody] XLocaleResourceDto locale,
            CancellationToken cancellationToken = default
        );

        /// <summary>
        /// Remove Locale ...
        /// </summary>
        /// <param name="locale"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        [HttpPost("Locale/Remove")]
        Task<ActionResult<XResourceDto>> RemoveLocale(
            [FromBody] XLocaleResourceDto locale,
            CancellationToken cancellationToken = default
        );

        /// <summary>
        /// Remove Specified Resource Model ...
        /// </summary>
        /// <param name="resource">a XResourceDto Model ...</param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        [HttpPost("Resource/Remove")]
        Task<ActionResult> RemoveResource(
            [FromBody] XResourceDto resource,
            CancellationToken cancellationToken = default
        );
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xStringService\Interfaces\IXItemResourceProvider.cs

using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;
using xModels.Dtos;
using xStringService.Models.Dtos;

namespace xStringService.Interfaces
{
    public interface IXItemResourceProvider
    {
        //
        #region Group Actions ...
        /// <summary>
        /// Retrieve a List of Exists Languages for Current Item ...
        /// </summary>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        Task<IEnumerable<string>> GetLanguages(
            CancellationToken cancellationToken = default
        );

        /// <summary>
        /// Retrieve all Exists Items of type ...
        /// </summary>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        Task<IEnumerable<XStringDto>> GetResourceLocales(
            CancellationToken cancellationToken = default
        );

        /// <summary>
        /// Remove all Exists Locales which Related to this Provider ...
        /// </summary>
        /// <param name="connectionId"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        Task RemoveResourceLocales(
            string connectionId = null,
            CancellationToken cancellationToken = default
        );
        #endregion

        //
        #region Item Actions ...
        /// <summary>
        /// Get all Exists Items for Specified identitifer ...
        /// </summary>
        /// <param name="identifier"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        Task<IEnumerable<XStringDto>> GetResourceLocales(
            object identifier,
            CancellationToken cancellationToken = default
        );

        /// <summary>
        /// Get all Exists Items for Specified identitifer ...
        /// </summary>
        /// <param name="identifier"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        Task<IEnumerable<XLocaleResourceDto>> GetLocales(
            object identifier,
            CancellationToken cancellationToken = default
        );

        /// <summary>
        /// Get all Exists Locales Representaion based on Specified Identitifer
        /// as XResourceDto ...
        /// </summary>
        /// <param name="identifier"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        Task<XResourceDto> GetResource(
            object identifier,
            CancellationToken cancellationToken = default
        );

        /// <summary>
        /// Add Or Update Locale for Specified Identitifer ...
        /// </summary>
        /// <param name="identifier"></param>
        /// <param name="locale"></param>
        /// <param name="connectionId"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        Task<XResourceDto> AddOrUpdateLocale(
            object identifier,
            XLocaleResourceDto locale,
            string connectionId = null,
            CancellationToken cancellationToken = default
        );

        /// <summary>
        /// Update a Resource State ...
        /// </summary>
        /// <param name="identifier"></param>
        /// <param name="resource"></param>
        /// <param name="connectionId"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        Task<XResourceDto> AddOrUpdateResource(
            object identifier,
            XResourceDto resource,
            string connectionId = null,
            CancellationToken cancellationToken = default
        );

        /// <summary>
        /// Remove Specified Language Locale of Specified Identifier ...
        /// </summary>
        /// <param name="identifier"></param>
        /// <param name="language"></param>
        /// <param name="connectionId"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        Task<XResourceDto> RemoveLocale(
            object identifier,
            string language,
            string connectionId = null,
            CancellationToken cancellationToken = default
        );

        /// <summary>
        /// Remove all Exists Locales for Specified Identifier ...
        /// </summary>
        /// <param name="identifier"></param>
        /// <param name="connectionId"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        Task RemoveLocales(
            object identifier,
            string connectionId = null,
            CancellationToken cancellationToken = default
        );

        /// <summary>
        /// Check Specified ocale Exists for Specified Identifier ...
        /// </summary>
        /// <param name="identifier"></param>
        /// <param name="language"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        Task<bool> HasLocale(
            object identifier,
            string language,
            CancellationToken cancellationToken = default
        );

        /// <summary>
        /// Get all Exists Languages for Specified Identifier ...
        /// </summary>
        /// <param name="identifier"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        Task<IEnumerable<string>> GetLanguages(
            object identifier,
            CancellationToken cancellationToken = default
        );
        #endregion

        //
        #region Resource Title Action ...
        /// <summary>
        /// Retrieve Resource Title ...
        /// </summary>
        /// <param name="identifier"></param>
        /// <returns></returns>
        string GetResourceTitle(object identifier = null);
        #endregion
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xStringService\Interfaces\IXResourceProvider.cs

using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;
using xModels.Dtos;
using xStringService.Models.Dtos;

namespace xStringService.Interfaces
{
    public interface IXResourceProvider
    {
        /// <summary>
        /// Retrieve a List of Exists Languages ...
        /// </summary>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        Task<IEnumerable<string>> GetLanguages(
            CancellationToken cancellationToken = default
        );

        /// <summary>
        /// Retrieve all Exists Items ...
        /// </summary>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        Task<IEnumerable<XStringDto>> GetResourceLocales(
            CancellationToken cancellationToken = default
        );

        /// <summary>
        /// Extract Translation of in Specified Language ...
        /// </summary>
        /// <param name="language">Specified Language ...</param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        Task<string> GetResourceTranslation(
            string language,
            CancellationToken cancellationToken = default
        );

        /// <summary>
        /// Check Has Specified Translation or not ...
        /// </summary>
        /// <param name="language">Specified Language ...</param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        Task<bool> HasLocale(
            string language,
            CancellationToken cancellationToken = default
        );

        /// <summary>
        /// Retrieve as Locale Model ...
        /// </summary>
        /// <param name="language">Specified Language ...</param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        Task<XLocaleResourceDto> GetLocale(
            string language,
            CancellationToken cancellationToken = default
        );

        /// <summary>
        /// Retrieve all Exists Locale Models ...
        /// </summary>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        Task<IEnumerable<XLocaleResourceDto>> GetLocales(
            CancellationToken cancellationToken = default
        );

        /// <summary>
        /// Retrieve as XResourceDto ...
        /// </summary>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        Task<XResourceDto> GetResource(
            CancellationToken cancellationToken = default
        );

        /// <summary>
        /// Add or Update a Resource Model ...
        /// </summary>
        /// <param name="resource">a XResourceDto Model ...</param>
        /// <param name="connectionId"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        Task<XResourceDto> AddOrUpdateResource(
            XResourceDto resource,
            string connectionId = null,
            CancellationToken cancellationToken = default
        );

        /// <summary>
        /// Add Or Update Locale ...
        /// </summary>
        /// <param name="locale"></param>
        /// <param name="connectionId"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        Task<XResourceDto> AddOrUpdateLocale(
            XLocaleResourceDto locale,
            string connectionId = null,
            CancellationToken cancellationToken = default
        );

        /// <summary>
        /// Remove Locale ...
        /// </summary>
        /// <param name="locale"></param>
        /// <param name="connectionId"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        Task<XResourceDto> RemoveLocale(
            XLocaleResourceDto locale,
            string connectionId = null,
            CancellationToken cancellationToken = default
        );

        /// <summary>
        /// Remove Specified Resource Model ...
        /// </summary>
        /// <param name="resource">a XResourceDto Model ...</param>
        /// <param name="connectionId"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        Task RemoveResource(
            XResourceDto resource,
            string connectionId = null,
            CancellationToken cancellationToken = default
        );
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xStringService\Interfaces\IXStringProvider.cs

using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;
using xIdentityModels.Models;
using xModels.Dtos;
using xPushService.Interfaces;
using xStringService.Models.Dtos;
using xStringService.Models.Entities;
using xStringService.Providers.Dtos;

namespace xStringService.Interfaces
{
    public interface IXStringProvider : IXBaseProvided<XString, XStringDto, int, XStringDtoHub>
    {
        //
        #region Tools ...
        /// <summary>
        /// Retrieve a List of Exists Languages ...
        /// </summary>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        Task<IEnumerable<string>> GetLanguages(
            CancellationToken cancellationToken = default
        );

        /// <summary>
        /// Retrieve a List of Resource Titles ...
        /// </summary>
        /// <param name="language">if provided, returns all language Specified resource titles, if not, all Resource Titles</param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        Task<IEnumerable<string>> GetResourceTitles(
            string language = null,
            CancellationToken cancellationToken = default
        );

        /// <summary>
        /// Retrieve all Exists Items which belongs to Specified Resource Title ...
        /// </summary>
        /// <param name="resource">Specified Resource Title</param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        Task<IEnumerable<XStringDto>> GetResourceLocales(
            string resource,
            CancellationToken cancellationToken = default
        );

        /// <summary>
        /// Extract Translation of a Resource in Specified Language ...
        /// </summary>
        /// <param name="language">Specified Language ...</param>
        /// <param name="resource">Specified Resource Title ...</param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        Task<string> GetResourceTranslation(
            string language,
            string resource,
            CancellationToken cancellationToken = default
        );

        /// <summary>
        /// Retrieve a Resource as Locale Model ...
        /// </summary>
        /// <param name="language">Specified Language ...</param>
        /// <param name="resource">Specified Resource Title ...</param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        Task<XLocaleResourceDto> GetLocale(
            string language,
            string resource,
            CancellationToken cancellationToken = default
        );

        /// <summary>
        /// Retrieve all Exists Resource Instances as Locale Models ...
        /// </summary>
        /// <param name="resource"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        Task<IEnumerable<XLocaleResourceDto>> GetLocales(
            string resource,
            CancellationToken cancellationToken = default
        );

        /// <summary>
        /// Retrieve all Locales of Specified Resource and Represent as XResourceDto ...
        /// </summary>
        /// <param name="resource"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        Task<XResourceDto> GetResource(
            string resource,
            CancellationToken cancellationToken = default
        );

        /// <summary>
        /// Add or Update a Resource Model ...
        /// </summary>
        /// <param name="resource">a XResourceDto Model ...</param>
        /// <param name="userInfo">Actor User for Permissions ...</param>
        /// <param name="connectionId"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        Task<XResourceDto> AddOrUpdateResource(
            XResourceDto resource,
            XUserClaimsInfoDto userInfo = null,
            string connectionId = null,
            CancellationToken cancellationToken = default
        );

        /// <summary>
        /// Remove Specified Resource Model ...
        /// </summary>
        /// <param name="resource">a XResourceDto Model ...</param>
        /// <param name="userInfo">Actor User for Permissions ...</param>
        /// <param name="connectionId"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        Task RemoveResource(
            XResourceDto resource,
            XUserClaimsInfoDto userInfo = null,
            string connectionId = null,
            CancellationToken cancellationToken = default
        ); 
        #endregion
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xStringService\Interfaces\IXStringProviderController.cs

using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
using xModels.Dtos;
using xPushService.Interfaces;
using xStringService.Models.Dtos;
using xStringService.Models.Entities;
using xStringService.Providers.Dtos;

namespace xStringService.Interfaces
{
    public interface IXStringProviderController : IXBaseProvidedController<XString, XStringDto, int, XStringDtoHub>
    {
        //
        #region Tools ...
        /// <summary>
        /// Retrieve a List of Exists Languages ...
        /// </summary>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        [HttpGet("Languages")]
        Task<ActionResult<IEnumerable<string>>> GetLanguages(
            CancellationToken cancellationToken = default
        );

        /// <summary>
        /// Retrieve a List of Resource Titles ...
        /// </summary>
        /// <param name="language">if provided, returns all language Specified resource titles, if not, all Resource Titles</param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        [HttpGet("ResourceTitles")]
        Task<ActionResult<IEnumerable<string>>> GetResourceTitles(
            [FromQuery] string language = null,
            CancellationToken cancellationToken = default
        );

        /// <summary>
        /// Retrieve all Exists Items which belongs to Specified Resource Title ...
        /// </summary>
        /// <param name="resource">Specified Resource Title</param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        [HttpGet("ResourceLocales")]
        Task<ActionResult<IEnumerable<XStringDto>>> GetResourceLocales(
            [FromQuery] string resource,
            CancellationToken cancellationToken = default
        );

        /// <summary>
        /// Extract Translation of a Resource in Specified Language ...
        /// </summary>
        /// <param name="language">Specified Language ...</param>
        /// <param name="resource">Specified Resource Title ...</param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        [HttpGet("Translation")]
        Task<ActionResult<string>> GetResourceTranslation(
            [FromQuery] string language,
            [FromQuery] string resource,
            CancellationToken cancellationToken = default
        );

        /// <summary>
        /// Retrieve a Resource as Locale Model ...
        /// </summary>
        /// <param name="language">Specified Language ...</param>
        /// <param name="resource">Specified Resource Title ...</param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        [HttpGet("Locale")]
        Task<ActionResult<XLocaleResourceDto>> GetLocale(
            [FromQuery] string language,
            [FromQuery] string resource,
            CancellationToken cancellationToken = default
        );

        /// <summary>
        /// Retrieve all Exists Resource Instances as Locale Models ...
        /// </summary>
        /// <param name="resource"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        [HttpGet("Locales")]
        Task<ActionResult<IEnumerable<XLocaleResourceDto>>> GetLocales(
            [FromQuery] string resource,
            CancellationToken cancellationToken = default
        );

        /// <summary>
        /// Retrieve all Locales of Specified Resource and Represent as XResourceDto ...
        /// </summary>
        /// <param name="resource"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        [HttpGet("GetResource")]
        Task<ActionResult<XResourceDto>> GetResource(
            [FromQuery] string resource,
            CancellationToken cancellationToken = default
        );

        /// <summary>
        /// Add or Update a Resource Model ...
        /// </summary>
        /// <param name="resource">a XResourceDto Model ...</param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        [HttpPost("AddOrUpdateResource")]
        Task<ActionResult<XResourceDto>> AddOrUpdateResource(
            [FromBody] XResourceDto resource,
            CancellationToken cancellationToken = default
        );

        /// <summary>
        /// Remove Specified Resource Model ...
        /// </summary>
        /// <param name="resource">a XResourceDto Model ...</param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        [HttpPost("RemoveResource")]
        Task<ActionResult> RemoveResource(
            [FromBody] XResourceDto resource,
            CancellationToken cancellationToken = default
        );
        #endregion
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xStringService\Models\Dtos\XStringDto.cs

using xModels.Base;

namespace xStringService.Models.Dtos
{
    public class XStringDto : XBaseIntIDEntityDto
    {
        public string Language { get; set; }
        public string ResourceTitle { get; set; }
        public string TranslatedValue { get; set; }
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xStringService\Models\Entities\XString.cs

using System.ComponentModel.DataAnnotations;
using xModels.Base;

namespace xStringService.Models.Entities
{
    public class XString : XBaseIntIDEntity
    {
        [Required]
        [StringLength (10)]
        public string Language { get; set; }

        [Required]
        [StringLength (255)]
        public string ResourceTitle { get; set; }

        [Required]
        public string TranslatedValue { get; set; }        
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xStringService\Providers\Dtos\XStringDtoHub.cs

using Microsoft.Extensions.Logging;
using xPushService.Base;
using xStringService.Interfaces.Dtos;
using xStringService.Models.Dtos;
using xStringService.Models.Entities;

namespace xStringService.Providers.Dtos
{
    public class XStringDtoHub : XBaseDtoHub<XString, XStringDto, int>, IXStringDtoHub
    {
        public XStringDtoHub(
            ILogger<XStringDtoHub> logger
        ) : base(logger)
        { }
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xStringService\Providers\Dtos\XStringRepositoryService.cs

using System.Collections.Generic;
using AutoMapper;
using xDataService.Providers;
using xStringService.Interfaces.Dtos;
using xStringService.Interfaces.Entities;
using xStringService.Models.Dtos;
using xStringService.Models.Entities;

namespace xStringService.Providers.Dtos
{
    public class XStringRepositoryService : XBaseRepositoryService<XString, XStringDto, int>, IXStringRepositoryService
    {
        public XStringRepositoryService(
            IXStringRepository repository,
            IEnumerable<Profile> mapperProfiles = null
        ) : base(
            repository,
            mapperProfiles
        )
        { }
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xStringService\Providers\Dtos\XStringServiceProvider.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.AspNetCore.SignalR;
using xCommons.Configurations;
using xCommons.Extensions;
using xDataService.Configuration;
using xExceptions.Constants;
using xIdentityService.Interfaces;
using xModels.Dtos;
using xPushService.Base;
using xPushService.Constants;
using xStringService.Extensions;
using xStringService.Interfaces.Dtos;
using xStringService.Models.Dtos;
using xStringService.Models.Entities;

namespace xStringService.Providers.Dtos
{
    public class XStringServiceProvider : XBaseDtoProvider<XString, XStringDto, int, XStringDtoHub>, IXStringServiceProvider
    {
        public XAppConfiguration AppConfiguration { get; }

        public XStringServiceProvider(
            IHubContext<XStringDtoHub> hub,
            XDataServiceConfiguration dataConfiguration,
            IXStringRepositoryService service,
            XAppConfiguration appConfiguration,
            IXIdentityProvider identityProvider = null
        ) : base(
            hub,
            dataConfiguration,
            service,
            identityProvider
        )
        {
            AppConfiguration = appConfiguration;
        }

        //
        #region Retrievers ...
        /// <summary>
        /// Retrieve all Exists Languages ...
        /// </summary>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public async Task<IEnumerable<string>> GetLanguages(
            CancellationToken cancellationToken = default
        )
        {
            //
            var result = (await Service.GetAllAsync(
                includeBuilder: null,
                ignoreSoftDeleteds: true,
                cancellationToken: cancellationToken,
                orderBuilder: x => x.OrderBy(y => y.Language)
            ))
            .AsQueryable()
            .Select(e => e.Language)
            .Distinct()
            .ToList();

            //
            // Check Configuration Default Language Exists ...
            var hasDefaultLanguage = !AppConfiguration.DefaultLanguage.IsNullOrEmpty();
            if (hasDefaultLanguage)
            {
                //
                // Find Default Language on Result ...
                hasDefaultLanguage = result.Any(e => e.ToNormalString() == AppConfiguration.DefaultLanguage.ToNormalString());
                if (!hasDefaultLanguage)
                {
                    result.Add(AppConfiguration.DefaultLanguage);
                }
            }

            //
            result = result
                .Distinct()
                .ToList();

            //
            return result;
        }

        /// <summary>
        /// Check Specified Resource Exists or not ...
        /// </summary>
        /// <param name="resource"></param>
        /// <param name="language"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public async Task<bool> IsResourceExists(
            string resource,
            string language = null,
            CancellationToken cancellationToken = default
        )
        {
            //
            var result = false;

            //
            // Validate ...
            result = !resource.IsNullOrEmpty();
            if (!result)
            {
                return result;
            }

            //
            XStringDto dto = null;
            if (language.IsNullOrEmpty())
            {
                //
                dto = await Service
                    .FindOneAsync(
                        includeBuilder: null,
                        ignoreSoftDeleteds: true,
                        cancellationToken: cancellationToken,
                        predicate: e => e.ResourceTitle == resource
                    );
            }
            else
            {
                //
                dto = await Service
                    .FindOneAsync(
                        includeBuilder: null,
                        ignoreSoftDeleteds: true,
                        cancellationToken: cancellationToken,
                        predicate:
                            e => e.ResourceTitle == resource &&
                            e.Language.ToNormalString() == language.ToNormalString()
                    );
            }

            //
            result = !dto.IsNullOrDefault();

            //
            return result;
        }

        /// <summary>
        /// Retrieve Specified Resource ...
        /// </summary>
        /// <param name="resource"></param>
        /// <param name="language"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public async Task<XStringDto> Get(
            string resource,
            string language = null,
            CancellationToken cancellationToken = default
        )
        {
            //
            // Normalize ...
            if (language.IsNullOrEmpty())
            {
                language = AppConfiguration.DefaultLanguage;
            }

            //
            // Validate ...
            if (resource.IsNullOrEmpty() || language.IsNullOrEmpty())
            {
                XException.InvalidArgs.Throw();
            }

            //
            // Check Resource Exists ...
            var isExists = await IsResourceExists(
                resource: resource,
                language: language
            );
            if (!isExists)
            {
                XException.NotFound.Throw();
            }

            //
            var result = await Service
                .FindOneAsync(
                    includeBuilder: null,
                    ignoreSoftDeleteds: true,
                    cancellationToken: cancellationToken,
                    predicate: e =>
                        e.ResourceTitle == resource &&
                        e.Language.ToNormalString() == language.ToNormalString()
            );
            if (result.IsNullOrDefault())
            {
                XException.ActionFailed.Throw();
            }

            //
            return result;
        }

        /// <summary>
        /// Retrieve Specified Translation of Specified Resource ...
        /// </summary>
        /// <param name="resource"></param>
        /// <param name="language"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public async Task<string> GetResourceValue(
            string resource,
            string language = null,
            CancellationToken cancellationToken = default
        )
        {
            //
            var result = "";

            //
            // Normalize ...
            if (language.IsNullOrEmpty())
            {
                language = AppConfiguration.DefaultLanguage;
            }

            //
            // Validate ...
            var isValid =
                !resource.IsNullOrEmpty() &&
                !language.IsNullOrEmpty();
            if (!isValid)
            {
                XException.InvalidArgs.Throw();
            }

            //
            // Check Langauage Exists ...
            var languages = await GetLanguages(cancellationToken);
            isValid = languages.Any(l => l.ToNormalString() == language.ToNormalString());
            if (!isValid)
            {
                XException.NotFound.Throw();
            }

            //
            // Check Resource Exists ...
            isValid = await IsResourceExists(
                resource: resource,
                language: language,
                cancellationToken: cancellationToken
            );
            if (!isValid)
            {
                XException.NotFound.Throw();
            }

            //
            var dto = await Service.FindOneAsync(
                includeBuilder: null,
                ignoreSoftDeleteds: true,
                cancellationToken: cancellationToken,
                predicate: e =>
                    e.ResourceTitle == resource &&
                    e.Language.ToNormalString() == language.ToNormalString()
            );
            isValid = !dto.IsNullOrDefault();
            if (!isValid)
            {
                XException.ActionFailed.Throw();
            }

            //
            result = dto.TranslatedValue;

            //
            return result;
        }

        /// <summary>
        /// Retrieve an Specified Resource Items ...
        /// </summary>
        /// <param name="resource"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public async Task<IEnumerable<XStringDto>> GetResources(
            string resource,
            CancellationToken cancellationToken = default
        )
        {
            //
            // Validate ...
            var isValid = await IsResourceExists(resource);
            if (!isValid)
            {
                XException.NotFound.Throw();
            }

            //
            var result = await Service
                .FindManyAsync(
                    includeBuilder: null,
                    ignoreSoftDeleteds: true,
                    predicate: e =>
                        e.ResourceTitle == resource,
                    orderBuilder: x =>
                        x.OrderBy(y => y.ResourceTitle),
                    cancellationToken: cancellationToken
                );

            //
            return result;
        }

        /// <summary>
        /// Retrieve Specified Resource Items as XResourceDto Presentation ...
        /// </summary>
        /// <param name="resource"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public async Task<XResourceDto> GetResource(
            string resource,
            CancellationToken cancellationToken = default
        )
        {
            //
            // Validate ...
            bool isExists = await IsResourceExists(
                language: null,
                resource: resource,
                cancellationToken: cancellationToken
            );
            if (!isExists)
            {
                XException.NotFound.Throw();
            }

            //
            // Retrieve String Dto (s) ...
            var resources = await GetResources(
                resource: resource,
                cancellationToken: cancellationToken
            );
            if (!resource.HasChild())
            {
                XException.NotFound.Throw();
            }

            //
            var result = new XResourceDto
            {
                Resource = resource,
                Locales = resources.ToXLocaleResourceDtos()
            };

            //
            return result;
        }
        #endregion

        //
        #region Query ...
        /// <summary>
        /// Query Resource IDs ...
        /// </summary>
        /// <param name="query"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public async Task<XQueryResult<string>> QueryResourceIds(
            XQuery query,
            CancellationToken cancellationToken = default
        )
        {
            //
            var dtoResult = await Service.QueryAsync(
                query: query,
                predicate: null,
                includeBuilder: null,
                ignoreSoftDeleteds: true,
                orderBuilder: x =>
                    x.OrderBy(y => y.ResourceTitle),
                cancellationToken: cancellationToken
            );

            //
            var result = new XQueryResult<string>()
                .UpdateData(
                    updateWith: dtoResult,
                    propertyBlackList: new List<string>
                    {
                        nameof(XQueryResult<string>.Items)
                    });

            //
            result.Items = dtoResult.Items.ToList().Select(dto => dto.ResourceTitle);

            //
            return result;
        }

        /// <summary>
        /// Query Specified Language Resources ...
        /// </summary>
        /// <param name="query"></param>
        /// <param name="language"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public async Task<XQueryResult<XStringDto>> QueryLanguageResources(
            XQuery query,
            string language = null,
            CancellationToken cancellationToken = default
        )
        {
            //
            var result = await Service.QueryAsync(
                query: query,
                includeBuilder: null,
                ignoreSoftDeleteds: true,
                orderBuilder: x => x
                    .OrderBy(y => y.Language)
                    .ThenBy(y => y.ResourceTitle),
                cancellationToken: cancellationToken,
                predicate: x =>
                    x.Language.ToNormalString() == language.ToNormalString()
            );

            //
            return result;
        }

        /// <summary>
        /// Query Locale Resources ...
        /// </summary>
        /// <param name="query"></param>
        /// <param name="language"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public async Task<XQueryResult<XLocaleResourceDto>> QueryLocaleResources(
            XQuery query,
            string language = null,
            CancellationToken cancellationToken = default
        )
        {
            //
            Expression<Func<XString, bool>> predicate = null;
            if (!language.IsNullOrEmpty())
            {
                //
                predicate = x =>
                    x.Language.ToNormalString() == language.ToNormalString();
            }

            //
            var dtoResult = await Service.QueryAsync(
                query: query,
                includeBuilder: null,
                predicate: predicate,
                ignoreSoftDeleteds: true,
                orderBuilder: x => x
                    .OrderBy(y => y.Language)
                    .ThenBy(y => y.ResourceTitle),
                cancellationToken: cancellationToken
            );

            //
            var result = new XQueryResult<XLocaleResourceDto>()
                .UpdateData(
                    updateWith: dtoResult,
                    propertyBlackList: new List<string>
                    {
                        nameof(XQueryResult<XLocaleResourceDto>.Items)
                    });

            //
            result.Items = dtoResult.Items.ToList().ToXLocaleResourceDtos();

            //
            return result;
        }
        #endregion

        //
        #region Add/Update Actions ...
        /// <summary>
        /// Add Specified Resource ...
        /// </summary>
        /// <param name="resource"></param>
        /// <param name="value"></param>
        /// <param name="language"></param>
        /// <param name="connectionId"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public async Task<bool> Add(
            string resource,
            string value,
            string language = null,
            string connectionId = null,
            CancellationToken cancellationToken = default
        )
        {
            //
            bool result = false;

            //
            // Normalize ...
            if (language.IsNullOrEmpty())
            {
                language = AppConfiguration.DefaultLanguage;
            }

            //
            // Validate ...
            result =
                !value.IsNullOrEmpty() &&
                !resource.IsNullOrEmpty() &&
                !language.IsNullOrEmpty();
            if (!result)
            {
                return result;
            }

            //
            // Check Exists ...
            bool isExists = await IsResourceExists(
                resource: resource,
                language: language,
                cancellationToken: cancellationToken
            );
            result = !isExists;
            if (!result)
            {
                XException.Duplicate.Throw();
            }

            //
            // Prepare Entity to Add ...
            XStringDto item = new XStringDto
            {
                Language = language,
                TranslatedValue = value,
                ResourceTitle = resource,
            };
            item = await AddAsync(
                item: item,
                saveChanges: true,
                connectionId: connectionId,
                cancellationToken: cancellationToken
            );
            result = !item.IsNullOrDefault();

            //
            return result;
        }

        /// <summary>
        /// Update Resource ...
        /// </summary>
        /// <param name="resource"></param>
        /// <param name="value"></param>
        /// <param name="language"></param>
        /// <param name="connectionId"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public async Task<bool> Update(
            string resource,
            string value,
            string language = null,
            string connectionId = null,
            CancellationToken cancellationToken = default
        )
        {
            //
            bool result = false;

            //
            // Normalize ...
            if (language.IsNullOrEmpty())
            {
                language = AppConfiguration.DefaultLanguage;
            }

            //
            // Validate ...
            result =
                !value.IsNullOrEmpty() &&
                !language.IsNullOrEmpty() &&
                !resource.IsNullOrEmpty();
            if (!result)
            {
                return result;
            }

            //
            // Check Value Must Exists ...
            result = await IsResourceExists(
                resource: resource,
                language: language,
                cancellationToken: cancellationToken
            );
            if (!result)
            {
                XException.NotFound.Throw();
            }

            //
            var item = await Get(
                language: language,
                resource: resource,
                cancellationToken: cancellationToken
            );
            item.TranslatedValue = value;
            item = await UpdateAsync(
                item: item,
                id: item.Id,
                saveChanges: true,
                connectionId: connectionId,
                cancellationToken: cancellationToken
            );
            result = !item.IsNullOrDefault();

            //
            return result;
        }

        /// <summary>
        /// Add Or Update Resource ...
        /// </summary>
        /// <param name="resource"></param>
        /// <param name="value"></param>
        /// <param name="language"></param>
        /// <param name="connectionId"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public async Task<bool> AddOrUpdate(
            string resource,
            string value,
            string language = null,
            string connectionId = null,
            CancellationToken cancellationToken = default
        )
        {
            //
            var result = false;

            //
            // Normalize ...
            if (language.IsNullOrEmpty())
            {
                language = AppConfiguration.DefaultLanguage;
            }

            //
            // Check Existsance ...
            bool isExists = await IsResourceExists(
                resource: resource,
                language: language
            );

            //
            // Act Based on Existance ...
            if (isExists)
            {
                //
                result = await Update(
                    value: value,
                    resource: resource,
                    language: language,
                    connectionId: connectionId,
                    cancellationToken: cancellationToken
                );
            }
            else
            {
                //
                result = await Add(
                    value: value,
                    resource: resource,
                    language: language,
                    connectionId: connectionId,
                    cancellationToken: cancellationToken
                );
            }

            //
            return result;
        }

        /// <summary>
        /// Add Specified Locale Resource ...
        /// </summary>
        /// <param name="item"></param>
        /// <param name="resource"></param>
        /// <param name="connectionId"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public async Task<XStringDto> AddByLocaleResource(
            XLocaleResourceDto item,
            string resource,
            string connectionId = null,
            CancellationToken cancellationToken = default
        )
        {
            //
            // Validate ...
            bool isValid =
                !item.IsNull() &&
                !resource.IsNullOrEmpty() &&
                !item.Value.IsNullOrEmpty() &&
                !item.Language.IsNullOrEmpty();
            if (!isValid)
            {
                XException.InvalidArgs.Throw();
            }

            //
            // Check Specified Resource / Language Exists ...
            isValid = await IsResourceExists(
                resource: resource,
                language: item.Language,
                cancellationToken: cancellationToken
            );
            if (isValid)
            {
                XException.Duplicate.Throw();
            }

            //
            // Prepare Item to Add ...
            var result = new XStringDto
            {
                Language = item.Language,
                ResourceTitle = resource,
                TranslatedValue = item.Value
            };
            result = await AddAsync(
                item: result,
                saveChanges: true,
                connectionId: connectionId,
                cancellationToken: cancellationToken
            );

            //
            return result;
        }

        /// <summary>
        /// Update Specified Locale Resource ...
        /// </summary>
        /// <param name="item"></param>
        /// <param name="resource"></param>
        /// <param name="connectionId"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public async Task<XStringDto> UpdateByLocaleResource(
            XLocaleResourceDto item,
            string resource,
            string connectionId = null,
            CancellationToken cancellationToken = default
        )
        {
            //
            // Validate ...
            bool isValid =
                !item.IsNull() &&
                !resource.IsNullOrEmpty() &&
                !item.Value.IsNullOrEmpty() &&
                !item.Language.IsNullOrEmpty();
            if (!isValid)
            {
                XException.InvalidArgs.Throw();
            }

            //
            // Check Specified Resource / Language Exists ...
            isValid = await IsResourceExists(
                resource: resource,
                language: item.Language,
                cancellationToken: cancellationToken
            );
            if (!isValid)
            {
                XException.NotFound.Throw();
            }

            //
            var result = await Get(
                resource: resource,
                language: item.Language,
                cancellationToken: cancellationToken
            );
            isValid = !result.IsNullOrDefault();
            if (!isValid)
            {
                XException.NotFound.Throw();
            }

            //
            // Update ...
            result.TranslatedValue = item.Value;
            result = await UpdateAsync(
                item: result,
                id: result.Id,
                saveChanges: true,
                connectionId: connectionId,
                cancellationToken: cancellationToken
            );
            isValid = !result.IsNullOrDefault();
            if (!isValid)
            {
                XException.ActionFailed.Throw();
            }

            //
            return result;
        }

        /// <summary>
        /// Add Or Update Resource By Locale ...
        /// </summary>
        /// <param name="item"></param>
        /// <param name="resource"></param>
        /// <param name="connectionId"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public async Task<XStringDto> AddOrUpdateByLocaleResource(
            XLocaleResourceDto item,
            string resource,
            string connectionId = null,
            CancellationToken cancellationToken = default
        )
        {
            //
            // Validate ...
            bool isValid =
                !item.IsNull() &&
                !resource.IsNullOrEmpty() &&
                !item.Value.IsNullOrEmpty() &&
                !item.Language.IsNullOrEmpty();
            if (!isValid)
            {
                XException.InvalidArgs.Throw();
            }

            //
            // Check Specified Resource / Language Exists ...
            isValid = await IsResourceExists(
                resource: resource,
                language: item.Language,
                cancellationToken: cancellationToken
            );

            //
            XStringDto result = null;
            if (!isValid)
            {
                //
                result = await AddByLocaleResource(
                    item: item,
                    resource: resource,
                    connectionId: connectionId,
                    cancellationToken: cancellationToken
                );
            }
            else
            {
                //
                result = await UpdateByLocaleResource(
                    item: item,
                    resource: resource,
                    connectionId: connectionId,
                    cancellationToken: cancellationToken
                );
            }
            if (result.IsNullOrDefault())
            {
                XException.ActionFailed.Throw();
            }

            //
            return result;
        }

        /// <summary>
        /// Add Or Update all XResourceDto(s) Locales ...
        /// </summary>
        /// <param name="item"></param>
        /// <param name="connectionId"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public async Task<IEnumerable<XStringDto>> AddByResource(
            XResourceDto item,
            string connectionId = null,
            CancellationToken cancellationToken = default
        )
        {
            //
            // Validate ...
            bool isValid =
                !item.IsNull() &&
                item.Locales.HasChild() &&
                !item.Resource.IsNullOrEmpty();
            if (!isValid)
            {
                XException.InvalidArgs.Throw();
            }

            //
            var result = await Task
                .WhenAll(item.Locales
                    .Select(async e => await AddOrUpdateByLocaleResource(
                        item: e,
                        resource: item.Resource,
                        connectionId: connectionId,
                        cancellationToken: cancellationToken)));

            //
            return result;
        }
        #endregion

        //
        #region Remove Actions ...
        /// <summary>
        /// Remove all Specified Language's Resources ...
        /// </summary>
        /// <param name="language"></param>
        /// <param name="connectionId"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public async Task RemoveLanguageResources(
            string language,
            string connectionId = null,
            CancellationToken cancellationToken = default
        )
        {
            //
            // Validate ...
            bool isValid = !language.IsNullOrEmpty();
            if (!isValid)
            {
                return;
            }

            //
            var dtos = await Service
                .FindManyAsync(
                    orderBuilder: null,
                    includeBuilder: null,
                    ignoreSoftDeleteds: true,
                    cancellationToken: cancellationToken,
                    predicate: e =>
                        e.Language.ToNormalString() == language.ToNormalString());

            //
            try
            {
                //
                await Service.RemoveRangeAsync(
                    items: dtos,
                    softDelete: false,
                    saveChanges: true,
                    cancellationToken: cancellationToken
                );

                //
                var ids = dtos.Select(e => e.Id);
                await SendPush(
                    connectionId: connectionId,
                    payLoad: ids.ToJSON(camelCase: true),
                    cancellationToken: cancellationToken,
                    action: XBaseEntityHubAction.DeleteMany.GetStringValue()
                );
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }

        /// <summary>
        /// Remove all Specified Resource Ids instances ... 
        /// </summary>
        /// <param name="resource"></param>
        /// <param name="connectionId"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public async Task<IEnumerable<XStringDto>> RemoveResource(
            string resource,
            string connectionId = null,
            CancellationToken cancellationToken = default
        )
        {
            //
            // Validate ...
            bool isValid = !resource.IsNullOrEmpty();
            if (!isValid)
            {
                XException.InvalidArgs.Throw();
            }

            //
            var result = await Service
                .FindManyAsync(
                    orderBuilder: null,
                    includeBuilder: null,
                    ignoreSoftDeleteds: true,
                    cancellationToken: cancellationToken,
                    predicate: e =>
                        e.ResourceTitle.ToNormalString() == resource.ToNormalString());

            //
            try
            {
                //
                await Service.RemoveRangeAsync(
                    items: result,
                    softDelete: false,
                    saveChanges: true,
                    cancellationToken: cancellationToken
                );

                //
                var ids = result.Select(e => e.Id);
                await SendPush(
                    connectionId: connectionId,
                    payLoad: ids.ToJSON(camelCase: true),
                    cancellationToken: cancellationToken,
                    action: XBaseEntityHubAction.DeleteMany.GetStringValue()
                );
            }
            catch (Exception ex)
            {
                throw ex;
            }

            //
            return result;
        }

        /// <summary>
        /// Remove Specified Resource ...
        /// </summary>
        /// <param name="resource"></param>
        /// <param name="language"></param>
        /// <param name="connectionId"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public async Task<bool> Remove(
            string resource,
            string language = null,
            string connectionId = null,
            CancellationToken cancellationToken = default
        )
        {
            //
            bool result = false;

            //
            // Normalize ...
            if (language.IsNullOrEmpty())
            {
                language = AppConfiguration.DefaultLanguage;
            }

            //
            // Validate ...
            result =
                !language.IsNullOrEmpty() &&
                !resource.IsNullOrEmpty();
            if (!result)
            {
                return result;
            }

            //
            // Check Resource Exists ...
            result = await IsResourceExists(
                language: language,
                resource: resource,
                cancellationToken: cancellationToken
            );
            if (!result)
            {
                return result;
            }

            //
            var dto = await Get(
                language: language,
                resource: resource,
                cancellationToken: cancellationToken
            );
            result = !dto.IsNullOrDefault();
            if (!result)
            {
                return result;
            }

            //
            dto = await RemoveAsync(
                id: dto.Id,
                softDelete: false,
                saveChanges: true,
                connectionId: connectionId,
                cancellationToken: cancellationToken
            );
            result = !dto.IsNullOrDefault();

            //
            return result;
        }

        /// <summary>
        /// Remove all Resource of Specified XResourceDto ...
        /// </summary>
        /// <param name="item"></param>
        /// <param name="connectionId"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public async Task RemoveByResource(
            XResourceDto item,
            string connectionId = null,
            CancellationToken cancellationToken = default
        )
        {
            //
            bool isValid =
                !item.IsNullOrDefault() &&
                item.Locales.HasChild() &&
                !item.Resource.IsNullOrEmpty();
            if (!isValid)
            {
                XException.InvalidArgs.Throw();
            }

            //            
            foreach (var locale in item.Locales)
            {
                //
                await Remove(
                    resource: item.Resource,
                    language: locale.Language,
                    connectionId: connectionId,
                    cancellationToken: cancellationToken
                );
            }
        }
        #endregion
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xStringService\Providers\Entities\XStringEFRepository.cs

using xDataService.Configuration;
using xDataService.Db;
using xDataService.Interfaces;
using xDataService.Providers;
using xStringService.Interfaces.Entities;
using xStringService.Models.Entities;

namespace xStringService.Providers.Entities
{
    public class XStringEFRepository<TContext> : XBaseEFRepository<XString, int, TContext>, IXStringRepository
    where TContext : XDbContext
    {
        public XStringEFRepository(
            IXUnitOfWorks<TContext> unitOfWorks, 
            XDataServiceConfiguration configuration, 
            IXStringKeyGenerator keyGenerator = null, 
            IXStringRepositoryEvents baseRepositoryEvents = null
        ) : base(
            unitOfWorks, 
            configuration, 
            keyGenerator, 
            baseRepositoryEvents
        )
        { }
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xStringService\Providers\Entities\XStringEntityHub.cs

using Microsoft.Extensions.Logging;
using xPushService.Base;
using xStringService.Interfaces.Entities;
using xStringService.Models.Entities;

namespace xStringService.Providers.Entities
{
    public class XStringEntityHub : XBaseEntityHub<XString, int>, IXStringEntityHub
    {
        public XStringEntityHub(
            ILogger<XStringEntityHub> logger
        ) : base(logger)
        { }
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xStringService\Providers\Entities\XStringInMemoryRepository.cs

using xDataService.Configuration;
using xDataService.Providers;
using xStringService.Interfaces.Entities;
using xStringService.Models.Entities;

namespace xStringService.Providers.Entities
{
    public class XStringInMemoryRepository : XBaseInMemoryRepository<XString, int>, IXStringRepository
    {
        public XStringInMemoryRepository(
            XDataServiceConfiguration configuration,
            IXStringKeyGenerator keyGenerator = null,
            IXStringRepositoryEvents baseRepositoryEvents = null
        ) : base(
            configuration,
            keyGenerator,
            baseRepositoryEvents
        )
        { }
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xStringService\Providers\Entities\XStringKeyGenerator.cs

using xDataService.Providers;
using xStringService.Interfaces.Entities;
using xStringService.Models.Entities;

namespace xStringService.Providers.Entities
{
    public class XStringKeyGenerator : XIntKeyGenerator<XString>, IXStringKeyGenerator
    { }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xStringService\Providers\Entities\XStringMongoRepository.cs

using xDataService.Configuration;
using xDataService.Providers;
using xStringService.Interfaces.Entities;
using xStringService.Models.Entities;

namespace xStringService.Providers.Entities
{
    public class XStringMongoRepository : XBaseMongoRepository<XString, int>, IXStringRepository
    {
        public XStringMongoRepository(
            XDataBaseConfiguration dbConfiguration,
            XDataServiceConfiguration configuration,
            string collectionName = null,
            IXStringKeyGenerator keyGenerator = null,
            IXStringRepositoryEvents baseRepositoryEvents = null
        ) : base(
            dbConfiguration,
            configuration,
            collectionName,
            keyGenerator,
            baseRepositoryEvents
        )
        { }
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xStringService\Providers\Entities\XStringRepositoryEvents.cs

using xDataService.Providers;
using xStringService.Interfaces.Entities;
using xStringService.Models.Entities;

namespace xStringService.Providers.Entities
{
    public class XStringRepositoryEvents : XBaseRepositoryEvents<XString>, IXStringRepositoryEvents
    {}
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xStringService\Providers\Entities\XStringRepositoryProvider.cs

using Microsoft.AspNetCore.SignalR;
using xDataService.Configuration;
using xIdentityService.Interfaces;
using xPushService.Base;
using xStringService.Interfaces.Entities;
using xStringService.Models.Entities;

namespace xStringService.Providers.Entities
{
    public class XStringRepositoryProvider : XBaseEntityProvider<XString, int, XStringEntityHub>, IXStringRepositoryProvider
    {
        public XStringRepositoryProvider(
            IHubContext<XStringEntityHub> hub,
            IXStringRepository repository,
            XDataServiceConfiguration dataConfiguration,
            IXIdentityProvider identityProvider = null
        ) : base(
            hub,
            repository,
            dataConfiguration,
            identityProvider
        )
        { }
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xStringService\Providers\Entities\XStringSeederBase.cs

using xDataService.Configuration;
using xDataService.Providers;
using xStringService.Interfaces.Entities;
using xStringService.Models.Entities;

namespace xStringService.Providers.Entities
{
    public abstract class XStringSeederBase : XBaseDbSeeder<XString, int>, IXStringSeeder
    {
        protected XStringSeederBase(
            string entity,
            string database,
            IXStringRepository repository,
            XDataServiceConfiguration dataServiceConfiguration
        ) : base(
            entity,
            database,
            repository,
            dataServiceConfiguration
        )
        { }
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xStringService\Providers\GraphQL\XStringGraphQLTypeHelper.cs

using xDataService.Configuration;
using xDataService.GraphQL;
using xStringService.Constants;
using xStringService.Interfaces.Entities;
using xStringService.Models.Entities;

namespace xStringService.Providers.GraphQL
{
    public class XStringGraphQLTypeHelper : XBaseGraphQLTypeHelper<XString, int>, IXStringGraphQLTypeHelper
    {
        public XStringGraphQLTypeHelper(
            XDataServiceConfiguration configuration
        ) : base(configuration)
        { }

        public override string GetInQueryCollectionName()
        {
            return XStringServiceConstants.XStringCollectionName;
        }

        public override string GetInQuerySingleName()
        {
            return XStringServiceConstants.XStringSingleName;
        }
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xStringService\Providers\GraphQL\XStringGraphQuery.cs

using GraphQL.Types;
using xDataService.Configuration;
using xDataService.GraphQL;
using xStringService.Interfaces.Entities;
using xStringService.Models.Entities;

namespace xDataHelper.Providers.GraphQL
{
    public class XStringGraphQuery : XBaseGraphQLQuery<XString, int, XStringGraphType, IntGraphType>
    {
        public XStringGraphQuery(
            XDataServiceConfiguration configuration,
            IXStringRepository repository,
            IXStringGraphQLTypeHelper helper
        ) : base(
            configuration,
            repository,
            helper
        )
        { }
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xStringService\Providers\GraphQL\XStringGraphSchema.cs

using System;
using GraphQL.Types;

namespace xDataHelper.Providers.GraphQL
{
    public class XStringGraphSchema : Schema
    {
        public XStringGraphSchema(IServiceProvider services) : base(services)
        {
            Query = (XStringGraphQuery)services.GetService(typeof(XStringGraphQuery));
        }
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xStringService\Providers\GraphQL\XStringGraphType.cs

using xDataService.GraphQL;
using xStringService.Models.Entities;

namespace xDataHelper.Providers.GraphQL
{
    public class XStringGraphType : XBaseGraphObjectType<XString, int>
    {
        public XStringGraphType() : base()
        {
            Field(x => x.Language);
            Field(x => x.ResourceTitle);
            Field(x => x.TranslatedValue);
        }
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xStringService\Providers\XBaseItemResourceProvider.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using xCommons.Extensions;
using xExceptions.Constants;
using xModels.Dtos;
using xStringService.Interfaces;
using xStringService.Interfaces.Dtos;
using xStringService.Models.Dtos;

namespace xStringService.Providers
{
    public abstract class XBaseItemResourceProvider : IXItemResourceProvider
    {
        //
        #region Props ...
        /// <summary>
        /// Item Name for Resource Providing ... 
        /// </summary>
        private readonly string item;

        /// <summary>
        /// an Implementation of Item Resource Provider 
        /// </summary>
        /// <value></value>
        private readonly XBaseResourceProvider provider;

        /// <summary>
        /// String Provider Service ...
        /// </summary>
        private readonly IXStringServiceProvider stringProvider;
        #endregion

        //
        #region Constructor ...
        protected XBaseItemResourceProvider(
            string item,
            IXStringServiceProvider stringProvider
        )
        {
            //
            this.item = item;
            this.stringProvider = stringProvider;
            provider = new XBaseResourceProvider(
                item,
                stringProvider
            );
        }
        #endregion

        //
        #region Group Actions ...
        /// <summary>
        /// Retrieve a List of Exists Languages for Current Item ...
        /// </summary>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public virtual async Task<IEnumerable<string>> GetLanguages(
            CancellationToken cancellationToken = default
        )
        {
            //
            var result = (await ExtractItems(cancellationToken))
                .Select(x => x.Language)
                .Distinct();

            //
            return result;
        }

        /// <summary>
        /// Retrieve all Exists Items of type ...
        /// </summary>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public virtual async Task<IEnumerable<XStringDto>> GetResourceLocales(
            CancellationToken cancellationToken = default
        )
        {
            //
            var result = await ExtractItems(cancellationToken);

            //
            return result;
        }

        /// <summary>
        /// Remove all Exists Locales which Related to this Provider ...
        /// </summary>
        /// <param name="connectionId"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public virtual async Task RemoveResourceLocales(
            string connectionId = null,
            CancellationToken cancellationToken = default
        )
        {
            //
            var isDelete = false;
            XStringDto deleted = null;
            var items = await ExtractItems(cancellationToken);
            foreach (var item in items)
            {
                //
                // Check Cancellation ...
                if (cancellationToken.IsCancellationRequested)
                {
                    break;
                }

                //
                // Remove Item ...
                deleted = await stringProvider.RemoveAsync(
                    id: item.Id,
                    softDelete: false,
                    saveChanges: true,
                    connectionId: connectionId,
                    cancellationToken: cancellationToken
                );

                //
                // Check Removation Succeed ...
                isDelete = !deleted.IsNullOrDefault();
                if (!isDelete)
                {
                    XException.ActionFailed.Throw();
                }
            }
        }
        #endregion

        //
        #region Item Actions ...
        /// <summary>
        /// Get all Exists Items for Specified identitifer ...
        /// </summary>
        /// <param name="identifier"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public virtual async Task<IEnumerable<XStringDto>> GetResourceLocales(
            object identifier,
            CancellationToken cancellationToken = default
        )
        {
            //
            // Validate ...
            var isValid = !identifier.IsNull();
            if (!isValid)
            {
                XException.InvalidArgs.Throw();
            }

            //
            // Setting Resource Title ...
            SetResourceTitle(identifier);

            //
            // Retrieve Resource List ...
            var result = await provider
                .GetResourceLocales(cancellationToken);

            //
            return result;
        }

        /// <summary>
        /// Get all Exists Items for Specified identitifer ...
        /// </summary>
        /// <param name="identifier"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public virtual async Task<IEnumerable<XLocaleResourceDto>> GetLocales(
            object identifier,
            CancellationToken cancellationToken = default
        )
        {
            //
            // Validate ...
            var isValid = !identifier.IsNull();
            if (!isValid)
            {
                XException.InvalidArgs.Throw();
            }

            //
            // Setting Resource Title ...
            SetResourceTitle(identifier);

            //
            // Retrieve Resource List ...
            var result = await provider
                .GetLocales(cancellationToken);

            //
            return result;
        }

        /// <summary>
        /// Get all Exists Locales Representaion based on Specified Identitifer
        /// as XResourceDto ...
        /// </summary>
        /// <param name="identifier"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public virtual async Task<XResourceDto> GetResource(
            object identifier,
            CancellationToken cancellationToken = default
        )
        {
            //
            // Validate ...
            var isValid = !identifier.IsNull();
            if (!isValid)
            {
                XException.InvalidArgs.Throw();
            }

            //
            // Setting Resource Title ...
            SetResourceTitle(identifier);

            //
            // Retrieve Resource List ...
            var result = await provider
                .GetResource(cancellationToken);

            //
            return result;
        }

        /// <summary>
        /// Add Or Update Locale for Specified Identitifer ...
        /// </summary>
        /// <param name="identifier"></param>
        /// <param name="locale"></param>
        /// <param name="connectionId"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public virtual async Task<XResourceDto> AddOrUpdateLocale(
            object identifier,
            XLocaleResourceDto locale,
            string connectionId = null,
            CancellationToken cancellationToken = default
        )
        {
            //
            // Validate ...
            var isValid =
                !identifier.IsNull() &&
                !locale.IsNullOrDefault() &&
                !locale.Value.IsNullOrEmpty() &&
                !locale.Language.IsNullOrEmpty();
            if (!isValid)
            {
                XException.InvalidArgs.Throw();
            }

            //
            // Setting Resource Title ...
            SetResourceTitle(identifier);

            //
            // Retrieve Resource List ...
            var result = await provider
                .AddOrUpdateLocale(
                    locale: locale,
                    connectionId: connectionId,
                    cancellationToken: cancellationToken
                );

            //
            return result;
        }

        /// <summary>
        /// Update a Resource State ...
        /// </summary>
        /// <param name="identifier"></param>
        /// <param name="resource"></param>
        /// <param name="connectionId"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public virtual async Task<XResourceDto> AddOrUpdateResource(
            object identifier,
            XResourceDto resource,
            string connectionId = null,
            CancellationToken cancellationToken = default
        )
        {
            //
            // Validate ...
            var isValid =
                !identifier.IsNull();
            if (!isValid)
            {
                XException.InvalidArgs.Throw();
            }

            //
            // Retrieve Identified Resource Title ...
            var identifiedResource = GetResourceTitle(identifier);
            isValid =
                !resource.IsNullOrDefault() &&
                (resource.Resource.IsNullOrEmpty() ||
                    resource.Resource == identifiedResource);
            if (!isValid)
            {
                XException.InvalidArgs.Throw();
            }
            if (resource.Resource.IsNullOrEmpty())
            {
                resource.Resource = identifiedResource;
            }

            //
            // Setting Resource Title ...
            SetResourceTitle(identifier);

            //
            // Retrieve Resource List ...
            var result = await provider
                .AddOrUpdateResource(
                    resource: resource,
                    connectionId: connectionId,
                    cancellationToken: cancellationToken
                );

            //
            return result;
        }

        /// <summary>
        /// Remove Specified Language Locale of Specified Identifier ...
        /// </summary>
        /// <param name="identifier"></param>
        /// <param name="language"></param>
        /// <param name="connectionId"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public virtual async Task<XResourceDto> RemoveLocale(
            object identifier,
            string language,
            string connectionId = null,
            CancellationToken cancellationToken = default
        )
        {
            //
            // Validate ...
            var isValid =
                !identifier.IsNull() &&
                !language.IsNullOrEmpty();
            if (!isValid)
            {
                XException.InvalidArgs.Throw();
            }

            // 
            // Check Locale Exists ...
            isValid = await HasLocale(
                language: language,
                identifier: identifier,
                cancellationToken: cancellationToken
            );
            if (!isValid)
            {
                XException.NotFound.Throw();
            }

            //
            var locale = (await GetLocales(
                identifier: identifier,
                cancellationToken: cancellationToken
            ))
            .FirstOrDefault(x =>
                x.Language.Equals(language, StringComparison.InvariantCultureIgnoreCase));
            isValid = !locale.IsNullOrDefault();
            if (!isValid)
            {
                XException.NotFound.Throw();
            }

            //
            // Setting Resource Title ...
            SetResourceTitle(identifier);

            //
            var result = await provider.RemoveLocale(
                locale: locale,
                connectionId: connectionId,
                cancellationToken: cancellationToken
            );

            //
            return result;
        }

        /// <summary>
        /// Remove all Exists Locales for Specified Identifier ...
        /// </summary>
        /// <param name="identifier"></param>
        /// <param name="connectionId"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public virtual async Task RemoveLocales(
            object identifier,
            string connectionId = null,
            CancellationToken cancellationToken = default
        )
        {
            //
            // Validate ...
            var isValid =
                !identifier.IsNull();
            if (!isValid)
            {
                XException.InvalidArgs.Throw();
            }

            //
            var resource = await GetResource(
                identifier: identifier,
                cancellationToken: cancellationToken
            );
            isValid = !resource.IsNullOrDefault();
            if (!isValid)
            {
                XException.NotFound.Throw();
            }

            //
            // Setting Resource Title ...
            SetResourceTitle(identifier);

            //
            await provider.RemoveResource(
                resource: resource,
                connectionId: connectionId,
                cancellationToken: cancellationToken
            );
        }

        /// <summary>
        /// Check Specified ocale Exists for Specified Identifier ...
        /// </summary>
        /// <param name="identifier"></param>
        /// <param name="language"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public virtual async Task<bool> HasLocale(
            object identifier,
            string language,
            CancellationToken cancellationToken = default
        )
        {
            //
            // Validate ...
            var isValid =
                !identifier.IsNull() &&
                !language.IsNullOrEmpty();
            if (!isValid)
            {
                XException.InvalidArgs.Throw();
            }

            //
            // Setting Resource Title ...
            SetResourceTitle(identifier);

            //
            var result = await provider.HasLocale(
                language: language,
                cancellationToken: cancellationToken
            );

            //
            return result;
        }

        /// <summary>
        /// Get all Exists Languages for Specified Identifier ...
        /// </summary>
        /// <param name="identifier"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public virtual async Task<IEnumerable<string>> GetLanguages(
            object identifier,
            CancellationToken cancellationToken = default
        )
        {
            //
            // Validate ...
            var isValid = !identifier.IsNull();
            if (!isValid)
            {
                XException.InvalidArgs.Throw();
            }

            //
            // Setting Resource Title ...
            SetResourceTitle(identifier);

            //
            var result = await provider
                .GetLanguages(cancellationToken);

            //
            return result;
        }
        #endregion

        //
        #region Resource Title Action ...
        /// <summary>
        /// Retrieve Resource Title ...
        /// </summary>
        /// <param name="identifier"></param>
        /// <returns></returns>
        public string GetResourceTitle(object identifier = null)
        {
            //
            var result = item;

            //
            if (!identifier.IsNull())
            {
                result = $"{item}_{identifier}";
            }

            //
            return result;
        }
        #endregion

        //
        #region Private ...
        /// <summary>
        /// Set Resource Title ...
        /// </summary>
        /// <param name="identifier"></param>
        private void SetResourceTitle(object identifier = null)
        {
            //
            var itemIdentifier = GetResourceTitle(identifier);
            provider.SetField(
                field: "resource",
                value: $"{itemIdentifier}"
            );
        }

        /// <summary>
        /// xtract all Items which Belongs to Provider ...
        /// </summary>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        private async Task<IEnumerable<XStringDto>> ExtractItems(
            CancellationToken cancellationToken = default
        )
        {
            //
            var result = await stringProvider
                .FindManyAsync(
                    includeBuilder: null,
                    cancellationToken: cancellationToken,
                    orderBuilder: x => x.OrderBy(y => y.Id),
                    predicate: x =>
                        x.ResourceTitle.StartsWith(
                            item,
                            StringComparison.InvariantCultureIgnoreCase)
                );
            return result;
        }
        #endregion
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xStringService\Providers\XBaseResourceProvider.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using xCommons.Extensions;
using xExceptions.Constants;
using xModels.Dtos;
using xStringService.Extensions;
using xStringService.Interfaces;
using xStringService.Interfaces.Dtos;
using xStringService.Models.Dtos;

namespace xStringService.Providers
{
    public class XBaseResourceProvider : IXResourceProvider
    {
        protected string resource;
        private readonly IXStringServiceProvider provider;

        public XBaseResourceProvider(
            string resource,
            IXStringServiceProvider provider
        )
        {
            this.resource = resource;
            this.provider = provider;
        }

        //
        #region Actions ...
        /// <summary>
        /// Retrieve a List of Exists Languages ...
        /// </summary>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public virtual async Task<IEnumerable<string>> GetLanguages(
            CancellationToken cancellationToken = default
        )
        {
            //
            var result = (await ExtractItems(cancellationToken))
                .Select(x => x.Language)
                .Distinct()
                .ToList();

            //
            return result;
        }

        /// <summary>
        /// Retrieve all Exists Items ...
        /// </summary>
        /// <param name="resource">Specified Resource Title</param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public virtual async Task<IEnumerable<XStringDto>> GetResourceLocales(
            CancellationToken cancellationToken = default
        )
        {
            //
            var result = await ExtractItems(cancellationToken);

            //
            return result;
        }

        /// <summary>
        /// Extract Translation of in Specified Language ...
        /// </summary>
        /// <param name="language">Specified Language ...</param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public virtual async Task<string> GetResourceTranslation(
            string language,
            CancellationToken cancellationToken = default
        )
        {
            //
            var item = (await ExtractItems(cancellationToken))
                .FirstOrDefault(x => x.Language.Equals(language, StringComparison.InvariantCultureIgnoreCase));

            //
            var result = item?.TranslatedValue ?? string.Empty;

            //
            return result;
        }

        /// <summary>
        /// Check Has Specified Translation or not ...
        /// </summary>
        /// <param name="language">Specified Language ...</param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public virtual async Task<bool> HasLocale(
            string language,
            CancellationToken cancellationToken = default
        )
        {
            //
            var item = (await ExtractItems(cancellationToken))
                .FirstOrDefault(x => x.Language.Equals(language, StringComparison.InvariantCultureIgnoreCase));

            //
            var result = !item.IsNullOrDefault();

            //
            return result;
        }

        /// <summary>
        /// Retrieve as Locale Model ...
        /// </summary>
        /// <param name="language">Specified Language ...</param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public virtual async Task<XLocaleResourceDto> GetLocale(
            string language,
            CancellationToken cancellationToken = default
        )
        {
            //
            var item = (await ExtractItems(cancellationToken))
                .FirstOrDefault(x => x.Language.Equals(language, StringComparison.InvariantCultureIgnoreCase));

            //
            var result =
                !item.IsNullOrDefault()
                ? item.ToXLocaleResourceDto()
                : null;

            //
            return result;
        }

        /// <summary>
        /// Retrieve all Exists Locale Models ...
        /// </summary>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public virtual async Task<IEnumerable<XLocaleResourceDto>> GetLocales(
            CancellationToken cancellationToken = default
        )
        {
            //
            var result = (await ExtractItems(cancellationToken))
                .Select(x => x.ToXLocaleResourceDto())
                .ToList();

            //
            return result;
        }

        /// <summary>
        /// Retrieve as XResourceDto ...
        /// </summary>
        /// <param name="resource"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public virtual async Task<XResourceDto> GetResource(
            CancellationToken cancellationToken = default
        )
        {
            //
            var locales = await GetLocales();

            //
            var result = new XResourceDto
            {
                Locales = locales,
                Resource = resource,
            };

            //
            return result;
        }

        /// <summary>
        /// Add or Update a Resource Model ...
        /// </summary>
        /// <param name="resource">a XResourceDto Model ...</param>
        /// <param name="connectionId"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public virtual async Task<XResourceDto> AddOrUpdateResource(
            XResourceDto resource,
            string connectionId = null,
            CancellationToken cancellationToken = default
        )
        {
            //
            var isValid =
                !resource.IsNullOrDefault() &&
                resource.Resource == this.resource;
            if (!isValid)
            {
                XException.InvalidArgs.Throw();
            }

            //
            // Retrieve Exists Resource ...
            var result = await GetResource(cancellationToken);
            isValid = !result.IsNullOrDefault() && result.Locales.HasChild();
            if (isValid)
            {
                await RemoveResource(
                    resource: result,
                    connectionId: connectionId,
                    cancellationToken: cancellationToken
                );
            }

            //
            foreach (var locale in resource.Locales)
            {
                //
                var item = new XStringDto
                {
                    Language = locale.Language,
                    ResourceTitle = this.resource,
                    TranslatedValue = locale.Value,
                };

                //
                await provider.AddAsync(
                    item: item,
                    saveChanges: true,
                    connectionId: connectionId,
                    cancellationToken: cancellationToken
                );
            }

            //
            result = await GetResource(cancellationToken);
            return result;
        }

        /// <summary>
        /// Add Or Update Locale ...
        /// </summary>
        /// <param name="locale"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public virtual async Task<XResourceDto> AddOrUpdateLocale(
            XLocaleResourceDto locale,
            string connectionId = null,
            CancellationToken cancellationToken = default
        )
        {
            //
            var item = (await ExtractItems(cancellationToken))
                .FirstOrDefault(x =>
                    x.ResourceTitle == resource &&
                    x.Language == locale.Language);
            var isExists = !item.IsNullOrDefault();
            if (isExists)
            {
                item.TranslatedValue = locale.Value;
                item = await provider.UpdateAsync(
                    item: item,
                    id: item.Id,
                    saveChanges: true,
                    connectionId: connectionId,
                    cancellationToken: cancellationToken
                );
            }
            else
            {
                item = new XStringDto
                {
                    ResourceTitle = resource,
                    Language = locale.Language,
                    TranslatedValue = locale.Value
                };
                item = await provider.AddAsync(
                    item: item,
                    saveChanges: true,
                    connectionId: connectionId,
                    cancellationToken: cancellationToken
                );
            }

            //
            var result = await GetResource(cancellationToken);

            //
            return result;
        }

        /// <summary>
        /// Remove Locale ...
        /// </summary>
        /// <param name="locale"></param>
        /// <param name="connectionId"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public virtual async Task<XResourceDto> RemoveLocale(
            XLocaleResourceDto locale,
            string connectionId = null,
            CancellationToken cancellationToken = default
        )
        {
            //
            var item = (await ExtractItems(cancellationToken))
                .FirstOrDefault(x =>
                    x.ResourceTitle == resource &&
                    x.Language == locale.Language);
            var isExists = !item.IsNullOrDefault();
            if (isExists)
            {
                await provider.RemoveAsync(
                    id: item.Id,
                    softDelete: false,
                    saveChanges: true,
                    connectionId: connectionId,
                    cancellationToken: cancellationToken
                );
            }

            //
            var result = await GetResource(cancellationToken);

            //
            return result;
        }

        /// <summary>
        /// Remove Specified Resource Model ...
        /// </summary>
        /// <param name="resource">a XResourceDto Model ...</param>
        /// <param name="connectionId"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public virtual async Task RemoveResource(
            XResourceDto resource,
            string connectionId = null,
            CancellationToken cancellationToken = default
        )
        {
            //
            // Validate Resource ...
            var isValid = 
                !resource.IsNullOrDefault() &&
                !resource.Resource.IsNullOrEmpty() &&
                resource.Resource == this.resource;
            if (!isValid)
            {
                XException.InvalidArgs.Throw();
            }
            
            //
            var items = await ExtractItems(cancellationToken);

            //
            foreach (var item in items)
            {
                //
                await provider.RemoveAsync(
                    id: item.Id,
                    softDelete: false,
                    saveChanges: true,
                    connectionId: connectionId,
                    cancellationToken: cancellationToken
                );
            }
        }
        #endregion

        //
        #region Private ...
        private async Task<IEnumerable<XStringDto>> ExtractItems(
            CancellationToken cancellationToken = default
        )
        {
            //
            var result = await provider.FindManyAsync(
                includeBuilder: null,
                ignoreSoftDeleteds: true,
                orderBuilder: x => x
                    .OrderBy(y => y.Language)
                    .ThenBy(y => y.ResourceTitle),
                cancellationToken: cancellationToken,
                predicate: x =>
                    x.ResourceTitle.Equals(resource, StringComparison.InvariantCultureIgnoreCase)
            );

            //
            return result;
        }
        #endregion
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xStringService\Providers\XStringEntityRegisterar.cs

using Microsoft.EntityFrameworkCore;
using xDataService.Interfaces;
using xDataService.Providers;
using xStringService.Configurations.Entities;
using xStringService.Models.Entities;

namespace xStringService.Providers
{
    /// <summary>
    /// an Entity Registerar class for XStringService ...
    /// </summary>
    public class XStringEntityRegisterar : XBaseEntityRegisterar, IXEntityRegisterar
    {
        public XStringEntityRegisterar()
        : base(nameof(XStringEntityRegisterar))
        {
            //
            // Add XString Entity ...
            AddEntity<XString, int>();
        }

        /// <summary>
        /// Configure Entities ...
        /// </summary>
        /// <param name="modelBuilder"></param>
        public override void ConfigureEntities(ModelBuilder modelBuilder)
        {
            //
            // Configure Entity Using Provided ...
            modelBuilder
                .ApplyConfigurationsFromAssembly(typeof(XStringEntityConfiguration).Assembly);
            
            //
            base.ConfigureEntities(modelBuilder);
        }
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xStringService\Providers\XStringProvider.cs

using System.Collections.Generic;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using xCommons.Extensions;
using xExceptions.Constants;
using xIdentityModels.Models;
using xModels.Dtos;
using xPushService.Providers;
using xStringService.Extensions;
using xStringService.Interfaces;
using xStringService.Interfaces.Dtos;
using xStringService.Models.Dtos;
using xStringService.Models.Entities;
using xStringService.Providers.Dtos;

namespace xStringService.Providers
{
    public class XStringProvider : XBaseProvided<XString, XStringDto, int, XStringDtoHub>, IXStringProvider
    {
        public XStringProvider(
            IXStringServiceProvider provider
        ) : base(
            provider,
            permittedRoles: new string[] { }
        )
        { }

        public override bool IsOwned(
            XStringDto item,
            XUserClaimsInfoDto userInfo
        )
        {
            return !item.IsNullOrDefault();
        }

        public override bool IsOwned(
            XString item,
            XUserClaimsInfoDto userInfo
        )
        {
            return !item.IsNullOrDefault();
        }

        //
        #region Tools ...
        /// <summary>
        /// Retrieve a List of Exists Languages ...
        /// </summary>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public async Task<IEnumerable<string>> GetLanguages(
            CancellationToken cancellationToken = default
        )
        {
            //
            var result = (await GetAll(
                includeBuilder: null,
                cancellationToken: cancellationToken,
                orderBuilder: x => x.OrderBy(y => y.Language)
            ))
            .Select(x => x.Language)
            .Distinct()
            .ToList();

            //
            return result;
        }

        /// <summary>
        /// Retrieve a List of Resource Titles ...
        /// </summary>
        /// <param name="language">if provided, returns all language Specified resource titles, if not, all Resource Titles</param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public async Task<IEnumerable<string>> GetResourceTitles(
            string language = null,
            CancellationToken cancellationToken = default
        )
        {
            //
            var result = (await FindMany(
                includeBuilder: null,
                cancellationToken: cancellationToken,
                orderBuilder: x => x.OrderBy(y => y.ResourceTitle),
                predicate: x =>
                    string.IsNullOrWhiteSpace(language) ||
                    x.Language.Equals(language, System.StringComparison.InvariantCultureIgnoreCase)
            ))
            .Select(x => x.ResourceTitle)
            .Distinct()
            .ToList();

            //
            return result;
        }

        /// <summary>
        /// Retrieve all Exists Items which belongs to Specified Resource Title ...
        /// </summary>
        /// <param name="resource">Specified Resource Title</param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public async Task<IEnumerable<XStringDto>> GetResourceLocales(
            string resource,
            CancellationToken cancellationToken = default
        )
        {
            //
            var result = await FindMany(
                includeBuilder: null,
                cancellationToken: cancellationToken,
                orderBuilder: x => x.OrderBy(y => y.Language),
                predicate: x =>
                    !string.IsNullOrWhiteSpace(resource) &&
                    resource.Equals(x.ResourceTitle, System.StringComparison.InvariantCultureIgnoreCase)
            );

            //
            return result;
        }

        /// <summary>
        /// Extract Translation of a Resource in Specified Language ...
        /// </summary>
        /// <param name="language">Specified Language ...</param>
        /// <param name="resource">Specified Resource Title ...</param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public async Task<string> GetResourceTranslation(
            string language,
            string resource,
            CancellationToken cancellationToken = default
        )
        {
            //
            var result = (await FindOne(
                includeBuilder: null,
                cancellationToken: cancellationToken,
                predicate: x =>
                    !string.IsNullOrWhiteSpace(language) &&
                    !string.IsNullOrWhiteSpace(resource) &&
                    x.Language.Equals(language, System.StringComparison.InvariantCultureIgnoreCase) &&
                    x.ResourceTitle.Equals(resource, System.StringComparison.InvariantCultureIgnoreCase)
            ))?
            .TranslatedValue ?? "";

            //
            return result;
        }

        /// <summary>
        /// Retrieve a Resource as Locale Model ...
        /// </summary>
        /// <param name="language">Specified Language ...</param>
        /// <param name="resource">Specified Resource Title ...</param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public async Task<XLocaleResourceDto> GetLocale(
            string language,
            string resource,
            CancellationToken cancellationToken = default
        )
        {
            //
            var result = (await FindOne(
                includeBuilder: null,
                cancellationToken: cancellationToken,
                predicate: x =>
                    !string.IsNullOrWhiteSpace(language) &&
                    !string.IsNullOrWhiteSpace(resource) &&
                    x.Language.Equals(language, System.StringComparison.InvariantCultureIgnoreCase) &&
                    x.ResourceTitle.Equals(resource, System.StringComparison.InvariantCultureIgnoreCase)
            ))?
            .ToXLocaleResourceDto() ?? null;

            //
            return result;
        }

        /// <summary>
        /// Retrieve all Exists Resource Instances as Locale Models ...
        /// </summary>
        /// <param name="resource"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public async Task<IEnumerable<XLocaleResourceDto>> GetLocales(
            string resource,
            CancellationToken cancellationToken = default
        )
        {
            //
            var result = (await GetResourceLocales(
                resource: resource,
                cancellationToken: cancellationToken
            ))
            .ToList()
            .Select(x => x.ToXLocaleResourceDto())
            .ToList();

            //
            return result;
        }

        /// <summary>
        /// Retrieve all Locales of Specified Resource and Represent as XResourceDto ...
        /// </summary>
        /// <param name="resource"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public async Task<XResourceDto> GetResource(
            string resource,
            CancellationToken cancellationToken = default
        )
        {
            //
            XResourceDto result = null;

            //
            // Validate Resource ...
            if (resource.IsNullOrEmpty())
            {
                return result;
            }

            //
            // Extract Locales of Resource ...
            var locales = await GetLocales(
                resource: resource,
                cancellationToken: cancellationToken
            );

            //
            // Prepare Result ...
            result = new XResourceDto
            {
                Locales = locales,
                Resource = resource,
            };

            //
            return result;
        }

        /// <summary>
        /// Add or Update a Resource Model ...
        /// </summary>
        /// <param name="resource">a XResourceDto Model ...</param>
        /// <param name="userInfo">Actor User for Permissions ...</param>
        /// <param name="connectionId"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public async Task<XResourceDto> AddOrUpdateResource(
            XResourceDto resource,
            XUserClaimsInfoDto userInfo = null,
            string connectionId = null,
            CancellationToken cancellationToken = default
        )
        {
            //
            XResourceDto result = null;

            //
            // Validate Args ...
            var isValid =
                !resource.IsNullOrDefault() &&
                !resource.Resource.IsNullOrEmpty();
            if (!isValid)
            {
                XException.InvalidArgs.Throw();
            }

            //
            // Check Permissions ...
            isValid =
                userInfo.IsNullOrDefault() ||
                HasPermision(userInfo);
            if (!isValid)
            {
                XException.NotAllowed.Throw();
            }

            //
            // Remove all Resources if Exists ...
            result = await GetResource(
                resource: resource.Resource,
                cancellationToken: cancellationToken
            );
            var isExists = !result.IsNullOrDefault();
            if (isExists)
            {
                //
                await RemoveResource(
                    resource: result,
                    userInfo: userInfo,
                    cancellationToken: cancellationToken
                );
            }

            //
            // Loop through all Exists Locales and Add them ...
            foreach (var locale in resource.Locales)
            {
                //
                if (cancellationToken.IsCancellationRequested)
                {
                    break;
                }

                //
                var item = new XStringDto
                {
                    Language = locale.Language,
                    TranslatedValue = locale.Value,
                    ResourceTitle = resource.Resource,
                };
                await Add(
                    item: item,
                    userInfo: userInfo,
                    connectionId: connectionId,
                    cancellationToken: cancellationToken
                );
            }

            //
            // Reload Result after Updates ...
            result = await GetResource(
                resource: resource.Resource,
                cancellationToken: cancellationToken
            );

            //
            return result;
        }

        /// <summary>
        /// Remove Specified Resource Model ...
        /// </summary>
        /// <param name="resource">a XResourceDto Model ...</param>
        /// <param name="userInfo">Actor User for Permissions ...</param>
        /// <param name="connectionId"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public async Task RemoveResource(
            XResourceDto resource,
            XUserClaimsInfoDto userInfo = null,
            string connectionId = null,
            CancellationToken cancellationToken = default
        )
        {
            //
            // Validate ...
            var isValid = !resource.IsNullOrDefault();
            if (!isValid)
            {
                return;
            }

            //
            var items = await GetResourceLocales(
                resource: resource.Resource,
                cancellationToken: cancellationToken
            );
            isValid =
                !items.IsNullOrDefault() &&
                items.HasChild();
            if (!isValid)
            {
                return;
            }

            //
            foreach (var item in items)
            {
                //
                if (cancellationToken.IsCancellationRequested)
                {
                    break;
                }

                //
                await Remove(
                    id: item.Id,
                    userInfo: userInfo,
                    connectionId: connectionId,
                    cancellationToken: cancellationToken
                );
            }
        }
        #endregion
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xTagService\Configurations\Entities\XTagEntityConfiguration.cs

using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Metadata.Builders;
using xDataService.Providers;
using xTagService.Models.Entities;

namespace xTagService.Configurations.Entities
{
    public class XTagEntityConfiguration : XBaseEntityTypeConfiguration<XTag, int>
    {
        public override void Configure(EntityTypeBuilder<XTag> builder)
        {
            builder.ToTable("Tags");
        }
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xTagService\Constants\XTagServiceConstants.cs

namespace xTagService.Constants
{
    public struct XTagServiceConstants
    {
        //
        // Service Extensions Log Tag ...
        public const string XTagServiceDILogTag = "XTagService";

        //
        // Table Mapping Identifiers ...
        public const string XTagTable = "Tags";

        //
        // GraphQL Collection Mappings ...
        public const string XTagSingleName = "tag";
        public const string XTagCollectionName = "tags";

        //
        // Hubs ...
        public const string XTagDtoHub = "tagDto";
        public const string XTagEntityHub = "tagEntity";

        //
        // Custome Constants ...

        //
        // EF Repositories Helper Extensions ... 
        public const string GetXTagEFRepositoryDescriptor = "GetXTagEFRepositoryDescriptor";
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xTagService\Controllers\XBaseProvidedHasTagControllerBase.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore.Query;
using Microsoft.Extensions.Logging;
using xCommons.Configurations;
using xCommons.Extensions;
using xCommons.Providers;
using xExceptions.Constants;
using xIdentityService.Controllers;
using xIdentityService.Interfaces;
using xModels.Base;
using xModels.Dtos;
using xPushService.Base;
using xPushService.Interfaces;
using xTagService.Interfaces;

namespace xTagService.Controllers
{
    [AllowAnonymous]
    public abstract class XBaseProvidedHasTagControllerBase<TEntity, TDto, TKey, THub> : XBaseIdentityApiV1Controller, IXBaseProvidedHasTagController<TEntity, TDto, TKey, THub>
    where TEntity : XBaseEntity<TKey>
    where TDto : XBaseEntityDto<TKey>
    where THub : XBaseDtoHub<TEntity, TDto, TKey>
    {
        private readonly IXBaseProvided<TEntity, TDto, TKey, THub> provider;
        private readonly IXTagProvided<TEntity, TDto, TKey, THub> tagProvided;
        private readonly Func<IQueryable<TEntity>, IOrderedQueryable<TEntity>> defaultOrderBuilder;
        private readonly Func<IQueryable<TEntity>, IIncludableQueryable<TEntity, object>> defaultIncludeBuilder;

        protected XBaseProvidedHasTagControllerBase(
            ILogger<XBaseProvidedHasTagControllerBase<TEntity, TDto, TKey, THub>> logger,
            XAppConfiguration appConfiguration,
            IXIdentityProvider identityProvider,
            XValidationProvider validationProvider,
            IXBaseProvided<TEntity, TDto, TKey, THub> provider,
            IXTagProvided<TEntity, TDto, TKey, THub> tagProvided,
            Func<IQueryable<TEntity>, IOrderedQueryable<TEntity>> defaultOrderBuilder = null,
            Func<IQueryable<TEntity>, IIncludableQueryable<TEntity, object>> defaultIncludeBuilder = null
        ) : base(
            logger,
            appConfiguration,
            identityProvider,
            validationProvider
        )
        {
            this.provider = provider;
            this.tagProvided = tagProvided;
            this.defaultOrderBuilder = defaultOrderBuilder;
            this.defaultIncludeBuilder = defaultIncludeBuilder;
        }

        //
        #region Provided ...
        //
        #region Retrieve ...
        /// <summary>
        /// Get Specified Item by ID ...
        /// </summary>
        /// <param name="id"></param>
        /// <param name="useDefaultIncludes"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        [HttpGet("{id}")]
        public virtual async Task<ActionResult<TDto>> Get(
            [FromRoute] TKey id,
            [FromQuery] bool useDefaultIncludes = false,
            CancellationToken cancellationToken = default
        )
        {
            //
            try
            {
                //
                // Validate ...
                if (!ModelState.IsValid)
                {
                    XException.InvalidArgs.Throw();
                }
                ValidationProvider.NotNull(id);

                //
                var result = await provider.Get(
                    id: id,
                    includeBuilder: !useDefaultIncludes
                        ? null
                        : defaultIncludeBuilder,
                    cancellationToken: cancellationToken
                );

                //
                return Ok(result.ToDynamicObject());
            }
            catch (Exception ex)
            {
                //
                var result = GetExceptionActionResult(ex);
                return result;
            }
        }

        /// <summary>
        /// Get All Exists Items ...
        /// </summary>
        /// <param name="useDefaultOrders"></param>
        /// <param name="useDefaultIncludes"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        [HttpGet("")]
        public virtual async Task<ActionResult<IEnumerable<TDto>>> GetAll(
            [FromQuery] bool useDefaultOrders = false,
            [FromQuery] bool useDefaultIncludes = false,
            CancellationToken cancellationToken = default
        )
        {
            //
            try
            {
                //
                // Validate ...
                if (!ModelState.IsValid)
                {
                    XException.InvalidArgs.Throw();
                }

                //
                var result = await provider.GetAll(
                    orderBuilder: !useDefaultOrders
                        ? null
                        : defaultOrderBuilder,
                    includeBuilder: !useDefaultIncludes
                        ? null
                        : defaultIncludeBuilder,
                    cancellationToken: cancellationToken
                );

                //
                return Ok(result.ToDynamicObject());
            }
            catch (Exception ex)
            {
                //
                var result = GetExceptionActionResult(ex);
                return result;
            }
        }

        /// <summary>
        /// Find an item by providing a Conditional Expression ...
        /// </summary>
        /// <param name="query"></param>
        /// <param name="useDefaultIncludes"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        [HttpGet("Find/One")]
        public virtual async Task<ActionResult<TDto>> FindOne(
            [FromRoute] string query,
            [FromQuery] bool useDefaultIncludes = false,
            CancellationToken cancellationToken = default
        )
        {
            //
            try
            {
                //
                // Validate ...
                if (!ModelState.IsValid)
                {
                    XException.InvalidArgs.Throw();
                }
                await ValidationProvider
                    .GroupValidationBuilder()
                    .AddNotEmpty(query)
                    .ValidateGroupAsync();

                //
                var result = await provider.FindOne(
                    includeBuilder: !useDefaultIncludes
                        ? null
                        : defaultIncludeBuilder,
                    cancellationToken: cancellationToken,
                    predicate: x => x.PropValuesContains(query)
                );

                //
                return Ok(result.ToDynamicObject());
            }
            catch (Exception ex)
            {
                //
                var result = GetExceptionActionResult(ex);
                return result;
            }
        }

        /// <summary>
        /// Find a collection of Items by proving a Query Search ...
        /// </summary>
        /// <param name="query"></param>
        /// <param name="useDefaultOrders"></param>
        /// <param name="useDefaultIncludes"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        [HttpGet("Find/Many")]
        public virtual async Task<ActionResult<IEnumerable<TDto>>> FindMany(
            [FromRoute] string query,
            [FromQuery] bool useDefaultOrders = false,
            [FromQuery] bool useDefaultIncludes = false,
            CancellationToken cancellationToken = default
        )
        {
            //
            try
            {
                //
                // Validate ...
                if (!ModelState.IsValid)
                {
                    XException.InvalidArgs.Throw();
                }
                await ValidationProvider
                    .GroupValidationBuilder()
                    .AddNotEmpty(query)
                    .ValidateGroupAsync();

                //
                var result = await provider.FindMany(
                    orderBuilder: !useDefaultOrders
                        ? null
                        : defaultOrderBuilder,
                    includeBuilder: !useDefaultIncludes
                        ? null
                        : defaultIncludeBuilder,
                    cancellationToken: cancellationToken,
                    predicate: x => x.PropValuesContains(query)
                );

                //
                return Ok(result.ToDynamicObject());
            }
            catch (Exception ex)
            {
                //
                var result = GetExceptionActionResult(ex);
                return result;
            }
        }

        /// <summary>
        /// Retrieve Items based on XQuery Pagination structure ...
        /// </summary>
        /// <param name="query"></param>
        /// <param name="useDefaultOrders"></param>
        /// <param name="useDefaultIncludes"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        [HttpGet("Query")]
        public virtual async Task<ActionResult<XQueryResult<TDto>>> Query(
            [FromQuery] XQuery query,
            [FromQuery] bool useDefaultOrders = false,
            [FromQuery] bool useDefaultIncludes = false,
            CancellationToken cancellationToken = default
        )
        {
            //
            try
            {
                //
                // Validate ...
                if (!ModelState.IsValid)
                {
                    XException.InvalidArgs.Throw();
                }
                await ValidationProvider
                    .GroupValidationBuilder()
                    .AddNotNull(query)
                    .ValidateGroupAsync();

                //
                var result = await provider.Query(
                    query: query,
                    predicate: null,
                    orderBuilder: !useDefaultOrders
                        ? null
                        : defaultOrderBuilder,
                    includeBuilder: !useDefaultIncludes
                        ? null
                        : defaultIncludeBuilder,
                    cancellationToken: cancellationToken
                );

                //
                return Ok(result.ToDynamicObject());
            }
            catch (Exception ex)
            {
                //
                var result = GetExceptionActionResult(ex);
                return result;
            }
        }

        /// <summary>
        /// Retrieve Owned Items based on XQuery Pagination structure ...
        /// </summary>
        /// <param name="query"></param>
        /// <param name="useDefaultOrders"></param>
        /// <param name="useDefaultIncludes"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        [HttpGet("Query/Owned")]
        public virtual async Task<ActionResult<XQueryResult<TDto>>> QueryOwned(
            [FromQuery] XQuery query,
            [FromQuery] bool useDefaultOrders = false,
            [FromQuery] bool useDefaultIncludes = false,
            CancellationToken cancellationToken = default
        )
        {
            //
            try
            {
                //
                // Validate ...
                if (!ModelState.IsValid)
                {
                    XException.InvalidArgs.Throw();
                }
                await ValidationProvider
                    .GroupValidationBuilder()
                    .AddNotNull(query)
                    .ValidateGroupAsync();

                //
                var userInfo = await GetUserInfo();

                //
                var result = await provider.QueryOwned(
                    query: query,
                    predicate: null,
                    userInfo: userInfo,
                    orderBuilder: !useDefaultOrders
                        ? null
                        : defaultOrderBuilder,
                    includeBuilder: !useDefaultIncludes
                        ? null
                        : defaultIncludeBuilder,
                    cancellationToken: cancellationToken
                );

                //
                return Ok(result.ToDynamicObject());
            }
            catch (Exception ex)
            {
                //
                var result = GetExceptionActionResult(ex);
                return result;
            }
        }
        #endregion

        //
        #region Add/Update/Remove ...
        /// <summary>
        /// Add an item ...
        /// </summary>
        /// <param name="item"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        [HttpPost("")]
        public virtual async Task<ActionResult<TDto>> Add(
            [FromBody] TDto item,
            CancellationToken cancellationToken = default
        )
        {
            //
            try
            {
                //
                // Validate ...
                if (!ModelState.IsValid)
                {
                    XException.InvalidArgs.Throw();
                }
                await ValidationProvider
                    .GroupValidationBuilder()
                    .AddNotNull(item)
                    .ValidateGroupAsync();

                //
                var userInfo = await GetUserInfo();
                var connectionId = GetConnectionId();

                //
                var result = await provider.Add(
                    item: item,
                    userInfo: userInfo,
                    connectionId: connectionId,
                    cancellationToken: cancellationToken
                );

                //
                return Ok(result.ToDynamicObject());
            }
            catch (Exception ex)
            {
                //
                var result = GetExceptionActionResult(ex);
                return result;
            }
        }

        /// <summary>
        /// Update an item values ...
        /// </summary>
        /// <param name="id"></param>
        /// <param name="item"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        [HttpPut("{id}")]
        public virtual async Task<ActionResult<TDto>> Update(
            [FromRoute] TKey id,
            [FromBody] TDto item,
            CancellationToken cancellationToken = default
        )
        {
            //
            try
            {
                //
                // Validate ...
                if (!ModelState.IsValid)
                {
                    XException.InvalidArgs.Throw();
                }
                await ValidationProvider
                    .GroupValidationBuilder()
                    .AddNotNull(id)
                    .AddNotNull(item)
                    .ValidateGroupAsync();

                //
                var userInfo = await GetUserInfo();
                var connectionId = GetConnectionId();

                //
                var result = await provider.Update(
                    id: id,
                    item: item,
                    userInfo: userInfo,
                    connectionId: connectionId,
                    cancellationToken: cancellationToken
                );

                //
                return Ok(result.ToDynamicObject());
            }
            catch (Exception ex)
            {
                //
                var result = GetExceptionActionResult(ex);
                return result;
            }
        }

        /// <summary>
        /// Remove an Item ...
        /// </summary>
        /// <param name="id"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        [HttpDelete("{id}")]
        public virtual async Task<ActionResult<TDto>> Remove(
            [FromRoute] TKey id,
            CancellationToken cancellationToken = default
        )
        {
            //
            try
            {
                //
                // Validate ...
                if (!ModelState.IsValid)
                {
                    XException.InvalidArgs.Throw();
                }
                await ValidationProvider
                    .GroupValidationBuilder()
                    .AddNotNull(id)
                    .ValidateGroupAsync();

                //
                var userInfo = await GetUserInfo();
                var connectionId = GetConnectionId();

                //
                var result = await provider.Remove(
                    id: id,
                    userInfo: userInfo,
                    connectionId: connectionId,
                    cancellationToken: cancellationToken
                );

                //
                return Ok(result.ToDynamicObject());
            }
            catch (Exception ex)
            {
                //
                var result = GetExceptionActionResult(ex);
                return result;
            }
        }
        #endregion
        #endregion

        //
        #region Tag ...
        /// <summary>
        /// Attach Tag to Specified Item ...
        /// </summary>
        /// <param name="id"></param>
        /// <param name="tag"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        [HttpPost("{id}/tags/attach")]
        public virtual async Task<ActionResult> AttachTag(
            [FromRoute] TKey id,
            [FromBody] XBaseValueContainer<string> tag,
            CancellationToken cancellationToken = default
        )
        {
            //
            try
            {
                //
                // Validate Args ...
                if (!ModelState.IsValid)
                {
                    XException.InvalidArgs.Throw();
                }
                await ValidationProvider
                    .GroupValidationBuilder()
                    .AddNotNull(id)
                    .AddNotNull(tag)
                    .AddNotEmpty(tag.Value)
                    .ValidateGroupAsync();

                //
                var userInfo = await GetUserInfo();
                var connectionId = GetConnectionId();

                //
                // Get Result ...
                await tagProvided
                    .AttachTag(
                        id: id,
                        tag: tag.Value,
                        userInfo: userInfo,
                        connectionId: connectionId,
                        cancellationToken: cancellationToken
                    );

                //
                return Ok();
            }
            catch (Exception ex)
            {
                //
                var result = GetExceptionActionResult(ex);
                return result;
            }
        }

        /// <summary>
        /// Detach Tag of Specified Item ...
        /// </summary>
        /// <param name="id"></param>
        /// <param name="tag"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        [HttpPost("{id}/tags/detach")]
        public virtual async Task<ActionResult> DetachTag(
            [FromRoute] TKey id,
            [FromBody] XBaseValueContainer<string> tag,
            CancellationToken cancellationToken = default
        )
        {
            //
            try
            {
                //
                // Validate Args ...
                if (!ModelState.IsValid)
                {
                    XException.InvalidArgs.Throw();
                }
                await ValidationProvider
                    .GroupValidationBuilder()
                    .AddNotNull(id)
                    .AddNotNull(tag)
                    .AddNotEmpty(tag.Value)
                    .ValidateGroupAsync();

                //
                var userInfo = await GetUserInfo();
                var connectionId = GetConnectionId();

                //
                // Get Result ...
                await tagProvided
                    .DetachTag(
                        id: id,
                        tag: tag.Value,
                        userInfo: userInfo,
                        connectionId: connectionId,
                        cancellationToken: cancellationToken
                    );

                //
                return Ok();
            }
            catch (Exception ex)
            {
                //
                var result = GetExceptionActionResult(ex);
                return result;
            }
        }

        /// <summary>
        /// Attach Tags to Specified Item ...
        /// </summary>
        /// <param name="id"></param>
        /// <param name="tags"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        [HttpPost("{id}/tags/attachs")]
        public virtual async Task<ActionResult> AttachTags(
            [FromRoute] TKey id,
            [FromBody] XBaseRangeRequest<string> tags,
            CancellationToken cancellationToken = default
        )
        {
            //
            try
            {
                //
                // Validate Args ...
                if (!ModelState.IsValid)
                {
                    XException.InvalidArgs.Throw();
                }
                await ValidationProvider
                    .GroupValidationBuilder()
                    .AddNotNull(id)
                    .AddNotNull(tags)
                    .AddNotZeroChilds(tags.Items)
                    .ValidateGroupAsync();

                //
                var userInfo = await GetUserInfo();
                var connectionId = GetConnectionId();

                //
                // Get Result ...
                await tagProvided
                    .AttachTags(
                        id: id,
                        tags: tags.Items,
                        userInfo: userInfo,
                        connectionId: connectionId,
                        cancellationToken: cancellationToken
                    );

                //
                return Ok();
            }
            catch (Exception ex)
            {
                //
                var result = GetExceptionActionResult(ex);
                return result;
            }
        }

        /// <summary>
        /// Detach Tags of Specified Item ...
        /// </summary>
        /// <param name="id"></param>
        /// <param name="tags"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        [HttpPost("{id}/tags/detachs")]
        public virtual async Task<ActionResult> DetachTags(
            [FromRoute] TKey id,
            [FromBody] XBaseRangeRequest<string> tags = null,
            CancellationToken cancellationToken = default
        )
        {
            //
            try
            {
                //
                // Validate Args ...
                if (!ModelState.IsValid)
                {
                    XException.InvalidArgs.Throw();
                }
                await ValidationProvider
                    .GroupValidationBuilder()
                    .AddNotNull(id)
                    .ValidateGroupAsync();

                //
                var userInfo = await GetUserInfo();
                var connectionId = GetConnectionId();

                //
                // Get Result ...
                if (!tags.IsNull())
                {
                    //
                    await tagProvided
                        .DetachTags(
                            id: id,
                            tags: tags.Items,
                            userInfo: userInfo,
                            connectionId: connectionId,
                            cancellationToken: cancellationToken
                        );
                }
                else
                {
                    //
                    await tagProvided
                        .DetachTags(
                            id: id,
                            userInfo: userInfo,
                            connectionId: connectionId,
                            cancellationToken: cancellationToken
                        );
                }

                //
                return Ok();
            }
            catch (Exception ex)
            {
                //
                var result = GetExceptionActionResult(ex);
                return result;
            }
        }

        /// <summary>
        /// Get Specified Item Tags ...
        /// </summary>
        /// <param name="id"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        [HttpGet("{id}/tags")]
        public virtual async Task<ActionResult<IEnumerable<string>>> GetTags(
            [FromRoute] TKey id,
            CancellationToken cancellationToken = default
        )
        {
            //
            try
            {
                //
                // Validate Args ...
                if (!ModelState.IsValid)
                {
                    XException.InvalidArgs.Throw();
                }
                await ValidationProvider
                    .GroupValidationBuilder()
                    .AddNotNull(id)
                    .ValidateGroupAsync();

                //
                // Get Result ...
                var result = await tagProvided.GetTags(
                    id: id,
                    cancellationToken: cancellationToken
                );

                //
                return Ok(result.ToDynamicObject());
            }
            catch (Exception ex)
            {
                //
                var result = GetExceptionActionResult(ex);
                return result;
            }
        }
        #endregion
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xTagService\Controllers\XTagProvidedControllerBase.cs

using System;
using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Logging;
using xCommons.Configurations;
using xCommons.Extensions;
using xCommons.Providers;
using xExceptions.Constants;
using xIdentityService.Controllers;
using xIdentityService.Interfaces;
using xModels.Base;
using xPushService.Base;
using xTagService.Interfaces;

namespace xTagService.Controllers
{
    public abstract class XTagProvidedControllerBase<TEntity, TDto, TKey, THub> : XBaseIdentityApiV1Controller, IXTagProvidedController<TEntity, TDto, TKey, THub>
    where TEntity : XBaseEntity<TKey>
    where TDto : XBaseEntityDto<TKey>
    where THub : XBaseDtoHub<TEntity, TDto, TKey>
    {
        private readonly IXTagProvided<TEntity, TDto, TKey, THub> tagProvided;

        protected XTagProvidedControllerBase(
            ILogger<XTagProvidedControllerBase<TEntity, TDto, TKey, THub>> logger,
            XAppConfiguration appConfiguration,
            XValidationProvider validationProvider,
            IXIdentityProvider identityProvider,
            IXTagProvided<TEntity, TDto, TKey, THub> tagProvided
        ) : base(
            logger,
            appConfiguration,
            identityProvider,
            validationProvider
        )
        {
            this.tagProvided = tagProvided;
        }

        /// <summary>
        /// Attach Tag to Specified Item ...
        /// </summary>
        /// <param name="id"></param>
        /// <param name="tag"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        [HttpPost("{id}/tags/attach")]
        public virtual async Task<ActionResult> AttachTag(
            [FromRoute] TKey id,
            [FromBody] XBaseValueContainer<string> tag,
            CancellationToken cancellationToken = default
        )
        {
            //
            try
            {
                //
                // Validate Args ...
                if (!ModelState.IsValid)
                {
                    XException.InvalidArgs.Throw();
                }
                await ValidationProvider
                    .GroupValidationBuilder()
                    .AddNotNull(id)
                    .AddNotNull(tag)
                    .AddNotEmpty(tag.Value)
                    .ValidateGroupAsync();

                //
                var userInfo = await GetUserInfo();
                var connectionId = GetConnectionId();

                //
                // Get Result ...
                await tagProvided
                    .AttachTag(
                        id: id,
                        tag: tag.Value,
                        userInfo: userInfo,
                        connectionId: connectionId,
                        cancellationToken: cancellationToken
                    );

                //
                return Ok();
            }
            catch (Exception ex)
            {
                //
                var result = GetExceptionActionResult(ex);
                return result;
            }
        }

        /// <summary>
        /// Detach Tag of Specified Item ...
        /// </summary>
        /// <param name="id"></param>
        /// <param name="tag"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        [HttpPost("{id}/tags/detach")]
        public virtual async Task<ActionResult> DetachTag(
            [FromRoute] TKey id,
            [FromBody] XBaseValueContainer<string> tag,
            CancellationToken cancellationToken = default
        )
        {
            //
            try
            {
                //
                // Validate Args ...
                if (!ModelState.IsValid)
                {
                    XException.InvalidArgs.Throw();
                }
                await ValidationProvider
                    .GroupValidationBuilder()
                    .AddNotNull(id)
                    .AddNotNull(tag)
                    .AddNotEmpty(tag.Value)
                    .ValidateGroupAsync();

                //
                var userInfo = await GetUserInfo();
                var connectionId = GetConnectionId();

                //
                // Get Result ...
                await tagProvided
                    .DetachTag(
                        id: id,
                        tag: tag.Value,
                        userInfo: userInfo,
                        connectionId: connectionId,
                        cancellationToken: cancellationToken
                    );

                //
                return Ok();
            }
            catch (Exception ex)
            {
                //
                var result = GetExceptionActionResult(ex);
                return result;
            }
        }

        /// <summary>
        /// Attach Tags to Specified Item ...
        /// </summary>
        /// <param name="id"></param>
        /// <param name="tags"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        [HttpPost("{id}/tags/attachs")]
        public virtual async Task<ActionResult> AttachTags(
            [FromRoute] TKey id,
            [FromBody] XBaseRangeRequest<string> tags,
            CancellationToken cancellationToken = default
        )
        {
            //
            try
            {
                //
                // Validate Args ...
                if (!ModelState.IsValid)
                {
                    XException.InvalidArgs.Throw();
                }
                await ValidationProvider
                    .GroupValidationBuilder()
                    .AddNotNull(id)
                    .AddNotNull(tags)
                    .AddNotZeroChilds(tags.Items)
                    .ValidateGroupAsync();

                //
                var userInfo = await GetUserInfo();
                var connectionId = GetConnectionId();

                //
                // Get Result ...
                await tagProvided
                    .AttachTags(
                        id: id,
                        tags: tags.Items,
                        userInfo: userInfo,
                        connectionId: connectionId,
                        cancellationToken: cancellationToken
                    );

                //
                return Ok();
            }
            catch (Exception ex)
            {
                //
                var result = GetExceptionActionResult(ex);
                return result;
            }
        }

        /// <summary>
        /// Detach Tags of Specified Item ...
        /// </summary>
        /// <param name="id"></param>
        /// <param name="tags"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        [HttpPost("{id}/tags/detachs")]
        public virtual async Task<ActionResult> DetachTags(
            [FromRoute] TKey id,
            [FromBody] XBaseRangeRequest<string> tags = null,
            CancellationToken cancellationToken = default
        )
        {
            //
            try
            {
                //
                // Validate Args ...
                if (!ModelState.IsValid)
                {
                    XException.InvalidArgs.Throw();
                }
                await ValidationProvider
                    .GroupValidationBuilder()
                    .AddNotNull(id)
                    .ValidateGroupAsync();

                //
                var userInfo = await GetUserInfo();
                var connectionId = GetConnectionId();

                //
                // Get Result ...
                if (!tags.IsNull())
                {
                    //
                    await tagProvided
                        .DetachTags(
                            id: id,
                            tags: tags.Items,
                            userInfo: userInfo,
                            connectionId: connectionId,
                            cancellationToken: cancellationToken
                        );
                }
                else
                {
                    //
                    await tagProvided
                        .DetachTags(
                            id: id,
                            userInfo: userInfo,
                            connectionId: connectionId,
                            cancellationToken: cancellationToken
                        );
                }

                //
                return Ok();
            }
            catch (Exception ex)
            {
                //
                var result = GetExceptionActionResult(ex);
                return result;
            }
        }

        /// <summary>
        /// Get Specified Item Tags ...
        /// </summary>
        /// <param name="id"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        [HttpGet("{id}/tags")]
        public virtual async Task<ActionResult<IEnumerable<string>>> GetTags(
            [FromRoute] TKey id,
            CancellationToken cancellationToken = default
        )
        {
            //
            try
            {
                //
                // Validate Args ...
                if (!ModelState.IsValid)
                {
                    XException.InvalidArgs.Throw();
                }
                await ValidationProvider
                    .GroupValidationBuilder()
                    .AddNotNull(id)
                    .ValidateGroupAsync();

                //
                // Get Result ...
                var result = await tagProvided.GetTags(
                    id: id,
                    cancellationToken: cancellationToken
                );

                //
                return Ok(result.ToDynamicObject());
            }
            catch (Exception ex)
            {
                //
                var result = GetExceptionActionResult(ex);
                return result;
            }
        }
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xTagService\Controllers\XTagProviderControllerBase.cs

using System;
using System.Linq;
using Microsoft.EntityFrameworkCore.Query;
using Microsoft.Extensions.Logging;
using xCommons.Configurations;
using xCommons.Providers;
using xIdentityService.Interfaces;
using xPushService.Controllers;
using xTagService.Interfaces;
using xTagService.Models.Dtos;
using xTagService.Models.Entities;
using xTagService.Providers.Dtos;

namespace xTagService.Controllers
{
    public abstract class XTagProviderControllerBase : XBaseProvidedController<XTag, XTagDto, int, XTagDtoHub>, IXTagProviderController
    {
        protected XTagProviderControllerBase(
            ILogger<XTagProviderControllerBase> logger,
            XAppConfiguration appConfiguration,
            IXIdentityProvider identityProvider,
            XValidationProvider validationProvider,
            IXTagProvider provider,
            Func<IQueryable<XTag>, IOrderedQueryable<XTag>> defaultOrderBuilder = null,
            Func<IQueryable<XTag>, IIncludableQueryable<XTag, object>> defaultIncludeBuilder = null
        ) : base(
            logger,
            appConfiguration,
            identityProvider,
            validationProvider,
            provider,
            defaultOrderBuilder,
            defaultIncludeBuilder
        )
        { }
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xTagService\Controllers\XTagRepositoryControllerBase.cs

using System;
using System.Linq;
using Microsoft.EntityFrameworkCore.Query;
using Microsoft.Extensions.Logging;
using xCommons.Configurations;
using xCommons.Providers;
using xDataService.Controllers;
using xDataService.Interfaces;
using xTagService.Interfaces.Entities;
using xTagService.Models.Entities;

namespace xTagService.Controllers
{
    public abstract class XTagRepositoryControllerBase : XBaseRepositoryController<XTag, int>, IXBaseRepositoryController<XTag, int>
    {
        protected XTagRepositoryControllerBase(
            ILogger<XTagRepositoryControllerBase> logger, 
            XAppConfiguration appConfiguration, 
            XValidationProvider validationProvider, 
            IXTagRepository repository, 
            Func<IQueryable<XTag>, IOrderedQueryable<XTag>> defaultOrderBuilder = null, 
            Func<IQueryable<XTag>, IIncludableQueryable<XTag, object>> defaultIncludeBuilder = null
        ) : base(
            logger, 
            appConfiguration, 
            validationProvider, 
            repository, 
            defaultOrderBuilder, 
            defaultIncludeBuilder
        )
        { }
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xTagService\Controllers\XTagRepositoryProviderControllerBase.cs

using System;
using System.Linq;
using Microsoft.EntityFrameworkCore.Query;
using Microsoft.Extensions.Logging;
using xCommons.Configurations;
using xCommons.Providers;
using xIdentityService.Interfaces;
using xPushService.Controllers;
using xPushService.Interfaces;
using xTagService.Interfaces.Entities;
using xTagService.Models.Entities;
using xTagService.Providers.Entities;

namespace xTagService.Controllers
{
    public abstract class XTagRepositoryProviderControllerBase : XBaseRepositoryProviderController<XTag, int, XTagEntityHub>, IXBaseRepositoryProviderController<XTag, int, XTagEntityHub>
    {
        protected XTagRepositoryProviderControllerBase(
            ILogger<XTagRepositoryProviderControllerBase> logger, 
            XAppConfiguration appConfiguration, 
            IXIdentityProvider identityProvider, 
            XValidationProvider validationProvider, 
            IXTagRepositoryProvider provider, 
            Func<IQueryable<XTag>, IOrderedQueryable<XTag>> defaultOrderBuilder = null, 
            Func<IQueryable<XTag>, IIncludableQueryable<XTag, object>> defaultIncludeBuilder = null
        ) : base(
            logger, 
            appConfiguration, 
            identityProvider, 
            validationProvider, 
            provider, 
            defaultOrderBuilder, 
            defaultIncludeBuilder
        )
        { }
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xTagService\Controllers\XTagServiceControllerBase.cs

using System;
using System.Linq;
using Microsoft.EntityFrameworkCore.Query;
using Microsoft.Extensions.Logging;
using xCommons.Configurations;
using xCommons.Providers;
using xDataService.Controllers;
using xDataService.Interfaces;
using xTagService.Interfaces.Dtos;
using xTagService.Models.Dtos;
using xTagService.Models.Entities;

namespace xTagService.Controllers
{
    public abstract class XTagServiceControllerBase : XBaseServiceController<XTag, XTagDto, int>, IXBaseServiceController<XTag, XTagDto, int>
    {
        protected XTagServiceControllerBase(
            ILogger<XTagServiceControllerBase> logger,
            XAppConfiguration appConfiguration,
            XValidationProvider validationProvider,
            IXTagRepositoryService repositoryService,
            Func<IQueryable<XTag>, IOrderedQueryable<XTag>> defaultOrderBuilder = null,
            Func<IQueryable<XTag>, IIncludableQueryable<XTag, object>> defaultIncludeBuilder = null
        ) : base(
            logger,
            appConfiguration,
            validationProvider,
            repositoryService,
            defaultOrderBuilder,
            defaultIncludeBuilder
        )
        { }
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xTagService\Controllers\XTagServiceProviderControllerBase.cs

using System;
using System.Linq;
using Microsoft.EntityFrameworkCore.Query;
using Microsoft.Extensions.Logging;
using xCommons.Configurations;
using xCommons.Providers;
using xIdentityService.Interfaces;
using xPushService.Controllers;
using xPushService.Interfaces;
using xTagService.Interfaces.Dtos;
using xTagService.Models.Dtos;
using xTagService.Models.Entities;
using xTagService.Providers.Dtos;

namespace xTagService.Controllers
{
    public abstract class XTagServiceProviderControllerBase : XBaseServiceProviderController<XTag, XTagDto, int, XTagDtoHub>, IXBaseServiceProviderController<XTag, XTagDto, int, XTagDtoHub>
    {
        protected XTagServiceProviderControllerBase(
            ILogger<XTagServiceProviderControllerBase> logger,
            XAppConfiguration appConfiguration,
            IXIdentityProvider identityProvider,
            XValidationProvider validationProvider,
            IXTagServiceProvider provider,
            Func<IQueryable<XTag>, IOrderedQueryable<XTag>> defaultOrderBuilder = null,
            Func<IQueryable<XTag>, IIncludableQueryable<XTag, object>> defaultIncludeBuilder = null
        ) : base(
            logger,
            appConfiguration,
            identityProvider,
            validationProvider,
            provider,
            defaultOrderBuilder,
            defaultIncludeBuilder
        )
        { }
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xTagService\DI\XDIHelperExtension.cs

using System;
using Microsoft.AspNetCore.Builder;
using Microsoft.Extensions.DependencyInjection;
using xCommons.Extensions;
using xCommons.Helpers;
using xDataService.Constants;
using xDataService.Db;
using xDataService.DI;
using xDataService.Models;
using xExceptions.Constants;
using xPushService.DI;
using xPushService.Helpers;
using xTagService.Constants;
using xTagService.Helpers;
using xTagService.Interfaces;
using xTagService.Interfaces.Dtos;
using xTagService.Interfaces.Entities;
using xTagService.Providers;
using xTagService.Providers.Dtos;
using xTagService.Providers.Entities;

namespace xTagService.DI
{
    public static class XDIHelperExtension
    {
        /// <summary>
        /// Register Service ...
        /// </summary>
        /// <param name="services"></param>
        /// <param name="repositoryType"></param>
        /// <param name="lifeTime"></param>
        public static void AddXTagService(
            this IServiceCollection services,
            XRepositoryType repositoryType,
            ServiceLifetime lifeTime = ServiceLifetime.Scoped
        )
        {
            AddTagService(
                contextType: null,
                services: services,
                lifeTime: lifeTime,
                repositoryType: repositoryType
            );
        }

        /// <summary>
        /// Register Service ...
        /// </summary>
        /// <typeparam name="TContext"></typeparam>
        /// <param name="services"></param>
        /// <param name="repositoryType"></param>
        /// <param name="lifeTime"></param>
        public static void AddXTagService<TContext>(
            this IServiceCollection services,
            XRepositoryType repositoryType,
            ServiceLifetime lifeTime = ServiceLifetime.Scoped
        )
        where TContext : XDbContext
        {
            AddTagService(
                services: services,
                lifeTime: lifeTime,
                contextType: typeof(TContext),
                repositoryType: repositoryType
            );
        }

        /// <summary>
        /// Use XTagService Middleware ... 
        /// </summary>
        /// <param name="app"></param>
        /// <param name="isDevelopmentEnvironment"></param>
        public static void UseXTagService(
            this IApplicationBuilder app,
            bool isDevelopmentEnvironment = false
        )
        {
            //
            #region  Using XTag Hubs ...
            //
            var pushHelper = new XPushServiceHelper();

            //
            pushHelper.AddHub<XTagDtoHub>(XTagServiceConstants.XTagDtoHub);
            pushHelper.AddHub<XTagEntityHub>(XTagServiceConstants.XTagEntityHub);

            //
            app.UseXPushService(pushHelper);
            #endregion

            //
            // Using XTag Repository Descriptor ...
            if (!descriptor.IsNull())
            {
                //
                app.UseXRepository(
                    descriptor: descriptor,
                    isDevelopmentEnvironment: isDevelopmentEnvironment
                );
            }
        }

        //
        #region Private ...
        private static XRepositoryDescriptor descriptor = null;

        /// <summary>
        /// a LogTag for Service ...
        /// </summary>
        private static string XLogTag = XTagServiceConstants.XTagServiceDILogTag;

        /// <summary>
        /// print a log in Console ...
        /// </summary>
        /// <param name="message"></param>
        private static void Log(string message)
        {
            Console.WriteLine($"{XLogTag} => {message}");
        }

        /// <summary>
        /// Register Service ...
        /// </summary>
        /// <param name="services"></param>
        /// <param name="repositoryType"></param>
        /// <param name="contextType"></param>
        /// <param name="lifeTime"></param>
        private static void AddTagService(
            IServiceCollection services,
            XRepositoryType repositoryType,
            Type contextType = null,
            ServiceLifetime lifeTime = ServiceLifetime.Scoped
        )
        {
            //
            var exception = XException.InvalidArgs.ToException(); ;

            //
            // Services ...
            var isServicesExists = !services.IsNull();
            if (!isServicesExists)
            {
                //
                Log("Service Registration failed, services not provided ...");
                throw exception;
            }

            //
            // Lifetime ...
            var isLifetimeExists = !lifeTime.IsNull();
            if (!isLifetimeExists)
            {
                //
                Log("Service Registration failed, lifetime not provided ...");
                throw exception;
            }

            //
            // Validate Repository Type ...
            var isRepositoryTypeValid =
                (repositoryType == XRepositoryType.EF &&
                !contextType.IsNull()) ||
                ((repositoryType == XRepositoryType.Mongo ||
                    repositoryType == XRepositoryType.InMemory) &&
                contextType.IsNull());
            if (!isRepositoryTypeValid)
            {
                //
                Log("Service Registration failed, Invalid Repository Type and Context Type ...");
                throw exception;
            }

            //
            // Maske Instance of Repository Descriptor 
            // Based on Provided Type ...
            switch (repositoryType)
            {
                //
                case XRepositoryType.EF:
                    //
                    descriptor = typeof(XTagServiceHelper)
                        .InvokeGenericMethod<XRepositoryDescriptor>(
                            args: null,
                            runtimeType: contextType,
                            methodName: XTagServiceConstants.GetXTagEFRepositoryDescriptor
                    );
                    break;

                //
                case XRepositoryType.Mongo:
                    descriptor = XTagServiceHelper.GetXTagMongoRepositoryDescriptor();
                    break;

                //
                case XRepositoryType.InMemory:
                    descriptor = XTagServiceHelper.GetXTagInMemoryRepositoryDescriptor();
                    break;
            }

            //
            // Register XTag Repository Descriptor ...
            services.AddXRepository(
                lifeTime: lifeTime,
                descriptor: descriptor
            );

            //
            // Register Dto Services ...
            services.Add(
                new ServiceDescriptor(typeof(IXTagServiceProvider), typeof(XTagServiceProvider), lifeTime)
            );
            services.Add(
                new ServiceDescriptor(typeof(IXTagRepositoryService), typeof(XTagRepositoryService), lifeTime)
            );
            services.Add(
                new ServiceDescriptor(typeof(IXTagRepositoryProvider), typeof(XTagRepositoryProvider), lifeTime)
            );

            //
            services.Add(
                new ServiceDescriptor(typeof(IXTagProvider), typeof(XTagProvider), lifeTime)
            );

            //
            Log("Service Regitration Succeed ...");
        }
        #endregion        
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xTagService\Extensions\XModelExtensions.cs

using System.Collections.Generic;
using System.Linq;
using xCommons.Extensions;
using xDataService.Extensions;
using xDataService.Models;
using xTagService.Models.Dtos;
using xTagService.Models.Entities;

namespace xTagService.Extensions
{
    public static class XModelExtensions
    {
        /// <summary>
        /// Extract References of a Model ...
        /// </summary>
        /// <param name="source"></param>
        /// <returns></returns>
        public static IList<XReference<string>> GetReferences(
            this XTag source
        )
        {
            //
            var result = new List<XReference<string>>();

            //
            if (
                !source.IsNullOrDefault() &&
                !source.References.IsNullOrEmpty()
            )
            {
                //  
                result = source.References
                    .ParseXReferenceList<string>()
                    .ToList();
            }

            //
            return result;
        }

        /// <summary>
        /// Extract References of a Model ...
        /// </summary>
        /// <param name="source"></param>
        /// <returns></returns>
        public static IList<XReference<string>> GetReferences(
            this XTagDto source
        )
        {
            //
            var result = new List<XReference<string>>();

            //
            if (
                !source.IsNullOrDefault() &&
                !source.References.IsNullOrEmpty()
            )
            {
                //  
                result = source.References
                    .ParseXReferenceList<string>()
                    .ToList();
            }

            //
            return result;
        }

        /// <summary>
        /// Update a Model's References by Providing References List ...
        /// </summary>
        /// <param name="source"></param>
        /// <param name="references"></param>
        /// <param name="forceClean"></param>
        /// <returns></returns>
        public static XTag UpdateReferences(
            this XTag source,
            IList<XReference<string>> references,
            bool forceClean = true
        )
        {
            //
            XTag result = source;

            //
            if (!source.IsNullOrDefault())
            {
                //
                result = source;
                
                //
                if (forceClean)
                {
                    result.References = string.Empty;
                }

                //
                if (!references.IsNull() && 
                    references.HasChild())
                {
                    result.References = references.ToXReferenceString();
                }
            }

            //
            return result;
        }

        /// <summary>
        /// Update a Model's References by Providing References List ...
        /// </summary>
        /// <param name="source"></param>
        /// <param name="references"></param>
        /// <param name="forceClean"></param>
        /// <returns></returns>
        public static XTagDto UpdateReferences(
            this XTagDto source,
            IList<XReference<string>> references,
            bool forceClean = true
        )
        {
            //
            XTagDto result = source;

            //
            if (!source.IsNullOrDefault())
            {
                //
                result = source;
                
                //
                if (forceClean)
                {
                    result.References = string.Empty;
                }

                //
                if (!references.IsNull() && 
                    references.HasChild())
                {
                    result.References = references.ToXReferenceString();
                }
            }

            //
            return result;
        }
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xTagService\Helpers\XTagServiceHelper.cs

using GraphQL.Types;
using xDataService.Db;
using xDataService.Models;
using xDataService.Providers;
using xTagService.Interfaces;
using xTagService.Interfaces.Entities;
using xTagService.Models.Entities;
using xTagService.Providers.Entities;
using xTagService.Providers.GraphQL;

namespace xTagService.Helpers
{
    public static class XTagServiceHelper
    {
        //
        #region EF Repository Descriptor Provider(s) ...
        public static XEFRepositoryDescriptor<
            XTag,
            int,
            IXTagKeyGenerator,
            XTagKeyGenerator,
            IXTagRepositoryEvents,
            XTagRepositoryEvents,
            XTagGraphType,
            IntGraphType,
            XTagGraphQuery,
            IXTagGraphQLTypeHelper,
            XTagGraphQLTypeHelper,
            XTagGraphSchema,
            IXTagRepository,
            XTagEFRepository<TContext>,
            TContext
        > GetXTagEFRepositoryDescriptor<TContext>()
        where TContext : XDbContext
        {
            //
            var result = new XEFRepositoryDescriptor<
                XTag,
                int,
                IXTagKeyGenerator,
                XTagKeyGenerator,
                IXTagRepositoryEvents,
                XTagRepositoryEvents,
                XTagGraphType,
                IntGraphType,
                XTagGraphQuery,
                IXTagGraphQLTypeHelper,
                XTagGraphQLTypeHelper,
                XTagGraphSchema,
                IXTagRepository,
                XTagEFRepository<TContext>,
                TContext
            >();

            //
            return result;
        }

        public static XEFRepositoryDescriptor<
            XTag,
            int,
            IXTagKeyGenerator,
            XTagKeyGenerator,
            IXTagRepositoryEvents,
            XTagRepositoryEvents,
            XTagGraphType,
            IntGraphType,
            XTagGraphQuery,
            IXTagGraphQLTypeHelper,
            XTagGraphQLTypeHelper,
            XTagGraphSchema,
            IXTagRepository,
            XTagEFRepository<TContext>,
            TContext,
            IXTagSeeder,
            TSeederImplementation
        > GetXTagEFRepositoryDescriptor<TContext, TSeederImplementation>()
        where TContext : XDbContext
        where TSeederImplementation : XBaseDbSeeder<XTag, int>
        {
            //
            var result = new XEFRepositoryDescriptor<
                XTag,
                int,
                IXTagKeyGenerator,
                XTagKeyGenerator,
                IXTagRepositoryEvents,
                XTagRepositoryEvents,
                XTagGraphType,
                IntGraphType,
                XTagGraphQuery,
                IXTagGraphQLTypeHelper,
                XTagGraphQLTypeHelper,
                XTagGraphSchema,
                IXTagRepository,
                XTagEFRepository<TContext>,
                TContext,
                IXTagSeeder,
                TSeederImplementation
            >();

            //
            return result;
        }
        #endregion

        //
        #region Mongo Repository Descriptor Provider(s) ...
        public static XMongoRepositoryDescriptor<
            XTag,
            int,
            IXTagKeyGenerator,
            XTagKeyGenerator,
            IXTagRepositoryEvents,
            XTagRepositoryEvents,
            XTagGraphType,
            IntGraphType,
            XTagGraphQuery,
            IXTagGraphQLTypeHelper,
            XTagGraphQLTypeHelper,
            XTagGraphSchema,
            IXTagRepository,
            XTagMongoRepository
        > GetXTagMongoRepositoryDescriptor()
        {
            //
            var result = new XMongoRepositoryDescriptor<
                XTag,
                int,
                IXTagKeyGenerator,
                XTagKeyGenerator,
                IXTagRepositoryEvents,
                XTagRepositoryEvents,
                XTagGraphType,
                IntGraphType,
                XTagGraphQuery,
                IXTagGraphQLTypeHelper,
                XTagGraphQLTypeHelper,
                XTagGraphSchema,
                IXTagRepository,
                XTagMongoRepository
            >();

            //
            return result;
        }

        public static XMongoRepositoryDescriptor<
            XTag,
            int,
            IXTagKeyGenerator,
            XTagKeyGenerator,
            IXTagRepositoryEvents,
            XTagRepositoryEvents,
            XTagGraphType,
            IntGraphType,
            XTagGraphQuery,
            IXTagGraphQLTypeHelper,
            XTagGraphQLTypeHelper,
            XTagGraphSchema,
            IXTagRepository,
            XTagMongoRepository,
            IXTagSeeder,
            TSeederImplementation
        > GetXTagMongoRepositoryDescriptor<TSeederImplementation>()
        where TSeederImplementation : XBaseDbSeeder<XTag, int>
        {
            //
            var result = new XMongoRepositoryDescriptor<
                XTag,
                int,
                IXTagKeyGenerator,
                XTagKeyGenerator,
                IXTagRepositoryEvents,
                XTagRepositoryEvents,
                XTagGraphType,
                IntGraphType,
                XTagGraphQuery,
                IXTagGraphQLTypeHelper,
                XTagGraphQLTypeHelper,
                XTagGraphSchema,
                IXTagRepository,
                XTagMongoRepository,
                IXTagSeeder,
                TSeederImplementation
            >();

            //
            return result;
        }
        #endregion

        //
        #region InMemory Repository Descriptor Provider(s) ...
        public static XInMemoryRepositoryDescriptor<
            XTag,
            int,
            IXTagKeyGenerator,
            XTagKeyGenerator,
            IXTagRepositoryEvents,
            XTagRepositoryEvents,
            XTagGraphType,
            IntGraphType,
            XTagGraphQuery,
            IXTagGraphQLTypeHelper,
            XTagGraphQLTypeHelper,
            XTagGraphSchema,
            IXTagRepository,
            XTagInMemoryRepository
        > GetXTagInMemoryRepositoryDescriptor()
        {
            //
            var result = new XInMemoryRepositoryDescriptor<
                XTag,
                int,
                IXTagKeyGenerator,
                XTagKeyGenerator,
                IXTagRepositoryEvents,
                XTagRepositoryEvents,
                XTagGraphType,
                IntGraphType,
                XTagGraphQuery,
                IXTagGraphQLTypeHelper,
                XTagGraphQLTypeHelper,
                XTagGraphSchema,
                IXTagRepository,
                XTagInMemoryRepository
            >();

            //
            return result;
        }

        public static XInMemoryRepositoryDescriptor<
            XTag,
            int,
            IXTagKeyGenerator,
            XTagKeyGenerator,
            IXTagRepositoryEvents,
            XTagRepositoryEvents,
            XTagGraphType,
            IntGraphType,
            XTagGraphQuery,
            IXTagGraphQLTypeHelper,
            XTagGraphQLTypeHelper,
            XTagGraphSchema,
            IXTagRepository,
            XTagInMemoryRepository,
            IXTagSeeder,
            TSeederImplementation
        > GetXTagInMemoryRepositoryDescriptor<TSeederImplementation>()
        where TSeederImplementation : XBaseDbSeeder<XTag, int>
        {
            //
            var result = new XInMemoryRepositoryDescriptor<
                XTag,
                int,
                IXTagKeyGenerator,
                XTagKeyGenerator,
                IXTagRepositoryEvents,
                XTagRepositoryEvents,
                XTagGraphType,
                IntGraphType,
                XTagGraphQuery,
                IXTagGraphQLTypeHelper,
                XTagGraphQLTypeHelper,
                XTagGraphSchema,
                IXTagRepository,
                XTagInMemoryRepository,
                IXTagSeeder,
                TSeederImplementation
            >();

            //
            return result;
        }
        #endregion        
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xTagService\Interfaces\Dtos\IXTagDtoHub.cs

using xPushService.Interfaces;
using xTagService.Models.Dtos;
using xTagService.Models.Entities;

namespace xTagService.Interfaces.Dtos
{
    public interface IXTagDtoHub : IXBaseDtoHub<XTag, XTagDto, int>
    { }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xTagService\Interfaces\Dtos\IXTagRepositoryService.cs

using xDataService.Interfaces;
using xTagService.Models.Dtos;
using xTagService.Models.Entities;

namespace xTagService.Interfaces.Dtos
{
    public interface IXTagRepositoryService : IXBaseRepositoryService<XTag, XTagDto, int>
    { }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xTagService\Interfaces\Dtos\IXTagServiceProvider.cs

using xPushService.Interfaces;
using xTagService.Models.Dtos;
using xTagService.Models.Entities;
using xTagService.Providers.Dtos;

namespace xTagService.Interfaces.Dtos
{
    public interface IXTagServiceProvider : IXBaseDtoProvider<XTag, XTagDto, int, XTagDtoHub>
    { }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xTagService\Interfaces\Entities\IXTagEntityHub.cs

using xPushService.Interfaces;
using xTagService.Models.Entities;

namespace xTagService.Interfaces.Entities
{
    public interface IXTagEntityHub : IXBaseEntityHub<XTag, int>
    { }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xTagService\Interfaces\Entities\IXTagGraphQLTypeHelper.cs

using xDataService.Interfaces;
using xTagService.Models.Entities;

namespace xTagService.Interfaces.Entities
{
    public interface IXTagGraphQLTypeHelper : IXBaseGraphQLTypeHelper<XTag, int>
    { }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xTagService\Interfaces\Entities\IXTagKeyGenerator.cs

using xDataService.Interfaces;
using xTagService.Models.Entities;

namespace xTagService.Interfaces.Entities
{
    public interface IXTagKeyGenerator : IXKeyGenerator<XTag, int>
    { }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xTagService\Interfaces\Entities\IXTagRepository.cs

using xDataService.Interfaces;
using xTagService.Models.Entities;

namespace xTagService.Interfaces.Entities
{
    public interface IXTagRepository : IXBaseRepository<XTag, int>
    { }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xTagService\Interfaces\Entities\IXTagRepositoryEvents.cs

using xDataService.Interfaces;
using xTagService.Models.Entities;

namespace xTagService.Interfaces.Entities
{
    public interface IXTagRepositoryEvents : IXBaseRepositoryEvents<XTag>
    { }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xTagService\Interfaces\Entities\IXTagRepositoryProvider.cs

using xPushService.Interfaces;
using xTagService.Models.Entities;
using xTagService.Providers.Entities;

namespace xTagService.Interfaces.Entities
{
    public interface IXTagRepositoryProvider : IXBaseEntityProvider<XTag, int, XTagEntityHub>
    { }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xTagService\Interfaces\Entities\IXTagSeeder.cs

using xDataService.Interfaces;
using xTagService.Models.Entities;

namespace xTagService.Interfaces.Entities
{
    public interface IXTagSeeder : IXBaseDbSeeder<XTag, int>
    { }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xTagService\Interfaces\IXBaseProvidedHasTag.cs

using xModels.Base;
using xPushService.Base;
using xPushService.Interfaces;

namespace xTagService.Interfaces
{
    public interface IXBaseProvidedHasTag<TEntity, TDto, TKey, THub> : IXBaseProvided<TEntity, TDto, TKey, THub>, IXTagProvided<TEntity, TDto, TKey, THub>
    where TEntity : XBaseEntity<TKey>
    where TDto : XBaseEntityDto<TKey>
    where THub : XBaseDtoHub<TEntity, TDto, TKey>
    { }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xTagService\Interfaces\IXBaseProvidedHasTagController.cs

using xModels.Base;
using xPushService.Base;
using xPushService.Interfaces;

namespace xTagService.Interfaces
{
    public interface IXBaseProvidedHasTagController<TEntity, TDto, TKey, THub> : IXBaseProvidedController<TEntity, TDto, TKey, THub>, IXTagProvidedController<TEntity, TDto, TKey, THub>
    where TEntity : XBaseEntity<TKey>
    where TDto : XBaseEntityDto<TKey>
    where THub : XBaseDtoHub<TEntity, TDto, TKey>
    { }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xTagService\Interfaces\IXBaseTagProvider.cs

using System.Threading;
using System.Threading.Tasks;
using xDataService.Interfaces;
using xDataService.Models;
using xTagService.Models.Dtos;

namespace xTagService.Interfaces
{
    public interface IXBaseTagProvider<TKey> : IXBaseReferencedProvider<XTagDto, TKey>
    {
        //
        #region Tools ...
        /// <summary>
        /// Add Reference a Tag to Specific Provided ID ...
        /// </summary>
        /// <param name="tag"></param>
        /// <param name="providedForId"></param>
        /// <param name="connectionId"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        Task<bool> AddReference(
            string tag,
            TKey providedForId,
            string connectionId = null,
            CancellationToken cancellationToken = default
        );

        /// <summary>
        /// Add Reference a Tag to Specific XRefence<TKey/> ...
        /// </summary>
        /// <param name="tag"></param>
        /// <param name="reference"></param>
        /// <param name="connectionId"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        Task<bool> AddReference(
            string tag,
            XReference<TKey> reference,
            string connectionId = null,
            CancellationToken cancellationToken = default
        );

        /// <summary>
        /// Remove Reference a Tag for Specific Provided ID ...
        /// </summary>
        /// <param name="tag"></param>
        /// <param name="providedForId"></param>
        /// <param name="connectionId"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        Task<bool> RemoveReference(
            string tag,
            TKey providedForId,
            string connectionId = null,
            CancellationToken cancellationToken = default
        );

        /// <summary>
        /// Remove Reference a Tag for Specific XRefence<TKey/> ...
        /// </summary>
        /// <param name="tag"></param>
        /// <param name="reference"></param>
        /// <param name="connectionId"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        Task<bool> RemoveReference(
            string tag,
            XReference<TKey> reference,
            string connectionId = null,
            CancellationToken cancellationToken = default
        );
        #endregion        
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xTagService\Interfaces\IXTagProvided.cs

using System;
using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;
using xIdentityModels.Models;
using xModels.Base;
using xPushService.Base;

namespace xTagService.Interfaces
{
    /// <summary>
    /// a Tag Provided Service is a Model Provider Service which
    /// can Contains Tags ... 
    /// </summary>
    public interface IXTagProvided<TEntity, TDto, TKey, THub>
    where TEntity : XBaseEntity<TKey>
    where TDto : XBaseEntityDto<TKey>
    where THub : XBaseDtoHub<TEntity, TDto, TKey>
    {
        /// <summary>
        /// Attach Tag to Specified Item ...
        /// </summary>
        /// <param name="id"></param>
        /// <param name="tag"></param>
        /// <param name="userInfo"></param>
        /// <param name="connectionId"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        Task AttachTag(
            TKey id,
            string tag,
            XUserClaimsInfoDto userInfo = null,
            string connectionId = null,
            CancellationToken cancellationToken = default
        );

        /// <summary>
        /// Detach Tag of Specified Item ...
        /// </summary>
        /// <param name="id"></param>
        /// <param name="tag"></param>
        /// <param name="userInfo"></param>
        /// <param name="connectionId"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        Task DetachTag(
            TKey id,
            string tag,
            XUserClaimsInfoDto userInfo = null,
            string connectionId = null,
            CancellationToken cancellationToken = default
        );

        /// <summary>
        /// Attach Tags to Specified Item ...
        /// </summary>
        /// <param name="id"></param>
        /// <param name="tags"></param>
        /// <param name="userInfo"></param>
        /// <param name="connectionId"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        Task AttachTags(
            TKey id,
            IEnumerable<string> tags,
            XUserClaimsInfoDto userInfo = null,
            string connectionId = null,
            CancellationToken cancellationToken = default
        );

        /// <summary>
        /// Detach Tags of Specified Item ...
        /// </summary>
        /// <param name="id"></param>
        /// <param name="tags"></param>
        /// <param name="userInfo"></param>
        /// <param name="connectionId"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        Task DetachTags(
            TKey id,
            IEnumerable<string> tags,
            XUserClaimsInfoDto userInfo = null,
            string connectionId = null,
            CancellationToken cancellationToken = default
        );

        /// <summary>
        /// Detach all Attached Tags of Specified Item ...
        /// </summary>
        /// <param name="id"></param>
        /// <param name="userInfo"></param>
        /// <param name="connectionId"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        Task DetachTags(
            TKey id,
            XUserClaimsInfoDto userInfo = null,
            string connectionId = null,
            CancellationToken cancellationToken = default
        );

        /// <summary>
        /// Get Specified Item Tags ...
        /// </summary>
        /// <param name="id"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        Task<IEnumerable<string>> GetTags(
            TKey id,
            CancellationToken cancellationToken = default
        );        
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xTagService\Interfaces\IXTagProvidedController.cs

using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
using xModels.Base;
using xPushService.Base;

namespace xTagService.Interfaces
{
    public interface IXTagProvidedController<TEntity, TDto, TKey, THub>
    where TEntity : XBaseEntity<TKey>
    where TDto : XBaseEntityDto<TKey>
    where THub : XBaseDtoHub<TEntity, TDto, TKey>
    {
        /// <summary>
        /// Attach Tag to Specified Item ...
        /// </summary>
        /// <param name="id"></param>
        /// <param name="tag"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        [HttpPost("{id}/tags/attach")]
        Task<ActionResult> AttachTag(
            [FromRoute] TKey id,
            [FromBody] XBaseValueContainer<string> tag,
            CancellationToken cancellationToken = default
        );

        /// <summary>
        /// Detach Tag of Specified Item ...
        /// </summary>
        /// <param name="id"></param>
        /// <param name="tag"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        [HttpPost("{id}/tags/detach")]
        Task<ActionResult> DetachTag(
            [FromRoute] TKey id,
            [FromBody] XBaseValueContainer<string> tag,
            CancellationToken cancellationToken = default
        );

        /// <summary>
        /// Attach Tags to Specified Item ...
        /// </summary>
        /// <param name="id"></param>
        /// <param name="tags"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        [HttpPost("{id}/tags/attachs")]
        Task<ActionResult> AttachTags(
            [FromRoute] TKey id,
            [FromBody] XBaseRangeRequest<string> tags,
            CancellationToken cancellationToken = default
        );

        /// <summary>
        /// Detach Tags of Specified Item ...
        /// </summary>
        /// <param name="id"></param>
        /// <param name="tags"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        [HttpPost("{id}/tags/detachs")]
        Task<ActionResult> DetachTags(
            [FromRoute] TKey id,
            [FromBody] XBaseRangeRequest<string> tags = null,
            CancellationToken cancellationToken = default
        );

        /// <summary>
        /// Get Specified Item Tags ...
        /// </summary>
        /// <param name="id"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        [HttpGet("{id}/tags")]
        Task<ActionResult<IEnumerable<string>>> GetTags(
            [FromRoute] TKey id,
            CancellationToken cancellationToken = default
        );
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xTagService\Interfaces\IXTagProvider.cs

using xPushService.Interfaces;
using xTagService.Models.Dtos;
using xTagService.Models.Entities;
using xTagService.Providers.Dtos;

namespace xTagService.Interfaces
{
    public interface IXTagProvider : IXBaseProvided<XTag, XTagDto, int, XTagDtoHub>
    { }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xTagService\Interfaces\IXTagProviderController.cs

using xPushService.Interfaces;
using xTagService.Models.Dtos;
using xTagService.Models.Entities;
using xTagService.Providers.Dtos;

namespace xTagService.Interfaces
{
    public interface IXTagProviderController : IXBaseProvidedController<XTag, XTagDto, int, XTagDtoHub>
    { }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xTagService\Models\Dtos\XTagDto.cs

using xModels.Base;

namespace xTagService.Models.Dtos
{
    public class XTagDto : XBaseIntIDEntityDto
    {
        public string Tag { get; set; }
        public string References { get; set; } 
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xTagService\Models\Entities\XTag.cs

using System.ComponentModel.DataAnnotations;
using xModels.Base;

namespace xTagService.Models.Entities
{
    /// <summary>
    /// a Tag Model ...
    /// </summary>
    public class XTag : XBaseIntIDEntity
    {
        /// <summary>
        /// Tag Label ...
        /// </summary>
        /// <value></value>
        [Required]
        [StringLength(255)]
        public string Tag { get; set; }

        /// <summary>
        /// Comma Separated List Which Provides Pointer to Specified 
        /// Model for Describe ...
        /// </summary>
        /// <value></value>
        public string References { get; set; }        
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xTagService\Providers\Dtos\XTagDtoHub.cs

using Microsoft.Extensions.Logging;
using xPushService.Base;
using xTagService.Interfaces.Dtos;
using xTagService.Models.Dtos;
using xTagService.Models.Entities;

namespace xTagService.Providers.Dtos
{
    public class XTagDtoHub : XBaseDtoHub<XTag, XTagDto, int>, IXTagDtoHub
    {
        public XTagDtoHub(
            ILogger<XTagDtoHub> logger
        ) : base(logger)
        { }
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xTagService\Providers\Dtos\XTagRepositoryService.cs

using System.Collections.Generic;
using AutoMapper;
using xDataService.Providers;
using xTagService.Interfaces.Dtos;
using xTagService.Interfaces.Entities;
using xTagService.Models.Dtos;
using xTagService.Models.Entities;

namespace xTagService.Providers.Dtos
{
    public class XTagRepositoryService : XBaseRepositoryService<XTag, XTagDto, int>, IXTagRepositoryService
    {
        public XTagRepositoryService(
            IXTagRepository repository,
            IEnumerable<Profile> mapperProfiles = null
        ) : base(
            repository,
            mapperProfiles
        )
        { }
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xTagService\Providers\Dtos\XTagServiceProvider.cs

using Microsoft.AspNetCore.SignalR;
using xDataService.Configuration;
using xIdentityService.Interfaces;
using xPushService.Base;
using xTagService.Interfaces.Dtos;
using xTagService.Models.Dtos;
using xTagService.Models.Entities;

namespace xTagService.Providers.Dtos
{
    public class XTagServiceProvider : XBaseDtoProvider<XTag, XTagDto, int, XTagDtoHub>, IXTagServiceProvider
    {
        public XTagServiceProvider(
            IHubContext<XTagDtoHub> hub,
            XDataServiceConfiguration dataConfiguration,
            IXTagRepositoryService service,
            IXIdentityProvider identityProvider = null
        ) : base(
            hub,
            dataConfiguration,
            service,
            identityProvider
        )
        { }
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xTagService\Providers\Entities\XTagEFRepository.cs

using xDataService.Configuration;
using xDataService.Db;
using xDataService.Interfaces;
using xDataService.Providers;
using xTagService.Interfaces.Entities;
using xTagService.Models.Entities;

namespace xTagService.Providers.Entities
{
    public class XTagEFRepository<TContext> : XBaseEFRepository<XTag, int, TContext>, IXTagRepository
    where TContext : XDbContext
    {
        public XTagEFRepository(
            IXUnitOfWorks<TContext> unitOfWorks,
            XDataServiceConfiguration configuration,
            IXTagKeyGenerator keyGenerator = null,
            IXTagRepositoryEvents baseRepositoryEvents = null
        ) : base(
            unitOfWorks,
            configuration,
            keyGenerator,
            baseRepositoryEvents
        )
        { }
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xTagService\Providers\Entities\XTagEntityHub.cs

using Microsoft.Extensions.Logging;
using xPushService.Base;
using xTagService.Interfaces.Entities;
using xTagService.Models.Entities;

namespace xTagService.Providers.Entities
{
    public class XTagEntityHub : XBaseEntityHub<XTag, int>, IXTagEntityHub
    {
        public XTagEntityHub(
            ILogger<XTagEntityHub> logger
        ) : base(logger)
        { }
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xTagService\Providers\Entities\XTagInMemoryRepository.cs

using xDataService.Configuration;
using xDataService.Providers;
using xTagService.Interfaces.Entities;
using xTagService.Models.Entities;

namespace xTagService.Providers.Entities
{
    public class XTagInMemoryRepository : XBaseInMemoryRepository<XTag, int>, IXTagRepository
    {
        public XTagInMemoryRepository(
            XDataServiceConfiguration configuration,
            IXTagKeyGenerator keyGenerator = null,
            IXTagRepositoryEvents baseRepositoryEvents = null
        ) : base(
            configuration,
            keyGenerator,
            baseRepositoryEvents
        )
        { }
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xTagService\Providers\Entities\XTagKeyGenerator.cs

using xDataService.Providers;
using xTagService.Interfaces.Entities;
using xTagService.Models.Entities;

namespace xTagService.Providers.Entities
{
    public class XTagKeyGenerator : XIntKeyGenerator<XTag>, IXTagKeyGenerator
    { }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xTagService\Providers\Entities\XTagMongoRepository.cs

using xDataService.Configuration;
using xDataService.Providers;
using xTagService.Interfaces.Entities;
using xTagService.Models.Entities;

namespace xTagService.Providers.Entities
{
    public class XTagMongoRepository : XBaseMongoRepository<XTag, int>, IXTagRepository
    {
        public XTagMongoRepository(
            XDataBaseConfiguration dbConfiguration,
            XDataServiceConfiguration configuration,
            string collectionName = null,
            IXTagKeyGenerator keyGenerator = null,
            IXTagRepositoryEvents baseRepositoryEvents = null
        ) : base(
            dbConfiguration,
            configuration,
            collectionName,
            keyGenerator,
            baseRepositoryEvents
        )
        { }
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xTagService\Providers\Entities\XTagRepositoryEvents.cs

using xDataService.Providers;
using xTagService.Interfaces.Entities;
using xTagService.Models.Entities;

namespace xTagService.Providers.Entities
{
    public class XTagRepositoryEvents : XBaseRepositoryEvents<XTag>, IXTagRepositoryEvents
    { }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xTagService\Providers\Entities\XTagRepositoryProvider.cs

using Microsoft.AspNetCore.SignalR;
using xDataService.Configuration;
using xIdentityService.Interfaces;
using xPushService.Base;
using xTagService.Interfaces.Entities;
using xTagService.Models.Entities;

namespace xTagService.Providers.Entities
{
    public class XTagRepositoryProvider : XBaseEntityProvider<XTag, int, XTagEntityHub>, IXTagRepositoryProvider
    {
        public XTagRepositoryProvider(
            IHubContext<XTagEntityHub> hub,
            IXTagRepository repository,
            XDataServiceConfiguration dataConfiguration,
            IXIdentityProvider identityProvider = null
        ) : base(
            hub,
            repository,
            dataConfiguration,
            identityProvider
        )
        { }
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xTagService\Providers\Entities\XTagSeederBase.cs

using xDataService.Configuration;
using xDataService.Providers;
using xTagService.Interfaces.Entities;
using xTagService.Models.Entities;

namespace xTagService.Providers.Entities
{
    public abstract class XTagSeederBase : XBaseDbSeeder<XTag, int>, IXTagSeeder
    {
        protected XTagSeederBase(
            string entity,
            string database,
            IXTagRepository repository,
            XDataServiceConfiguration dataServiceConfiguration
        ) : base(
            entity,
            database,
            repository,
            dataServiceConfiguration
        )
        { }
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xTagService\Providers\GraphQL\XTagGraphQLTypeHelper.cs

using xDataService.Configuration;
using xDataService.GraphQL;
using xTagService.Constants;
using xTagService.Interfaces.Entities;
using xTagService.Models.Entities;

namespace xTagService.Providers.GraphQL
{
    public class XTagGraphQLTypeHelper : XBaseGraphQLTypeHelper<XTag, int>, IXTagGraphQLTypeHelper
    {
        public XTagGraphQLTypeHelper(
            XDataServiceConfiguration configuration
        ) : base(configuration)
        { }

        public override string GetInQueryCollectionName()
        {
            return XTagServiceConstants.XTagCollectionName;
        }

        public override string GetInQuerySingleName()
        {
            return XTagServiceConstants.XTagSingleName;
        }
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xTagService\Providers\GraphQL\XTagGraphQuery.cs

using GraphQL.Types;
using xDataService.Configuration;
using xDataService.GraphQL;
using xTagService.Interfaces.Entities;
using xTagService.Models.Entities;

namespace xTagService.Providers.GraphQL
{
    public class XTagGraphQuery : XBaseGraphQLQuery<XTag, int, XTagGraphType, IntGraphType>
    {
        public XTagGraphQuery(
            XDataServiceConfiguration configuration,
            IXTagRepository repository,
            IXTagGraphQLTypeHelper helper
        ) : base(
            configuration,
            repository,
            helper
        )
        { }
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xTagService\Providers\GraphQL\XTagGraphSchema.cs

using System;
using GraphQL.Types;

namespace xTagService.Providers.GraphQL
{
    public class XTagGraphSchema : Schema
    {
        public XTagGraphSchema(IServiceProvider services) : base(services)
        {
            Query = (XTagGraphQuery)services.GetService(typeof(XTagGraphQuery));
        }

    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xTagService\Providers\GraphQL\XTagGraphType.cs

using xDataService.GraphQL;
using xTagService.Models.Entities;

namespace xTagService.Providers.GraphQL
{
    public class XTagGraphType : XBaseGraphObjectType<XTag, int>
    {
        public XTagGraphType() : base()
        {
            Field(x => x.Tag);
            Field(x => x.References);
        }
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xTagService\Providers\XBaseProvidedHasTag.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using xCommons.Extensions;
using xIdentityModels.Models;
using xModels.Base;
using xPushService.Base;
using xPushService.Interfaces;
using xTagService.Interfaces;
using xIdentityModels.Extensions;
using System.Threading;
using xExceptions.Constants;
using System.Linq.Expressions;
using Microsoft.EntityFrameworkCore.Query;
using xModels.Dtos;

namespace xTagService.Providers
{
    public abstract class XBaseProvidedHasTag<TEntity, TDto, TKey, THub> : IXBaseProvidedHasTag<TEntity, TDto, TKey, THub>
    where TEntity : XBaseEntity<TKey>
    where TDto : XBaseEntityDto<TKey>
    where THub : XBaseDtoHub<TEntity, TDto, TKey>
    {
        private readonly string[] permittedRoles;
        private readonly IXBaseTagProvider<TKey> tagProvider;
        private readonly IXBaseDtoProvider<TEntity, TDto, TKey, THub> provider;

        protected XBaseProvidedHasTag(
            IXBaseTagProvider<TKey> tagProvider,
            IXBaseDtoProvider<TEntity, TDto, TKey, THub> provider,
            string[] permittedRoles = null
        )
        {
            this.provider = provider;
            this.tagProvider = tagProvider;
            this.permittedRoles = permittedRoles;
        }

        /// <summary>
        /// Check an Items is Owned for User or not ...
        /// </summary>
        /// <param name="item"></param>
        /// <param name="userInfo"></param>
        /// <returns></returns>
        public abstract bool IsOwned(
            TDto item,
            XUserClaimsInfoDto userInfo
        );
        public abstract bool IsOwned(
            TEntity item,
            XUserClaimsInfoDto userInfo
        );

        /// <summary>
        /// Check User Has Permission for Manipulate Data or not ...
        /// </summary>
        /// <param name="userInfo"></param>
        /// <returns></returns>
        public bool HasPermision(
            XUserClaimsInfoDto userInfo
        )
        {
            //
            var result =
                !userInfo.IsNullOrDefault() &&
                userInfo.HasAccess(permittedRoles);

            //
            return result;
        }

        //
        #region Tag ...
        /// <summary>
        /// Attach Tag to Specified Item ...
        /// </summary>
        /// <param name="id"></param>
        /// <param name="tag"></param>
        /// <param name="userInfo"></param>
        /// <param name="connectionId"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public virtual async Task AttachTag(
            TKey id,
            string tag,
            XUserClaimsInfoDto userInfo = null,
            string connectionId = null,
            CancellationToken cancellationToken = default
        )
        {
            //
            // Validate ...
            var isValid =
                !id.IsNull() &&
                !tag.IsNullOrEmpty() &&
                !userInfo.IsNullOrDefault();
            if (!isValid)
            {
                XException.InvalidArgs.Throw();
            }

            //
            var item = await provider.GetAsync(
                id: id,
                includeBuilder: null,
                ignoreSoftDeleteds: true,
                cancellationToken: cancellationToken
            );
            isValid =
                !item.IsNullOrDefault() &&
                (IsOwned(item, userInfo) ||
                HasPermision(userInfo));
            if (!isValid)
            {
                XException.NotAllowed.Throw();
            }

            //
            try
            {
                //
                await tagProvider.AddReference(
                    tag: tag,
                    providedForId: id,
                    connectionId: connectionId,
                    cancellationToken: cancellationToken
                );
            }
            catch { }
        }

        /// <summary>
        /// Detach Tag fro Specified Item ...
        /// </summary>
        /// <param name="id"></param>
        /// <param name="tag"></param>
        /// <param name="userInfo"></param>
        /// <param name="connectionId"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public virtual async Task DetachTag(
            TKey id,
            string tag,
            XUserClaimsInfoDto userInfo = null,
            string connectionId = null,
            CancellationToken cancellationToken = default
        )
        {
            //
            // Validate ...
            var isValid =
                !id.IsNull() &&
                !tag.IsNullOrEmpty() &&
                !userInfo.IsNullOrDefault();
            if (!isValid)
            {
                XException.InvalidArgs.Throw();
            }

            //
            var item = await provider.GetAsync(
                id: id,
                includeBuilder: null,
                ignoreSoftDeleteds: true,
                cancellationToken: cancellationToken
            );
            isValid =
                !item.IsNullOrDefault() &&
                (IsOwned(item, userInfo) ||
                HasPermision(userInfo));
            if (!isValid)
            {
                XException.NotAllowed.Throw();
            }

            //
            try
            {
                //
                await tagProvider.RemoveReference(
                    tag: tag,
                    providedForId: id,
                    connectionId: connectionId,
                    cancellationToken: cancellationToken
                );
            }
            catch { }
        }

        /// <summary>
        /// Attach Tags for Specified Item ...
        /// </summary>
        /// <param name="id"></param>
        /// <param name="tags"></param>
        /// <param name="userInfo"></param>
        /// <param name="connectionId"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public virtual async Task AttachTags(
            TKey id,
            IEnumerable<string> tags,
            XUserClaimsInfoDto userInfo = null,
            string connectionId = null,
            CancellationToken cancellationToken = default
        )
        {
            //
            // Validate ...
            var isValid =
                !id.IsNull() &&
                !tags.IsNull() &&
                tags.HasChild();
            if (!isValid)
            {
                XException.InvalidArgs.Throw();
            }

            //
            // Loop through Tags ...
            foreach (var tag in tags)
            {
                //
                // Check Cancellation Token ...
                if (cancellationToken.IsCancellationRequested)
                {
                    break;
                }

                //
                await AttachTag(
                    id: id,
                    tag: tag,
                    userInfo: userInfo,
                    connectionId: connectionId,
                    cancellationToken: cancellationToken
                );
            }
        }

        /// <summary>
        /// Detach Tags for Specified Item ...
        /// </summary>
        /// <param name="id"></param>
        /// <param name="tags"></param>
        /// <param name="userInfo"></param>
        /// <param name="connectionId"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public virtual async Task DetachTags(
            TKey id,
            IEnumerable<string> tags,
            XUserClaimsInfoDto userInfo = null,
            string connectionId = null,
            CancellationToken cancellationToken = default
        )
        {
            //
            // Validate ...
            var isValid =
                !id.IsNull() &&
                !tags.IsNull() &&
                tags.HasChild();
            if (!isValid)
            {
                XException.InvalidArgs.Throw();
            }

            //
            // Loop through Tags ...
            foreach (var tag in tags)
            {
                //
                // Check Cancellation Token ...
                if (cancellationToken.IsCancellationRequested)
                {
                    break;
                }

                //
                await DetachTag(
                    id: id,
                    tag: tag,
                    userInfo: userInfo,
                    connectionId: connectionId,
                    cancellationToken: cancellationToken
                );
            }
        }

        /// <summary>
        /// Detach all Attached Tags for Specified Item ...
        /// </summary>
        /// <param name="id"></param>
        /// <param name="userInfo"></param>
        /// <param name="connectionId"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public virtual async Task DetachTags(
            TKey id,
            XUserClaimsInfoDto userInfo = null,
            string connectionId = null,
            CancellationToken cancellationToken = default
        )
        {
            //
            // Validate ...
            var isValid =
                !id.IsNull();
            if (!isValid)
            {
                XException.InvalidArgs.Throw();
            }

            //
            var item = await provider.GetAsync(
                id: id,
                includeBuilder: null,
                ignoreSoftDeleteds: true,
                cancellationToken: cancellationToken
            );
            isValid =
                !item.IsNullOrDefault() &&
                (IsOwned(item, userInfo) ||
                HasPermision(userInfo));
            if (!isValid)
            {
                XException.NotAllowed.Throw();
            }

            //
            try
            {
                //
                await tagProvider.RemoveReferences(
                    providedForId: id,
                    connectionId: connectionId,
                    cancellationToken: cancellationToken
                );
            }
            catch { }
        }

        /// <summary>
        /// Get Specified Model's Item ...
        /// </summary>
        /// <param name="id"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public virtual async Task<IEnumerable<string>> GetTags(
            TKey id,
            CancellationToken cancellationToken = default
        )
        {
            //
            // Validate ...
            var isValid = !id.IsNull();
            if (!isValid)
            {
                XException.InvalidArgs.Throw();
            }

            //
            isValid = await provider.IsExistsAsync(
                id: id,
                ignoreSoftDeleteds: true,
                cancellationToken: cancellationToken
            );
            if (!isValid)
            {
                XException.NotFound.Throw();
            }

            //
            var result = (await tagProvider.GetAllReferences(
                providedForId: id,
                cancellationToken: cancellationToken
            ))
            .Select(x => x.Tag)
            .Distinct()
            .ToList();

            //
            return result;
        }
        #endregion

        //
        #region Provided ...
        /// <summary>
        /// Get Specified Item by ID ...
        /// </summary>
        /// <param name="id"></param>
        /// <param name="includeBuilder"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public virtual async Task<TDto> Get(
            TKey id,
            Func<IQueryable<TEntity>, IIncludableQueryable<TEntity, object>> includeBuilder = null,
            CancellationToken cancellationToken = default
        )
        {
            //
            var result = await provider.GetAsync(
                id: id,
                includeBuilder: null,
                ignoreSoftDeleteds: true,
                cancellationToken: cancellationToken
            );

            //
            return result;
        }

        /// <summary>
        /// Get All Exists Items ...
        /// </summary>
        /// <param name="orderBuilder"></param>
        /// <param name="includeBuilder"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public virtual async Task<IEnumerable<TDto>> GetAll(
            Func<IQueryable<TEntity>, IOrderedQueryable<TEntity>> orderBuilder = null,
            Func<IQueryable<TEntity>, IIncludableQueryable<TEntity, object>> includeBuilder = null,
            CancellationToken cancellationToken = default
        )
        {
            //
            var result = await provider.GetAllAsync(
                ignoreSoftDeleteds: true,
                orderBuilder: orderBuilder,
                includeBuilder: includeBuilder,
                cancellationToken: cancellationToken
            );

            //
            return result;
        }

        /// <summary>
        /// find an item by providing a Conditional Expression ...
        /// </summary>
        /// <param name="predicate"></param>
        /// <param name="includeBuilder"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public virtual async Task<TDto> FindOne(
            Expression<Func<TEntity, bool>> predicate,
            Func<IQueryable<TEntity>, IIncludableQueryable<TEntity, object>> includeBuilder = null,
            CancellationToken cancellationToken = default
        )
        {
            //
            var result = await provider.FindOneAsync(
                predicate: predicate,
                ignoreSoftDeleteds: true,
                includeBuilder: includeBuilder,
                cancellationToken: cancellationToken
            );

            //
            return result;
        }

        /// <summary>
        /// find a collection of Items by proving a Conditional Expression ...
        /// </summary>
        /// <param name="predicate"></param>
        /// <param name="orderBuilder"></param>
        /// <param name="includeBuilder"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public virtual async Task<IEnumerable<TDto>> FindMany(
            Expression<Func<TEntity, bool>> predicate,
            Func<IQueryable<TEntity>, IOrderedQueryable<TEntity>> orderBuilder = null,
            Func<IQueryable<TEntity>, IIncludableQueryable<TEntity, object>> includeBuilder = null,
            CancellationToken cancellationToken = default
        )
        {
            //
            var result = await provider.FindManyAsync(
                predicate: predicate,
                ignoreSoftDeleteds: true,
                orderBuilder: orderBuilder,
                includeBuilder: includeBuilder,
                cancellationToken: cancellationToken
            );

            //
            return result;
        }

        /// <summary>
        /// retrieve Items based on XQuery Pagination structure ...
        /// </summary>
        /// <param name="query"></param>
        /// <param name="predicate"></param>
        /// <param name="orderBuilder"></param>
        /// <param name="includeBuilder"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public virtual async Task<XQueryResult<TDto>> Query(
            XQuery query,
            Expression<Func<TEntity, bool>> predicate = null,
            Func<IQueryable<TEntity>, IOrderedQueryable<TEntity>> orderBuilder = null,
            Func<IQueryable<TEntity>, IIncludableQueryable<TEntity, object>> includeBuilder = null,
            CancellationToken cancellationToken = default
        )
        {
            //
            var result = await provider.QueryAsync(
                query: query,
                predicate: predicate,
                ignoreSoftDeleteds: true,
                orderBuilder: orderBuilder,
                includeBuilder: includeBuilder,
                cancellationToken: cancellationToken
            );

            //
            return result;
        }

        /// <summary>
        /// retrieve Owned Items based on XQuery Pagination structure ...
        /// if supported ...
        /// </summary>
        /// <param name="query"></param>
        /// <param name="userInfo"></param>
        /// <param name="predicate"></param>
        /// <param name="orderBuilder"></param>
        /// <param name="includeBuilder"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public virtual async Task<XQueryResult<TDto>> QueryOwned(
            XQuery query,
            XUserClaimsInfoDto userInfo = null,
            Expression<Func<TEntity, bool>> predicate = null,
            Func<IQueryable<TEntity>, IOrderedQueryable<TEntity>> orderBuilder = null,
            Func<IQueryable<TEntity>, IIncludableQueryable<TEntity, object>> includeBuilder = null,
            CancellationToken cancellationToken = default
        )
        {
            //
            Expression<Func<TEntity, bool>> predicateor = null;
            if (!predicate.IsNull())
            {
                //
                var predicateFnc = predicate.Compile();
                predicateor = x =>
                    predicateFnc(x) &&
                    IsOwned(x, userInfo);
            }
            else
            {
                predicateor = x => IsOwned(x, userInfo);
            }

            //
            var result = await provider.QueryAsync(
                query: query,
                predicate: predicateor,
                ignoreSoftDeleteds: true,
                orderBuilder: orderBuilder,
                includeBuilder: includeBuilder,
                cancellationToken: cancellationToken
            );

            //
            return result;
        }

        /// <summary>
        /// Add an item values ...
        /// </summary>
        /// <param name="item"></param>
        /// <param name="userInfo"></param>
        /// <param name="connectionId"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public virtual async Task<TDto> Add(
            TDto item,
            XUserClaimsInfoDto userInfo = null,
            string connectionId = null,
            CancellationToken cancellationToken = default
        )
        {
            //
            var result = await provider.AddAsync(
                item: item,
                saveChanges: true,
                connectionId: connectionId,
                cancellationToken: cancellationToken
            );

            //
            return result;
        }

        /// <summary>
        /// Update an item values ...
        /// </summary>
        /// <param name="id"></param>
        /// <param name="item"></param>
        /// <param name="userInfo"></param>
        /// <param name="connectionId"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public virtual async Task<TDto> Update(
            TKey id,
            TDto item,
            XUserClaimsInfoDto userInfo = null,
            string connectionId = null,
            CancellationToken cancellationToken = default
        )
        {
            //
            // Check Permission ...
            var hasPermission =
                IsOwned(item, userInfo) ||
                HasPermision(userInfo);
            if (!hasPermission)
            {
                XException.NotAllowed.Throw();
            }

            //
            var result = await provider.UpdateAsync(
                id: id,
                item: item,
                saveChanges: true,
                connectionId: connectionId,
                cancellationToken: cancellationToken
            );

            //
            return result;
        }

        /// <summary>
        /// remove an Item ...
        /// </summary>
        /// <param name="id"></param>
        /// <param name="userInfo"></param>
        /// <param name="connectionId"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public virtual async Task<TDto> Remove(
            TKey id,
            XUserClaimsInfoDto userInfo = null,
            string connectionId = null,
            CancellationToken cancellationToken = default
        )
        {
            //
            // Check Permission ...
            var item = await Get(
                id: id,
                cancellationToken: cancellationToken
            );
            var hasPermission =
                IsOwned(item, userInfo) ||
                HasPermision(userInfo);
            if (!hasPermission)
            {
                XException.NotAllowed.Throw();
            }

            //
            var result = await provider.RemoveAsync(
                id: id,
                saveChanges: true,
                softDelete: false,
                connectionId: connectionId,
                cancellationToken: cancellationToken
            );

            //
            return result;
        }

        /// <summary>
        /// count all exists Items ...
        /// </summary>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public virtual async Task<int> Count(
            CancellationToken cancellationToken = default
        )
        {
            //
            var result = await provider.CountAsync(
                ignoreSoftDeleteds: true,
                cancellationToken: cancellationToken
            );

            //
            return result;
        }

        /// <summary>
        /// Check an Item exists or not ...
        /// </summary>
        /// <param name="id"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public virtual async Task<bool> IsExists(
            TKey id,
            CancellationToken cancellationToken = default
        )
        {
            //
            var result = await provider.IsExistsAsync(
                id: id,
                cancellationToken: cancellationToken
            );

            //
            return result;
        }
        #endregion
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xTagService\Providers\XBaseTagProvided.cs

using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;
using xCommons.Extensions;
using xIdentityModels.Models;
using xModels.Base;
using xPushService.Base;
using xPushService.Interfaces;
using xTagService.Interfaces;
using xIdentityModels.Extensions;
using xExceptions.Constants;
using System.Linq;

namespace xTagService.Providers
{
    public abstract class XBaseTagProvided<TEntity, TDto, TKey, THub> : IXTagProvided<TEntity, TDto, TKey, THub>
    where TEntity : XBaseEntity<TKey>
    where TDto : XBaseEntityDto<TKey>
    where THub : XBaseDtoHub<TEntity, TDto, TKey>
    {
        private readonly string[] permittedRoles;
        private readonly IXBaseTagProvider<TKey> tagProvider;
        private readonly IXBaseDtoProvider<TEntity, TDto, TKey, THub> provider;

        protected XBaseTagProvided(
            IXBaseTagProvider<TKey> tagProvider,
            IXBaseDtoProvider<TEntity, TDto, TKey, THub> provider,
            string[] permittedRoles = null
        )
        {
            this.provider = provider;
            this.tagProvider = tagProvider;
            this.permittedRoles = permittedRoles;
        }

        /// <summary>
        /// Check an Items is Owned for User or not ...
        /// </summary>
        /// <param name="item"></param>
        /// <param name="userInfo"></param>
        /// <returns></returns>
        public abstract bool IsOwned(
            TDto item,
            XUserClaimsInfoDto userInfo
        );
        public abstract bool IsOwned(
            TEntity item,
            XUserClaimsInfoDto userInfo
        );

        /// <summary>
        /// Check User Has Permission for Manipulate Data or not ...
        /// </summary>
        /// <param name="userInfo"></param>
        /// <returns></returns>
        public bool HasPermision(
            XUserClaimsInfoDto userInfo
        )
        {
            //
            var result =
                !userInfo.IsNullOrDefault() &&
                userInfo.HasAccess(permittedRoles);

            //
            return result;
        }

        //
        #region Actions ...
        /// <summary>
        /// Attach Tag to Specified Item ...
        /// </summary>
        /// <param name="id"></param>
        /// <param name="tag"></param>
        /// <param name="userInfo"></param>
        /// <param name="connectionId"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public virtual async Task AttachTag(
            TKey id,
            string tag,
            XUserClaimsInfoDto userInfo = null,
            string connectionId = null,
            CancellationToken cancellationToken = default
        )
        {
            //
            // Validate ...
            var isValid =
                !id.IsNull() &&
                !tag.IsNullOrEmpty() &&
                !userInfo.IsNullOrDefault();
            if (!isValid)
            {
                XException.InvalidArgs.Throw();
            }

            //
            var item = await provider.GetAsync(
                id: id,
                includeBuilder: null,
                ignoreSoftDeleteds: true,
                cancellationToken: cancellationToken
            );
            isValid =
                !item.IsNullOrDefault() &&
                (IsOwned(item, userInfo) ||
                HasPermision(userInfo));
            if (!isValid)
            {
                XException.NotAllowed.Throw();
            }

            //
            try
            {
                //
                await tagProvider.AddReference(
                    tag: tag,
                    providedForId: id,
                    connectionId: connectionId,
                    cancellationToken: cancellationToken
                );
            }
            catch { }
        }

        /// <summary>
        /// Detach Tag fro Specified Item ...
        /// </summary>
        /// <param name="id"></param>
        /// <param name="tag"></param>
        /// <param name="userInfo"></param>
        /// <param name="connectionId"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public virtual async Task DetachTag(
            TKey id,
            string tag,
            XUserClaimsInfoDto userInfo = null,
            string connectionId = null,
            CancellationToken cancellationToken = default
        )
        {
            //
            // Validate ...
            var isValid =
                !id.IsNull() &&
                !tag.IsNullOrEmpty() &&
                !userInfo.IsNullOrDefault();
            if (!isValid)
            {
                XException.InvalidArgs.Throw();
            }

            //
            var item = await provider.GetAsync(
                id: id,
                includeBuilder: null,
                ignoreSoftDeleteds: true,
                cancellationToken: cancellationToken
            );
            isValid =
                !item.IsNullOrDefault() &&
                (IsOwned(item, userInfo) ||
                HasPermision(userInfo));
            if (!isValid)
            {
                XException.NotAllowed.Throw();
            }

            //
            try
            {
                //
                await tagProvider.RemoveReference(
                    tag: tag,
                    providedForId: id,
                    connectionId: connectionId,
                    cancellationToken: cancellationToken
                );
            }
            catch { }
        }

        /// <summary>
        /// Attach Tags for Specified Item ...
        /// </summary>
        /// <param name="id"></param>
        /// <param name="tags"></param>
        /// <param name="userInfo"></param>
        /// <param name="connectionId"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public virtual async Task AttachTags(
            TKey id,
            IEnumerable<string> tags,
            XUserClaimsInfoDto userInfo = null,
            string connectionId = null,
            CancellationToken cancellationToken = default
        )
        {
            //
            // Validate ...
            var isValid =
                !id.IsNull() &&
                !tags.IsNull() &&
                tags.HasChild();
            if (!isValid)
            {
                XException.InvalidArgs.Throw();
            }

            //
            // Loop through Tags ...
            foreach (var tag in tags)
            {
                //
                // Check Cancellation Token ...
                if (cancellationToken.IsCancellationRequested)
                {
                    break;
                }

                //
                await AttachTag(
                    id: id,
                    tag: tag,
                    userInfo: userInfo,
                    connectionId: connectionId,
                    cancellationToken: cancellationToken
                );
            }
        }

        /// <summary>
        /// Detach Tags for Specified Item ...
        /// </summary>
        /// <param name="id"></param>
        /// <param name="tags"></param>
        /// <param name="userInfo"></param>
        /// <param name="connectionId"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public virtual async Task DetachTags(
            TKey id,
            IEnumerable<string> tags,
            XUserClaimsInfoDto userInfo = null,
            string connectionId = null,
            CancellationToken cancellationToken = default
        )
        {
            //
            // Validate ...
            var isValid =
                !id.IsNull() &&
                !tags.IsNull() &&
                tags.HasChild();
            if (!isValid)
            {
                XException.InvalidArgs.Throw();
            }

            //
            // Loop through Tags ...
            foreach (var tag in tags)
            {
                //
                // Check Cancellation Token ...
                if (cancellationToken.IsCancellationRequested)
                {
                    break;
                }

                //
                await DetachTag(
                    id: id,
                    tag: tag,
                    userInfo: userInfo,
                    connectionId: connectionId,
                    cancellationToken: cancellationToken
                );
            }
        }

        /// <summary>
        /// Detach all Attached Tags for Specified Item ...
        /// </summary>
        /// <param name="id"></param>
        /// <param name="userInfo"></param>
        /// <param name="connectionId"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public virtual async Task DetachTags(
            TKey id,
            XUserClaimsInfoDto userInfo = null,
            string connectionId = null,
            CancellationToken cancellationToken = default
        )
        {
            //
            // Validate ...
            var isValid =
                !id.IsNull();
            if (!isValid)
            {
                XException.InvalidArgs.Throw();
            }

            //
            var item = await provider.GetAsync(
                id: id,
                includeBuilder: null,
                ignoreSoftDeleteds: true,
                cancellationToken: cancellationToken
            );
            isValid =
                !item.IsNullOrDefault() &&
                (IsOwned(item, userInfo) ||
                HasPermision(userInfo));
            if (!isValid)
            {
                XException.NotAllowed.Throw();
            }

            //
            try
            {
                //
                await tagProvider.RemoveReferences(
                    providedForId: id,
                    connectionId: connectionId,
                    cancellationToken: cancellationToken
                );
            }
            catch { }
        }

        /// <summary>
        /// Get Specified Model's Item ...
        /// </summary>
        /// <param name="id"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public virtual async Task<IEnumerable<string>> GetTags(
            TKey id,
            CancellationToken cancellationToken = default
        )
        {
            //
            // Validate ...
            var isValid = !id.IsNull();
            if (!isValid)
            {
                XException.InvalidArgs.Throw();
            }

            //
            isValid = await provider.IsExistsAsync(
                id: id,
                ignoreSoftDeleteds: true,
                cancellationToken: cancellationToken
            );
            if (!isValid)
            {
                XException.NotFound.Throw();
            }

            //
            var result = (await tagProvider.GetAllReferences(
                providedForId: id,
                cancellationToken: cancellationToken
            ))
            .Select(x => x.Tag)
            .Distinct()
            .ToList();

            //
            return result;
        }
        #endregion
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xTagService\Providers\XBaseTagProvider.cs

using System.Collections.Generic;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using xCommons.Extensions;
using xDataService.Extensions;
using xDataService.Models;
using xExceptions.Constants;
using xModels.Dtos;
using xTagService.Extensions;
using xTagService.Interfaces;
using xTagService.Interfaces.Dtos;
using xTagService.Models.Dtos;

namespace xTagService.Providers
{
    public abstract class XBaseTagProvider<TKey> : IXBaseTagProvider<TKey>
    {
        //
        #region Props ...
        /// <summary>
        /// Provider Identifier ...
        /// </summary>
        public string Provider { get; }

        /// <summary>
        /// Tag Provider for Maipulating Tags ...
        /// </summary>
        public IXTagServiceProvider TagProvider { get; }
        #endregion

        //
        #region Constructor ...
        public XBaseTagProvider(
            string providedFor,
            IXTagServiceProvider tagProvider
        )
        {
            //
            Provider = providedFor;
            TagProvider = tagProvider;
        }
        #endregion

        //
        #region Referenced Actions ...
        /// <summary>
        /// Get Specified Indexed Reference for Specific Provided ID ...
        /// </summary>
        /// <param name="providedForId"></param>
        /// <param name="forIndex"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public async Task<XTagDto> GetReference(
            TKey providedForId,
            int forIndex = 0,
            CancellationToken cancellationToken = default
        )
        {
            //
            // Validate ...
            if (providedForId.IsNull())
            {
                XException.InvalidArgs.Throw();
            }

            //
            // Normalize ...
            if (forIndex < 0)
            {
                forIndex = 0;
            }

            //
            // Retrieve Last Index ...
            var maxIndex = (await GetReferencingIndexes(
                providedForId: providedForId,
                cancellationToken: cancellationToken
            ))
            .Max();
            if (forIndex > maxIndex)
            {
                XException.NotFound.Throw();
            }

            //
            var indexedIdentifier = GetIndexedProvidedID(
                forIndex: forIndex,
                providedForId: providedForId
            );
            var result = await TagProvider.FindOneAsync(
                includeBuilder: null,
                ignoreSoftDeleteds: true,
                cancellationToken: cancellationToken,
                predicate: x => x.References.Contains(indexedIdentifier)
            );
            if (result.IsNullOrDefault())
            {
                XException.NotFound.Throw();
            }

            //
            return result;
        }

        /// <summary>
        /// Retrieve all Exists References of Specific Provided ID ...
        /// </summary>
        /// <param name="providedForId"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public async Task<IEnumerable<XTagDto>> GetAllReferences(
            TKey providedForId,
            CancellationToken cancellationToken = default
        )
        {
            //
            // Validate ...
            if (providedForId.IsNull())
            {
                XException.InvalidArgs.Throw();
            }

            //
            var identifier = GetProvidedID(providedForId);
            var result = await TagProvider.FindManyAsync(
                orderBuilder: null,
                includeBuilder: null,
                ignoreSoftDeleteds: true,
                cancellationToken: cancellationToken,
                predicate: x => x.References.Contains(identifier)
            );

            //
            return result;
        }

        /// <summary>
        /// Extract all Referencing Models for Specified Key ...
        /// </summary>
        /// <param name="providedForId"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns> 
        public async Task<IEnumerable<XReference<TKey>>> GetAllReferencings(
            TKey providedForId,
            CancellationToken cancellationToken = default
        )
        {
            //
            // Validate ...
            var isValid =
                !providedForId.IsNull();
            if (!isValid)
            {
                XException.InvalidArgs.Throw();
            }

            //
            var identifier = GetProvidedID(providedForId);

            //
            var result = (await TagProvider.FindManyAsync(
                orderBuilder: null,
                includeBuilder: null,
                ignoreSoftDeleteds: true,
                cancellationToken: cancellationToken,
                predicate: x => x.References.Contains(identifier)
            ))
            .Select(x => x.References)
            .ToList()
            .SelectMany(x => x.ParseXReferenceList<TKey>())
            .Where(x => x.ProvidedFor == Provider && $"{x.ReferencedTo}" == $"{providedForId}")
            .OrderBy(x => x.Index)
            .AsEnumerable();

            //
            return result;
        }

        /// <summary>
        /// Count References ...
        /// </summary>
        /// <param name="providedForId"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public async Task<int> CountReferences(
            TKey providedForId,
            CancellationToken cancellationToken = default
        )
        {
            //
            // Validate ...
            var isValid = !providedForId.IsNull();
            if (!isValid)
            {
                XException.InvalidArgs.Throw();
            }

            //
            var identifier = GetProvidedID(providedForId);
            var result = (await TagProvider.FindManyAsync(
                orderBuilder: null,
                includeBuilder: null,
                ignoreSoftDeleteds: true,
                cancellationToken: cancellationToken,
                predicate: x => x.References.Contains(identifier)
            ))
            .Count();

            //
            return result;
        }

        /// <summary>
        /// Retrieve References of Specific Provided ID as Query ...
        /// </summary>
        /// <param name="providedForId"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public async Task<XQueryResult<XTagDto>> QueryReferences(
            XQuery query,
            TKey providedForId,
            CancellationToken cancellationToken = default
        )
        {
            //
            // Validate ...
            if (query.IsNull() || providedForId.IsNull())
            {
                XException.InvalidArgs.Throw();
            }

            //
            var identifier = GetProvidedID(providedForId);
            var result = await TagProvider.QueryAsync(
                query: query,
                includeBuilder: null,
                ignoreSoftDeleteds: true,
                cancellationToken: cancellationToken,
                orderBuilder: x => x.OrderBy(y => y.Id),
                predicate: x => x.References.Contains(identifier)
            );

            //
            return result;
        }

        /// <summary>
        /// Add Reference a Model to Specific Provided ID ...
        /// </summary>
        /// <param name="model"></param>
        /// <param name="providedForId"></param>
        /// <param name="connectionId"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public async Task<bool> AddReference(
            XTagDto model,
            TKey providedForId,
            string connectionId = null,
            CancellationToken cancellationToken = default
        )
        {
            //
            var result = false;

            //
            // Validate ...
            result = !model.IsNullOrDefault() &&
                !model.Tag.IsNullOrEmpty() &&
                model.Id.IsValidIntId() &&
                !providedForId.IsNull();
            if (!result)
            {
                XException.InvalidArgs.Throw();
            }

            //
            // Check Model Exists ...
            result = await TagProvider.IsExistsAsync(model.Id);
            if (!result)
            {
                XException.NotFound.Throw();
            }

            //
            // Update Model by Retrieving ...
            model = await TagProvider.GetAsync(
                id: model.Id,
                includeBuilder: null,
                ignoreSoftDeleteds: true,
                cancellationToken: cancellationToken
            );

            //
            // Retrieve all References ...
            var references = await GetAllReferences(
                providedForId: providedForId,
                cancellationToken: cancellationToken
            );

            //
            // Check isReferenced or not ...
            result = references
                .Any(r =>
                    r.Id == model.Id &&
                    r.GetReferences()
                    .Any(rf =>
                        rf.ProvidedFor == Provider &&
                        rf.ReferencedTo == $"{providedForId}"));
            if (result)
            {
                return result;
            }

            //
            // Here means there is not any reference to ProvidedForId ...
            int forIndex = await CountReferences(
                providedForId: providedForId,
                cancellationToken: cancellationToken
            );
            var modelReferences = model.GetReferences();
            modelReferences.Add(new XReference<string>
            {
                Index = forIndex,
                ProvidedFor = Provider,
                ReferencedTo = $"{providedForId}"
            });
            modelReferences = modelReferences
                .OrderBy(r => r.Index)
                .ToList();
            model = model.UpdateReferences(modelReferences);

            //
            // Update Data Base ...
            model = await TagProvider.UpdateAsync(
                id: model.Id,
                item: model,
                saveChanges: true,
                connectionId: connectionId,
                cancellationToken: cancellationToken
            );
            result = !model.IsNullOrDefault();

            //
            return result;
        }

        /// <summary>
        /// Add Reference a Model to Specific XRefence<TKey> ...
        /// </summary>
        /// <param name="model"></param>
        /// <param name="reference"></param>
        /// <param name="connectionId"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public async Task<bool> AddReference(
            XTagDto model,
            XReference<TKey> reference,
            string connectionId = null,
            CancellationToken cancellationToken = default
        )
        {
            //
            // Validate ...
            // Since other Validations Handled in Calling, we Ignore them here ...
            var result =
                !model.IsNull() &&
                !reference.IsNullOrDefault() &&
                reference.ProvidedFor == Provider &&
                !reference.ReferencedTo.IsNull();
            if (!result)
            {
                XException.InvalidArgs.Throw();
            }

            //
            result = await AddReference(
                model: model,
                connectionId: connectionId,
                cancellationToken: cancellationToken,
                providedForId: reference.ReferencedTo
            );

            //
            return result;
        }

        /// <summary>
        /// Remove Reference a Model for Specific Provided ID ...
        /// </summary>
        /// <param name="model"></param>
        /// <param name="providedForId"></param>
        /// <param name="connectionId"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public async Task<bool> RemoveReference(
            XTagDto model,
            TKey providedForId,
            string connectionId = null,
            CancellationToken cancellationToken = default
        )
        {
            //
            // Validate ...
            var result =
                !providedForId.IsNull() &&
                !model.IsNullOrDefault() &&
                model.Id.IsValidIntId();
            if (!result)
            {
                XException.InvalidArgs.Throw();
            }

            //
            // Retrieve Model ...
            model = await TagProvider.GetAsync(
                id: model.Id,
                includeBuilder: null,
                ignoreSoftDeleteds: true,
                cancellationToken: cancellationToken
            );
            result = !model.IsNullOrDefault();
            if (!result)
            {
                XException.NotFound.Throw();
            }

            //
            // Reading Referencing Indexes ...
            var indexes = await GetReferencingIndexes(
                providedForId: providedForId,
                cancellationToken: cancellationToken
            );

            //
            // Check Model Reference to ID ...
            var referencesCount = await CountReferences(
                providedForId: providedForId,
                cancellationToken: cancellationToken
            );
            result = referencesCount == 0;
            if (result)
            {
                //
                // There is not any Reference to Remove ...
                return result;
            }

            //
            // Check Model is Trully Referenced to ProvidedForId or not ...
            var reference = model
                .GetReferences()
                .FirstOrDefault(r =>
                    r.ProvidedFor == Provider &&
                    r.ReferencedTo == $"{providedForId}");
            result = !reference.IsNullOrDefault();
            if (!result)
            {
                XException.ActionFailed.Throw();
            }

            //
            // Remove Referenced Item from Model ...
            var modelReferences = model
                .GetReferences()
                .Where(r =>
                    !(r.ProvidedFor == Provider &&
                    r.ReferencedTo == $"{providedForId}"))
                .ToList();
            model = model.UpdateReferences(modelReferences);

            //
            // Update DataBase ...
            model = await TagProvider.UpdateAsync(
                item: model,
                id: model.Id,
                saveChanges: true,
                connectionId: connectionId,
                cancellationToken: cancellationToken
            );

            //
            result = !model.IsNullOrDefault();
            if (!result)
            {
                XException.ActionFailed.Throw();
            }

            //
            // Get Max Exists Indexes ...
            var maxIndex = indexes.Max();

            //
            // Here We Have to Re Arrange Indexed ...
            if (reference.Index < maxIndex)
            {
                //
                var startIndex = reference.Index + 1;
                for (int i = startIndex; i <= maxIndex; i++)
                {
                    //
                    var dto = await GetReference(
                        forIndex: i,
                        providedForId: providedForId,
                        cancellationToken: cancellationToken
                    );
                    if (!dto.IsNullOrDefault())
                    {
                        //
                        var dtoReferences = dto.GetReferences();
                        dtoReferences
                        .ToList()
                        .ForEach(iref =>
                        {
                            //
                            if (
                                iref.Index == i &&
                                iref.ProvidedFor == Provider &&
                                iref.ReferencedTo == reference.ReferencedTo
                            )
                            {
                                iref.Index = i - 1;
                            }
                        });
                        dto = dto.UpdateReferences(dtoReferences);

                        //
                        dto = await TagProvider.UpdateAsync(
                            item: dto,
                            id: dto.Id,
                            saveChanges: true,
                            connectionId: connectionId,
                            cancellationToken: cancellationToken
                        );
                    }
                }
            }

            //
            return result;
        }

        /// <summary>
        /// Remove Reference a Model for Specific XRefence<TKey> ...
        /// </summary>
        /// <param name="model"></param>
        /// <param name="reference"></param>
        /// <param name="connectionId"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public async Task<bool> RemoveReference(
            XTagDto model,
            XReference<TKey> reference,
            string connectionId = null,
            CancellationToken cancellationToken = default
        )
        {
            //
            if (model.IsNullOrDefault() ||
                reference.IsNullOrDefault() ||
                reference.ReferencedTo.IsNull() ||
                reference.ProvidedFor != Provider)
            {
                XException.InvalidArgs.Throw();
            }

            //
            var result = await RemoveReference(
                model: model,
                connectionId: connectionId,
                cancellationToken: cancellationToken,
                providedForId: reference.ReferencedTo
            );

            //
            return result;
        }

        /// <summary>
        /// Remove All References to Specified Key ...
        /// </summary>
        /// <param name="providedForId"></param>
        /// <param name="connectionId"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public async Task<bool> RemoveReferences(
            TKey providedForId,
            string connectionId = null,
            CancellationToken cancellationToken = default
        )
        {
            //
            // Validate ...
            if (providedForId.IsNull())
            {
                XException.InvalidArgs.Throw();
            }

            //
            var result = false;
            var references = await GetAllReferences(
                providedForId: providedForId,
                cancellationToken: cancellationToken
            );
            if (!references.IsNull() && references.HasChild())
            {
                //
                foreach (var reference in references)
                {
                    //
                    // Remove Reference ...
                    var itemReferences = reference.GetReferences()
                        .Where(r =>
                            r.ProvidedFor != Provider ||
                            (r.ProvidedFor == Provider &&
                                r.ReferencedTo != $"{providedForId}"))
                        .ToList();
                    var updatedModel = reference.UpdateReferences(itemReferences);
                    updatedModel = await TagProvider.UpdateAsync(
                        saveChanges: true,
                        item: updatedModel,
                        id: updatedModel.Id,
                        connectionId: connectionId,
                        cancellationToken: cancellationToken
                    );
                    if (!updatedModel.IsNullOrDefault())
                    {
                        result = true;
                    }
                }
            }

            //
            return result;
        }
        #endregion

        //
        #region Tools ...
        /// <summary>
        /// Add Reference a Tag to Specific Provided ID ...
        /// </summary>
        /// <param name="tag"></param>
        /// <param name="providedForId"></param>
        /// <param name="connectionId"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public async Task<bool> AddReference(
            string tag,
            TKey providedForId,
            string connectionId = null,
            CancellationToken cancellationToken = default
        )
        {
            //
            var result = false;

            //
            // Validate ...
            result = !tag.IsNullOrEmpty();
            if (!result)
            {
                XException.InvalidArgs.Throw();
            }

            //
            // Check Tag Exists ...
            result = await IsExists(
                tag: tag,
                cancellationToken: cancellationToken
            );
            if (!result)
            {
                //
                // Create Tag if Not Exists ...
                var tagDto = new XTagDto
                {
                    Tag = tag,
                };
                tagDto = await TagProvider.AddAsync(
                    item: tagDto,
                    saveChanges: true,
                    connectionId: connectionId,
                    cancellationToken: cancellationToken
                );
                result = !tagDto.IsNullOrDefault();
                if (!result)
                {
                    XException.ActionFailed.Throw();
                }
            }

            //
            var dto = await GetTagByTag(
                tag: tag,
                cancellationToken: cancellationToken
            );
            result = !dto.IsNullOrDefault();
            if (!result)
            {
                XException.ActionFailed.Throw();
            }

            //
            result = await AddReference(
                model: dto,
                connectionId: connectionId,
                providedForId: providedForId,
                cancellationToken: cancellationToken
            );

            //
            return result;
        }

        /// <summary>
        /// Add Reference a Tag to Specific XRefence<TKey> ...
        /// </summary>
        /// <param name="tag"></param>
        /// <param name="reference"></param>
        /// <param name="connectionId"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public async Task<bool> AddReference(
            string tag,
            XReference<TKey> reference,
            string connectionId = null,
            CancellationToken cancellationToken = default
        )
        {
            //
            var result = false;

            //
            // Validate ...
            result =
                !tag.IsNullOrEmpty() &&
                !reference.IsNullOrDefault() &&
                reference.ProvidedFor == Provider &&
                !reference.ReferencedTo.IsNull();
            if (!result)
            {
                XException.InvalidArgs.Throw();
            }

            //
            result = await AddReference(
                tag: tag,
                connectionId: connectionId,
                cancellationToken: cancellationToken,
                providedForId: reference.ReferencedTo
            );

            //
            return result;
        }

        /// <summary>
        /// Remove Reference a Tag for Specific Provided ID ...
        /// </summary>
        /// <param name="tag"></param>
        /// <param name="providedForId"></param>
        /// <param name="connectionId"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public async Task<bool> RemoveReference(
            string tag,
            TKey providedForId,
            string connectionId = null,
            CancellationToken cancellationToken = default
        )
        {
            //
            // Validate ...
            var result =
                !tag.IsNullOrEmpty() &&
                !providedForId.IsNull();
            if (!result)
            {
                XException.InvalidArgs.Throw();
            }

            //
            // Check Tag Exists ...
            result = await IsExists(
                tag: tag,
                cancellationToken: cancellationToken
            );
            if (!result)
            {
                XException.NotFound.Throw();
            }

            //
            var dto = await GetTagByTag(
                tag: tag,
                cancellationToken: cancellationToken
            );
            result = !dto.IsNullOrDefault();
            if (!result)
            {
                XException.ActionFailed.Throw();
            }

            //
            result = await RemoveReference(
                model: dto,
                connectionId: connectionId,
                providedForId: providedForId,
                cancellationToken: cancellationToken
            );

            //
            return result;
        }

        /// <summary>
        /// Remove Reference a Tag for Specific XRefence<TKey> ...
        /// </summary>
        /// <param name="tag"></param>
        /// <param name="reference"></param>
        /// <param name="connectionId"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public async Task<bool> RemoveReference(
            string tag,
            XReference<TKey> reference,
            string connectionId = null,
            CancellationToken cancellationToken = default
        )
        {
            //
            // Validate ...
            var result =
                !tag.IsNullOrEmpty() &&
                !reference.IsNullOrDefault() &&
                !reference.ReferencedTo.IsNull() &&
                reference.ProvidedFor == Provider;
            if (!result)
            {
                XException.InvalidArgs.Throw();
            }

            //
            result = await RemoveReference(
                tag: tag,
                connectionId: connectionId,
                cancellationToken: cancellationToken,
                providedForId: reference.ReferencedTo
            );

            //
            return result;
        }
        #endregion

        //
        #region Private ...
        private string GetProvidedID(
            TKey providedForId,
            char splitter = '_'
        )
        {
            //
            // Validate ...
            if (providedForId.IsNull())
            {
                XException.InvalidArgs.Throw();
            }

            //
            var result = $"{Provider}{splitter}{providedForId}";
            return result;
        }

        private string GetIndexedProvidedID(
            TKey providedForId,
            int forIndex,
            char splitter = '_'
        )
        {
            //
            var result = $"{GetProvidedID(providedForId, splitter)}{splitter}{forIndex}";

            //
            return result;
        }

        private async Task<IEnumerable<int>> GetReferencingIndexes(
            TKey providedForId,
            CancellationToken cancellationToken = default
        )
        {
            //
            // Validate ...
            var isValid =
                !providedForId.IsNull();
            if (!isValid)
            {
                XException.InvalidArgs.Throw();
            }

            //
            var result = new List<int>();
            var referencings = await GetAllReferencings(
                providedForId: providedForId,
                cancellationToken: cancellationToken
            );
            isValid =
                !referencings.IsNull() &&
                referencings.HasChild();
            if (!isValid)
            {
                return result;
            }

            //
            result =
                referencings
                    .OrderBy(r => r.Index)
                    .Select(r => r.Index)
                    .ToList();

            //
            return result;
        }

        private async Task<XTagDto> GetTagByTag(
            string tag,
            CancellationToken cancellationToken = default
        )
        {
            //
            XTagDto result = null;

            //
            if (!tag.IsNullOrEmpty())
            {
                //
                result = await TagProvider
                    .FindOneAsync(
                        predicate: x => x.Tag == tag,
                        cancellationToken: cancellationToken
                    );
            }

            //
            return result;
        }

        private async Task<bool> IsExists(
            string tag,
            CancellationToken cancellationToken = default
        )
        {
            //
            var result = false;

            //
            if (!tag.IsNullOrEmpty())
            {
                //
                var dto = await GetTagByTag(
                    tag: tag,
                    cancellationToken: cancellationToken
                );
                result = !dto.IsNullOrDefault();
            }

            //
            return result;
        }
        #endregion        
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xTagService\Providers\XTagEntityRegisterar.cs

using Microsoft.EntityFrameworkCore;
using xDataService.Interfaces;
using xDataService.Providers;
using xTagService.Configurations.Entities;
using xTagService.Models.Entities;

namespace xTagService.Providers
{
    public class XTagEntityRegisterar : XBaseEntityRegisterar, IXEntityRegisterar
    {
        public XTagEntityRegisterar()
        : base(nameof(XTagEntityRegisterar))
        {
            //
            // Add XTag Entity ...
            AddEntity<XTag, int>();
        }

        /// <summary>
        /// Configure Entities ...
        /// </summary>
        /// <param name="modelBuilder"></param>
        public override void ConfigureEntities(ModelBuilder modelBuilder)
        {
            //
            // Configure Entity Using Provided ...
            modelBuilder
                .ApplyConfigurationsFromAssembly(typeof(XTagEntityConfiguration).Assembly);

            //
            base.ConfigureEntities(modelBuilder);
        }
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xTagService\Providers\XTagProvider.cs

using xCommons.Extensions;
using xIdentityModels.Models;
using xPushService.Providers;
using xTagService.Interfaces;
using xTagService.Interfaces.Dtos;
using xTagService.Models.Dtos;
using xTagService.Models.Entities;
using xTagService.Providers.Dtos;

namespace xTagService.Providers
{
    public class XTagProvider : XBaseProvided<XTag, XTagDto, int, XTagDtoHub>, IXTagProvider
    {
        public XTagProvider(
            IXTagServiceProvider provider
        ) : base(
            provider,
            permittedRoles: new string[] { }
        )
        { }

        public override bool IsOwned(
            XTagDto item,
            XUserClaimsInfoDto userInfo
        )
        {
            return !item.IsNullOrDefault();
        }

        public override bool IsOwned(
            XTag item,
            XUserClaimsInfoDto userInfo
        )
        {
            return !item.IsNullOrDefault();
        }
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xTermsAndConditionsService\Configurations\XTermsAndConditionsServiceConfiguration.cs

using System.Collections.Generic;
using xDataService.Constants;
using xStringService.Models.Dtos;

namespace xTermsAndConditionsService.Configurations
{
    /// <summary>
    /// Terms and Conditions Configuration ...
    /// </summary>
    public class XTermsAndConditionsServiceConfiguration
    {
        /// <summary>
        /// Terms And Conditions Resource Title in XString Table ...
        /// </summary>
        public string ResourceTitle { get; set; } = "terms_and_conditions";

        /// <summary>
        /// Seeding Mode for Terms and Conditions ...
        /// </summary>
        public XDbSeedingMode SeedingMode { get; set; } = XDbSeedingMode.AddIfNotExists;

        /// <summary>
        /// Default Terms and Conditions for Add to Databse on App Startup ...
        /// </summary>
        public List<XStringDto> TermsAndConditions { get; set; } = null;        
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xTermsAndConditionsService\Constants\ConfigurationNodeNames.cs

namespace xTermsAndConditionsService.Constants
{
    public partial struct ConfigurationNodeNames
    {
        public const string TERMS_AND_CONDITIONS_SERVICE_NODE = "TermsAndConditionsService";
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xTermsAndConditionsService\Constants\XTermsAndConditionsServiceConstants.cs

namespace xTermsAndConditionsService.Constants
{
    public struct XTermsAndConditionsServiceConstants
    {
        //
        // Service Extensions Log Tag ...
        public const string XTermsAndConditionsServiceDILogTag = "XTermsAndConditionsService";

        //
        // Table Mapping Identifiers ...

        //
        // GraphQL Collection Mappings ...

        //
        // Hubs ...

        //
        // Custome Constants ...

        //
        // EF Repositories Helper Extensions ...        
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xTermsAndConditionsService\Controllers\XTermsAndConditionsControllerBase.cs

using Microsoft.AspNetCore.Authorization;
using Microsoft.Extensions.Logging;
using xCommons.Configurations;
using xCommons.Providers;
using xIdentityService.Interfaces;
using xStringService.Controllers;
using xTermsAndConditionsService.Interfaces;

namespace xTermsAndConditionsService.Controllers
{
    /// <summary>
    /// a Base Controller Implementation for Providing Base Actions of 
    /// Terms and Conditions Provided Actions ...
    /// </summary>
    [AllowAnonymous]
    public abstract class XTermsAndConditionsControllerBase : XBaseResourceProviderControllerBase<IXTermsAndConditionsProvider>, IXTermsAndConditionsController
    {
        protected XTermsAndConditionsControllerBase(
            ILogger<XTermsAndConditionsControllerBase> logger,
            XAppConfiguration appConfiguration,
            IXIdentityProvider identityProvider,
            XValidationProvider validationProvider,
            IXTermsAndConditionsProvider provider
        ) : base(
            logger,
            appConfiguration,
            identityProvider,
            validationProvider,
            provider
        )
        { }
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xTermsAndConditionsService\DI\XDIHelperExtension.cs

using System;
using System.Linq;
using Microsoft.AspNetCore.Builder;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using xCommons.Configurations;
using xCommons.Extensions;
using xExceptions.Constants;
using xPushService.DI;
using xPushService.Helpers;
using xStringService.Interfaces.Dtos;
using xTermsAndConditionsService.Configurations;
using xTermsAndConditionsService.Constants;
using xTermsAndConditionsService.Hubs;
using xTermsAndConditionsService.Interfaces;
using xTermsAndConditionsService.Providers;

namespace xTermsAndConditionsService.DI
{
    public static class XDIHelperExtension
    {
        /// <summary>
        /// Retrieve xTermsAndConditionsService Configuration from AppSettings ...
        /// </summary>
        /// <param name="configuration"></param>
        /// <returns></returns>
        public static XTermsAndConditionsServiceConfiguration GetXTermsAndConditionsServiceConfiguration(
            this IConfiguration configuration
        )
        {
            //
            var section = configuration.GetSection(ConfigurationNodeNames.TERMS_AND_CONDITIONS_SERVICE_NODE);
            var result = section.Get<XTermsAndConditionsServiceConfiguration>();

            //
            return result;
        }

        /// <summary>
        /// Extract xTermsAndConditionsService Configurations from AppSettings 
        /// and Register it in DI ...
        /// </summary>
        /// <param name="services"></param>
        /// <param name="configuration"></param>
        public static void AddXTermsAndConditionsConfiguration(
            this IServiceCollection services,
            IConfiguration configuration
        )
        {
            //
            var serviceConfiguration = configuration.GetXTermsAndConditionsServiceConfiguration();
            services.AddXTermsAndConditionsConfiguration(serviceConfiguration);
        }

        /// <summary>
        /// Register xTermsAndConditionsService Configurations in DI ...
        /// </summary>
        /// <param name="services"></param>
        /// <param name="configuration"></param>
        public static void AddXTermsAndConditionsConfiguration(
            this IServiceCollection services,
            XTermsAndConditionsServiceConfiguration configuration
        )
        {
            //
            if (configuration.IsNull())
            {
                Log($"there is no provided configurations, using default ...");
                configuration = new XTermsAndConditionsServiceConfiguration();
            }

            //
            services.AddSingleton(configuration);
        }

        /// <summary>
        /// Register TermsConditions Provider ...
        /// </summary>
        /// <param name="services"></param>
        /// <param name="configuration">provided AppSettings Configuration</param>
        /// <param name="lifeTime"></param>
        public static void AddXTermsConditionsService(
            this IServiceCollection services,
            IConfiguration configuration,
            ServiceLifetime lifeTime = ServiceLifetime.Transient
        )
        {
            //
            AddTermsAndConditionsService(
                services: services,
                lifeTime: lifeTime,
                configuration: configuration
            );
        }

        /// <summary>
        /// Register TermsConditions Provider ...
        /// </summary>
        /// <param name="services"></param>
        /// <param name="configuration">provided xTermsAndConditionsService Configuration</param>
        /// <param name="lifeTime"></param>
        public static void AddXTermsConditionsService(
            this IServiceCollection services,
            XTermsAndConditionsServiceConfiguration configuration,
            ServiceLifetime lifeTime = ServiceLifetime.Transient
        )
        {
            //
            AddTermsAndConditionsService(
                services: services,
                lifeTime: lifeTime,
                serviceConfiguration: configuration
            );
        }

        public static void UseXTermsAndConditionsService(
            this IApplicationBuilder app
        )
        {
            //
            // Create an Scope for Services Acess ...
            using (var scope = app.ApplicationServices.CreateScope())
            {
                //
                // Inject Requirements ...
                var stringProvider = scope.ServiceProvider.GetService<IXStringServiceProvider>();
                var serviceConfiguration = scope.ServiceProvider.GetService<XTermsAndConditionsServiceConfiguration>();

                //
                // Using XTerms Hub ...
                var pushHelper = new XPushServiceHelper();
                pushHelper.AddHub<XTermsHub>("terms");
                app.UseXPushService(pushHelper);

                //
                // Validate Requirements Exists ...
                var isValid =
                    !stringProvider.IsNull() &&
                    !serviceConfiguration.IsNull() &&
                    !serviceConfiguration.TermsAndConditions.IsNull() &&
                    serviceConfiguration.TermsAndConditions.HasChild() &&
                    serviceConfiguration.SeedingMode != xDataService.Constants.XDbSeedingMode.None;
                if (isValid)
                {
                    //
                    // Prepare Default Terms ...
                    serviceConfiguration
                        .TermsAndConditions
                        .ToList()
                        .ForEach(t => t.ResourceTitle = serviceConfiguration.ResourceTitle);

                    //
                    // Loop through Terms and Conditions for Seeding ...
                    foreach (var item in serviceConfiguration.TermsAndConditions)
                    {
                        //
                        // Detect Exists Item ...
                        var exists = stringProvider.FindOneAsync(
                            predicate: x =>
                                x.Language == item.Language &&
                                x.ResourceTitle == item.ResourceTitle
                        )
                        .GetAwaiter()
                        .GetResult();

                        //
                        var isExists = !exists.IsNullOrDefault();

                        //
                        switch (serviceConfiguration.SeedingMode)
                        {
                            //
                            case xDataService.Constants.XDbSeedingMode.AddOrUpdate:
                                //
                                // Update Exists by new Provided ...
                                exists.TranslatedValue = item.TranslatedValue;
                                exists = stringProvider.UpdateAsync(
                                    id: exists.Id,
                                    item: exists,
                                    saveChanges: true
                                )
                                .GetAwaiter()
                                .GetResult();

                                //
                                Log($"Refresh Terms and Conditions of {exists.Language}");
                                break;

                            //
                            case xDataService.Constants.XDbSeedingMode.AddIfNotExists:
                                //
                                if (!isExists)
                                {
                                    //
                                    exists = stringProvider.AddAsync(
                                        item: item,
                                        saveChanges: true
                                    )
                                    .GetAwaiter()
                                    .GetResult();

                                    //
                                    Log($"Add Terms and Conditions for {exists.Language}");
                                }
                                break;
                        }
                    }
                }
            }
        }

        //
        #region Private ...
        /// <summary>
        /// a LogTag for Service ...
        /// </summary>
        private static string XLogTag = XTermsAndConditionsServiceConstants.XTermsAndConditionsServiceDILogTag;

        /// <summary>
        /// print a log in Console ...
        /// </summary>
        /// <param name="message"></param>
        private static void Log(string message)
        {
            Console.WriteLine($"{XLogTag} => {message}");
        }

        /// <summary>
        /// Add Terms and Conditions Provider Service ...
        /// </summary>
        /// <param name="services"></param>
        /// <param name="lifeTime"></param>
        private static void AddTermsAndConditionsService(
            IServiceCollection services,
            IConfiguration configuration = null,
            XTermsAndConditionsServiceConfiguration serviceConfiguration = null,
            ServiceLifetime lifeTime = ServiceLifetime.Transient
        )
        {
            //
            var exception = XException.InvalidArgs.ToException(); ;

            //
            // Services ...
            var isServicesExists = !services.IsNull();
            if (!isServicesExists)
            {
                //
                Log("AddTermsAndConditions failed, services not provided ...");
                throw exception;
            }

            //
            // Validate Configuration ...
            var isConfigValid = !configuration.IsNull() || !serviceConfiguration.IsNull();
            if (!isConfigValid)
            {
                //
                Log("AddTermsAndConditions failed, configuration not provided ...");
                throw exception;
            }

            //
            // Lifetime ...
            var isLifetimeExists = !lifeTime.IsNull();
            if (!isLifetimeExists)
            {
                //
                Log("AddTermsAndConditions failed, lifetime not provided ...");
                throw exception;
            }

            //
            // Check Dependencies Exists ...
            var isDependenciesPassed = !services
                .GetRegisteredService<XAppConfiguration>()
                .IsNull() &&
                !services.GetRegisteredService<IXStringServiceProvider>()
                .IsNull();
            if (!isDependenciesPassed)
            {
                //
                Log("AddTermsAndConditions failed due Dependencies Issues, IXStringServiceProvider or XAppConfiguration not provided ...");
                throw exception;
            }

            //
            // Service Configuration Handler ...
            if (serviceConfiguration.IsNull())
            {
                serviceConfiguration = configuration.GetXTermsAndConditionsServiceConfiguration();
            }
            services.AddXTermsAndConditionsConfiguration(serviceConfiguration);

            //
            // Register Resource Providers ...
            services.Add(new ServiceDescriptor(typeof(IXTermsAndConditionsProvider), typeof(XTermsAndConditionsProvider), lifeTime));
        }
        #endregion
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xTermsAndConditionsService\Hubs\XTermsHub.cs

using System.Threading;
using System.Threading.Tasks;
using Microsoft.AspNetCore.SignalR;
using Microsoft.Extensions.Logging;
using xCommons.Extensions;
using xPushService.Base;
using xPushService.Constants;
using xStringService.Models.Dtos;

namespace xTermsAndConditionsService.Hubs
{
    /// <summary>
    /// a Hub for Notifing Terms and Conditions Events to Connected Clients ...
    /// </summary>
    public class XTermsHub : XBaseHub
    {
        public XTermsHub(
            ILogger<XTermsHub> logger
        ) : base(logger)
        {
        }

        //
        #region Hub Actions ...
        /// <summary>
        /// Add Specified Terms and Conditions ...
        /// </summary>
        /// <param name="entity"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public async Task Add(
            XStringDto entity,
            CancellationToken cancellationToken = default
        )
        {
            //
            var connectionId = Context.ConnectionId;
            if (!connectionId.IsNullOrEmpty())
            {
                //
                await Clients
                    .AllExcept(connectionId)
                    .SendAsync(
                        XBaseEntityHubAction.Add.GetStringValue(),
                        entity.ToJSON(camelCase: true),
                        connectionId,
                        cancellationToken
                    );
            }
        }

        /// <summary>
        /// Deleted Specified Terms and Conditions ...
        /// </summary>
        /// <param name="entity"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public async Task Delete(
            XStringDto entity,
            CancellationToken cancellationToken = default
        )
        {
            //
            var connectionId = Context.ConnectionId;
            if (!connectionId.IsNullOrEmpty())
            {
                //
                await Clients
                    .AllExcept(connectionId)
                    .SendAsync(
                        XBaseEntityHubAction.Delete.GetStringValue(),
                        entity.ToJSON(camelCase: true),
                        connectionId,
                        cancellationToken
                    );
            }
        }

        /// <summary>
        /// Notify an Entity Updated ...
        /// </summary>
        /// <param name="entity"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public async Task Update(
            XStringDto entity,
            CancellationToken cancellationToken = default
        )
        {
            //
            var connectionId = Context.ConnectionId;
            if (!connectionId.IsNullOrEmpty())
            {
                //
                await Clients
                    .AllExcept(connectionId)
                    .SendAsync(
                        XBaseEntityHubAction.Update.GetStringValue(),
                        entity.ToJSON(camelCase: true),
                        connectionId,
                        cancellationToken
                    );
            }
        }
        #endregion
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xTermsAndConditionsService\Interfaces\IXTermsAndConditionsController.cs

using xStringService.Interfaces;

namespace xTermsAndConditionsService.Interfaces
{
    /// <summary>
    /// an Interface for Describing Terms and Conditions Management Controller Actions ...
    /// </summary>
    public interface IXTermsAndConditionsController : IXBaseResourceProviderController
    { }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xTermsAndConditionsService\Interfaces\IXTermsAndConditionsProvider.cs

using xStringService.Interfaces;

namespace xTermsAndConditionsService.Interfaces
{
    /// <summary>
    /// an Interface for Describing Terms and Conditions Management Provided Actions ...
    /// </summary>
    public interface IXTermsAndConditionsProvider : IXResourceProvider
    { }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xTermsAndConditionsService\Providers\XTermsAndConditionsProvider.cs

using xStringService.Interfaces.Dtos;
using xStringService.Providers;
using xTermsAndConditionsService.Configurations;
using xTermsAndConditionsService.Interfaces;

namespace xTermsAndConditionsService.Providers
{
    /// <summary>
    /// an Implementation of Terms and Conditions Management Provided Actions ...
    /// </summary>
    public class XTermsAndConditionsProvider : XBaseResourceProvider, IXTermsAndConditionsProvider
    {
        public XTermsAndConditionsProvider(
            IXStringServiceProvider provider,
            XTermsAndConditionsServiceConfiguration configuration
        ) : base(
            resource: "NULL", 
            provider
        )
        {
            //
            // Since we nee to Set Resource Title of Terms and Conditions 
            // during instancing using Provided Configurations ...
            // set this value here ...
            resource = configuration.ResourceTitle;
        }
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xWebinarService\Configurations\Entities\XWebinarEntityConfiguration.cs

using System;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Metadata.Builders;
using xDataService.Providers;
using xWebinarService.Constants;
using xWebinarService.Models.Entities;

namespace xWebinarService.Configurations.Entities
{
    public class XWebinarEntityConfiguration : XBaseEntityTypeConfiguration<XWebinar, Guid>
    {
        public override void Configure(EntityTypeBuilder<XWebinar> builder)
        {
            builder.ToTable(XWebinarServiceConstants.XWebinarTable);
        }
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xWebinarService\Configurations\Entities\XWebinarSubscriberEntityConfiguration.cs

using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Metadata.Builders;
using xDataService.Providers;
using xWebinarService.Constants;
using xWebinarService.Models.Entities;

namespace xWebinarService.Configurations.Entities
{
    public class XWebinarSubscriberEntityConfiguration : XBaseEntityTypeConfiguration<XWebinarSubscriber, int>
    {
        public override void Configure(EntityTypeBuilder<XWebinarSubscriber> builder)
        {
            builder.ToTable(XWebinarServiceConstants.XWebinarSubscriberTable);
        }
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xWebinarService\Constants\XWebinarServiceConstants.cs

namespace xWebinarService.Constants
{
    public struct XWebinarServiceConstants
    {
        //
        // Service Extensions Log Tag ...
        public const string XWebinarServiceDILogTag = "XWebinarService";

        //
        // Table Mapping Identifiers ...
        public const string XWebinarTable = "Webinars";
        public const string XWebinarSubscriberTable = "WebinarSubscribers";

        //
        // GraphQL Collection Mappings ...
        public const string XWebinarSingleName = "webinar";
        public const string XWebinarCollectionName = "webinars";

        public const string XWebinarSubscriberSingleName = "webinarSubscriber";
        public const string XWebinarSubscriberCollectionName = "webinarSubscribers";

        //
        // Hubs ...
        public const string XWebinarDtoHub = "webinarDto";
        public const string XWebinarEntityHub = "webinarEntity";
        public const string XWebinarSubscriberDtoHub = "webinarSubscriberDto";
        public const string XWebinarSubscriberEntityHub = "webinarSubscriberEntity";

        //
        // Custome Constants ...

        //
        // EF Repositories Helper Extensions ...   
        public const string GetXWebinarEFRepositoryDescriptor = "GetXWebinarEFRepositoryDescriptor";
        public const string GetXWebinarSubscriberEFRepositoryDescriptor = "GetXWebinarSubscriberEFRepositoryDescriptor";
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xWebinarService\Constants\XWebinarType.cs

using xExceptions.Attributes;

namespace xWebinarService.Constants
{
    /// <summary>
    /// Webinar Type ...
    /// </summary>
    public enum XWebinarType
    {
        [StringValue("Public")]
        Public = 0,
        [StringValue("Private")]
        Private = 1
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xWebinarService\DI\XDIHelperExtension.cs

using System;
using Microsoft.AspNetCore.Builder;
using Microsoft.Extensions.DependencyInjection;
using xCommons.Extensions;
using xCommons.Helpers;
using xDataService.Constants;
using xDataService.Db;
using xDataService.DI;
using xDataService.Models;
using xExceptions.Constants;
using xPushService.DI;
using xPushService.Helpers;
using xWebinarService.Constants;
using xWebinarService.Helpers;
using xWebinarService.Interfaces.Dtos;
using xWebinarService.Interfaces.Entities;
using xWebinarService.Providers.Dtos;
using xWebinarService.Providers.Entities;

namespace xWebinarService.DI
{
    public static class XDIHelperExtension
    {
        /// <summary>
        /// Register Service ...
        /// </summary>
        /// <param name="services"></param>
        /// <param name="repositoryType"></param>
        /// <param name="lifeTime"></param>
        public static void AddXWebinarService(
            this IServiceCollection services,
            XRepositoryType repositoryType,
            ServiceLifetime lifeTime = ServiceLifetime.Scoped
        )
        {
            AddWebinarService(
                contextType: null,
                services: services,
                lifeTime: lifeTime,
                repositoryType: repositoryType
            );
        }

        /// <summary>
        /// Register Service ...
        /// </summary>
        /// <typeparam name="TContext"></typeparam>
        /// <param name="services"></param>
        /// <param name="repositoryType"></param>
        /// <param name="lifeTime"></param>
        public static void AddXWebinarService<TContext>(
            this IServiceCollection services,
            XRepositoryType repositoryType,
            ServiceLifetime lifeTime = ServiceLifetime.Scoped
        )
        where TContext : XDbContext
        {
            AddWebinarService(
                services: services,
                lifeTime: lifeTime,
                contextType: typeof(TContext),
                repositoryType: repositoryType
            );
        }

        /// <summary>
        /// Use XWebinarService Middleware ... 
        /// </summary>
        /// <param name="app"></param>
        /// <param name="isDevelopmentEnvironment"></param>
        public static void UsexWebinarService(
            this IApplicationBuilder app,
            bool isDevelopmentEnvironment = false
        )
        {
            //
            #region  Using XWebinar Hubs ...
            //
            var pushHelper = new XPushServiceHelper();

            //
            pushHelper.AddHub<XWebinarDtoHub>(XWebinarServiceConstants.XWebinarDtoHub);
            pushHelper.AddHub<XWebinarEntityHub>(XWebinarServiceConstants.XWebinarEntityHub);

            //
            pushHelper.AddHub<XWebinarSubscriberDtoHub>(XWebinarServiceConstants.XWebinarSubscriberDtoHub);
            pushHelper.AddHub<XWebinarSubscriberEntityHub>(XWebinarServiceConstants.XWebinarSubscriberEntityHub);

            //
            app.UseXPushService(pushHelper);
            #endregion

            //
            // Using XWebinar Repository Descriptor ...
            if (!webinarDescriptor.IsNull())
            {
                //
                app.UseXRepository(
                    descriptor: webinarDescriptor,
                    isDevelopmentEnvironment: isDevelopmentEnvironment
                );
            }

            //
            // Using XWebinarSubscriber Repository Descriptor ...
            if (!webinarSubscriberDescriptor.IsNull())
            {
                //
                app.UseXRepository(
                    descriptor: webinarSubscriberDescriptor,
                    isDevelopmentEnvironment: isDevelopmentEnvironment
                );
            }
        }

        //
        #region Private ...
        private static XRepositoryDescriptor webinarDescriptor = null;
        private static XRepositoryDescriptor webinarSubscriberDescriptor = null;

        /// <summary>
        /// a LogTag for Service ...
        /// </summary>
        private static string XLogTag = XWebinarServiceConstants.XWebinarServiceDILogTag;

        /// <summary>
        /// print a log in Console ...
        /// </summary>
        /// <param name="message"></param>
        private static void Log(string message)
        {
            Console.WriteLine($"{XLogTag} => {message}");
        }

        /// <summary>
        /// Register Service ...
        /// </summary>
        /// <param name="services"></param>
        /// <param name="repositoryType"></param>
        /// <param name="contextType"></param>
        /// <param name="lifeTime"></param>
        private static void AddWebinarService(
            IServiceCollection services,
            XRepositoryType repositoryType,
            Type contextType = null,
            ServiceLifetime lifeTime = ServiceLifetime.Scoped
        )
        {
            //
            var exception = XException.InvalidArgs.ToException(); ;

            //
            // Services ...
            var isServicesExists = !services.IsNull();
            if (!isServicesExists)
            {
                //
                Log("Service Registration failed, services not provided ...");
                throw exception;
            }

            //
            // Lifetime ...
            var isLifetimeExists = !lifeTime.IsNull();
            if (!isLifetimeExists)
            {
                //
                Log("Service Registration failed, lifetime not provided ...");
                throw exception;
            }

            //
            // Validate Repository Type ...
            var isRepositoryTypeValid =
                (repositoryType == XRepositoryType.EF &&
                !contextType.IsNull()) ||
                ((repositoryType == XRepositoryType.Mongo ||
                    repositoryType == XRepositoryType.InMemory) &&
                contextType.IsNull());
            if (!isRepositoryTypeValid)
            {
                //
                Log("Service Registration failed, Invalid Repository Type and Context Type ...");
                throw exception;
            }

            //
            // Maske Instance of Repository Descriptor 
            // Based on Provided Type ...
            switch (repositoryType)
            {
                //
                case XRepositoryType.EF:
                    //
                    webinarDescriptor = typeof(XWebinarServiceHelper)
                        .InvokeGenericMethod<XRepositoryDescriptor>(
                            args: null,
                            runtimeType: contextType,
                            methodName: XWebinarServiceConstants.GetXWebinarEFRepositoryDescriptor
                    );

                    //
                    webinarSubscriberDescriptor = typeof(XWebinarServiceHelper)
                        .InvokeGenericMethod<XRepositoryDescriptor>(
                            args: null,
                            runtimeType: contextType,
                            methodName: XWebinarServiceConstants.GetXWebinarSubscriberEFRepositoryDescriptor
                    );
                    break;

                //
                case XRepositoryType.Mongo:
                    webinarDescriptor = XWebinarServiceHelper.GetXWebinarMongoRepositoryDescriptor();
                    webinarSubscriberDescriptor = XWebinarServiceHelper.GetXWebinarSubscriberMongoRepositoryDescriptor();
                    break;

                //
                case XRepositoryType.InMemory:
                    webinarDescriptor = XWebinarServiceHelper.GetXWebinarInMemoryRepositoryDescriptor();
                    webinarSubscriberDescriptor = XWebinarServiceHelper.GetXWebinarSubscriberInMemoryRepositoryDescriptor();
                    break;
            }

            //
            // Register xWebinar Repository Descriptor ...
            services.AddXRepository(
                lifeTime: lifeTime,
                descriptor: webinarDescriptor
            );

            services.AddXRepository(
                lifeTime: lifeTime,
                descriptor: webinarSubscriberDescriptor
            );

            //
            // Register Dto Services ...
            services.Add(
                new ServiceDescriptor(typeof(IXWebinarServiceProvider), typeof(XWebinarServiceProvider), lifeTime)
            );
            services.Add(
                new ServiceDescriptor(typeof(IXWebinarRepositoryService), typeof(XWebinarRepositoryService), lifeTime)
            );
            services.Add(
                new ServiceDescriptor(typeof(IXWebinarRepositoryProvider), typeof(XWebinarRepositoryProvider), lifeTime)
            );

            services.Add(
                new ServiceDescriptor(typeof(IXWebinarSubscriberServiceProvider), typeof(XWebinarSubscriberServiceProvider), lifeTime)
            );
            services.Add(
                new ServiceDescriptor(typeof(IXWebinarSubscriberRepositoryService), typeof(XWebinarSubscriberRepositoryService), lifeTime)
            );
            services.Add(
                new ServiceDescriptor(typeof(IXWebinarSubscriberRepositoryProvider), typeof(XWebinarSubscriberRepositoryProvider), lifeTime)
            );

            //
            // services.Add(
            //     new ServiceDescriptor(typeof(IXWebinarProvider), typeof(XWebinarProvider), lifeTime)
            // );

            //
            Log("Service Regitration Succeed ...");
        }
        #endregion
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xWebinarService\Helpers\XWebinarServiceHelper.cs

using System;
using GraphQL.Types;
using xDataService.Db;
using xDataService.Models;
using xDataService.Providers;
using xWebinarService.Interfaces;
using xWebinarService.Interfaces.Entities;
using xWebinarService.Models.Entities;
using xWebinarService.Providers.Entities;
using xWebinarService.Providers.GraphQL;

namespace xWebinarService.Helpers
{
    public static class XWebinarServiceHelper
    {
        //
        #region XWebinar ...
        //
        #region EF Repository Descriptor Provider(s) ...
        public static XEFRepositoryDescriptor<
            XWebinar,
            Guid,
            IXWebinarKeyGenerator,
            XWebinarKeyGenerator,
            IXWebinarRepositoryEvents,
            XWebinarRepositoryEvents,
            XWebinarGraphType,
            GuidGraphType,
            XWebinarGraphQuery,
            IXWebinarGraphQLTypeHelper,
            XWebinarGraphQLTypeHelper,
            XWebinarGraphSchema,
            IXWebinarRepository,
            XWebinarEFRepository<TContext>,
            TContext
        > GetXWebinarEFRepositoryDescriptor<TContext>()
        where TContext : XDbContext
        {
            //
            var result = new XEFRepositoryDescriptor<
                XWebinar,
                Guid,
                IXWebinarKeyGenerator,
                XWebinarKeyGenerator,
                IXWebinarRepositoryEvents,
                XWebinarRepositoryEvents,
                XWebinarGraphType,
                GuidGraphType,
                XWebinarGraphQuery,
                IXWebinarGraphQLTypeHelper,
                XWebinarGraphQLTypeHelper,
                XWebinarGraphSchema,
                IXWebinarRepository,
                XWebinarEFRepository<TContext>,
                TContext
            >();

            //
            return result;
        }

        public static XEFRepositoryDescriptor<
            XWebinar,
            Guid,
            IXWebinarKeyGenerator,
            XWebinarKeyGenerator,
            IXWebinarRepositoryEvents,
            XWebinarRepositoryEvents,
            XWebinarGraphType,
            GuidGraphType,
            XWebinarGraphQuery,
            IXWebinarGraphQLTypeHelper,
            XWebinarGraphQLTypeHelper,
            XWebinarGraphSchema,
            IXWebinarRepository,
            XWebinarEFRepository<TContext>,
            TContext,
            IXWebinarSeeder,
            TSeederImplementation
        > GetXWebinarEFRepositoryDescriptor<TContext, TSeederImplementation>()
        where TContext : XDbContext
        where TSeederImplementation : XBaseDbSeeder<XWebinar, Guid>
        {
            //
            var result = new XEFRepositoryDescriptor<
                XWebinar,
                Guid,
                IXWebinarKeyGenerator,
                XWebinarKeyGenerator,
                IXWebinarRepositoryEvents,
                XWebinarRepositoryEvents,
                XWebinarGraphType,
                GuidGraphType,
                XWebinarGraphQuery,
                IXWebinarGraphQLTypeHelper,
                XWebinarGraphQLTypeHelper,
                XWebinarGraphSchema,
                IXWebinarRepository,
                XWebinarEFRepository<TContext>,
                TContext,
                IXWebinarSeeder,
                TSeederImplementation
            >();

            //
            return result;
        }
        #endregion

        //
        #region Mongo Repository Descriptor Provider(s) ...
        public static XMongoRepositoryDescriptor<
            XWebinar,
            Guid,
            IXWebinarKeyGenerator,
            XWebinarKeyGenerator,
            IXWebinarRepositoryEvents,
            XWebinarRepositoryEvents,
            XWebinarGraphType,
            GuidGraphType,
            XWebinarGraphQuery,
            IXWebinarGraphQLTypeHelper,
            XWebinarGraphQLTypeHelper,
            XWebinarGraphSchema,
            IXWebinarRepository,
            XWebinarMongoRepository
        > GetXWebinarMongoRepositoryDescriptor()
        {
            //
            var result = new XMongoRepositoryDescriptor<
                XWebinar,
                Guid,
                IXWebinarKeyGenerator,
                XWebinarKeyGenerator,
                IXWebinarRepositoryEvents,
                XWebinarRepositoryEvents,
                XWebinarGraphType,
                GuidGraphType,
                XWebinarGraphQuery,
                IXWebinarGraphQLTypeHelper,
                XWebinarGraphQLTypeHelper,
                XWebinarGraphSchema,
                IXWebinarRepository,
                XWebinarMongoRepository
            >();

            //
            return result;
        }

        public static XMongoRepositoryDescriptor<
            XWebinar,
            Guid,
            IXWebinarKeyGenerator,
            XWebinarKeyGenerator,
            IXWebinarRepositoryEvents,
            XWebinarRepositoryEvents,
            XWebinarGraphType,
            GuidGraphType,
            XWebinarGraphQuery,
            IXWebinarGraphQLTypeHelper,
            XWebinarGraphQLTypeHelper,
            XWebinarGraphSchema,
            IXWebinarRepository,
            XWebinarMongoRepository,
            IXWebinarSeeder,
            TSeederImplementation
        > GetXWebinarMongoRepositoryDescriptor<TSeederImplementation>()
        where TSeederImplementation : XBaseDbSeeder<XWebinar, Guid>
        {
            //
            var result = new XMongoRepositoryDescriptor<
                XWebinar,
                Guid,
                IXWebinarKeyGenerator,
                XWebinarKeyGenerator,
                IXWebinarRepositoryEvents,
                XWebinarRepositoryEvents,
                XWebinarGraphType,
                GuidGraphType,
                XWebinarGraphQuery,
                IXWebinarGraphQLTypeHelper,
                XWebinarGraphQLTypeHelper,
                XWebinarGraphSchema,
                IXWebinarRepository,
                XWebinarMongoRepository,
                IXWebinarSeeder,
                TSeederImplementation
            >();

            //
            return result;
        }
        #endregion

        //
        #region InMemory Repository Descriptor Provider(s) ...
        public static XInMemoryRepositoryDescriptor<
            XWebinar,
            Guid,
            IXWebinarKeyGenerator,
            XWebinarKeyGenerator,
            IXWebinarRepositoryEvents,
            XWebinarRepositoryEvents,
            XWebinarGraphType,
            GuidGraphType,
            XWebinarGraphQuery,
            IXWebinarGraphQLTypeHelper,
            XWebinarGraphQLTypeHelper,
            XWebinarGraphSchema,
            IXWebinarRepository,
            XWebinarInMemoryRepository
        > GetXWebinarInMemoryRepositoryDescriptor()
        {
            //
            var result = new XInMemoryRepositoryDescriptor<
                XWebinar,
                Guid,
                IXWebinarKeyGenerator,
                XWebinarKeyGenerator,
                IXWebinarRepositoryEvents,
                XWebinarRepositoryEvents,
                XWebinarGraphType,
                GuidGraphType,
                XWebinarGraphQuery,
                IXWebinarGraphQLTypeHelper,
                XWebinarGraphQLTypeHelper,
                XWebinarGraphSchema,
                IXWebinarRepository,
                XWebinarInMemoryRepository
            >();

            //
            return result;
        }

        public static XInMemoryRepositoryDescriptor<
            XWebinar,
            Guid,
            IXWebinarKeyGenerator,
            XWebinarKeyGenerator,
            IXWebinarRepositoryEvents,
            XWebinarRepositoryEvents,
            XWebinarGraphType,
            GuidGraphType,
            XWebinarGraphQuery,
            IXWebinarGraphQLTypeHelper,
            XWebinarGraphQLTypeHelper,
            XWebinarGraphSchema,
            IXWebinarRepository,
            XWebinarInMemoryRepository,
            IXWebinarSeeder,
            TSeederImplementation
        > GetXWebinarInMemoryRepositoryDescriptor<TSeederImplementation>()
        where TSeederImplementation : XBaseDbSeeder<XWebinar, Guid>
        {
            //
            var result = new XInMemoryRepositoryDescriptor<
                XWebinar,
                Guid,
                IXWebinarKeyGenerator,
                XWebinarKeyGenerator,
                IXWebinarRepositoryEvents,
                XWebinarRepositoryEvents,
                XWebinarGraphType,
                GuidGraphType,
                XWebinarGraphQuery,
                IXWebinarGraphQLTypeHelper,
                XWebinarGraphQLTypeHelper,
                XWebinarGraphSchema,
                IXWebinarRepository,
                XWebinarInMemoryRepository,
                IXWebinarSeeder,
                TSeederImplementation
            >();

            //
            return result;
        }
        #endregion        
        #endregion

        //
        #region XWebinarSubscriber ...
        //
        #region EF Repository Descriptor Provider(s) ...
        public static XEFRepositoryDescriptor<
            XWebinarSubscriber,
            int,
            IXWebinarSubscriberKeyGenerator,
            XWebinarSubscriberKeyGenerator,
            IXWebinarSubscriberRepositoryEvents,
            XWebinarSubscriberRepositoryEvents,
            XWebinarSubscriberGraphType,
            IntGraphType,
            XWebinarSubscriberGraphQuery,
            IXWebinarSubscriberGraphQLTypeHelper,
            XWebinarSubscriberGraphQLTypeHelper,
            XWebinarSubscriberGraphSchema,
            IXWebinarSubscriberRepository,
            XWebinarSubscriberEFRepository<TContext>,
            TContext
        > GetXWebinarSubscriberEFRepositoryDescriptor<TContext>()
        where TContext : XDbContext
        {
            //
            var result = new XEFRepositoryDescriptor<
                XWebinarSubscriber,
                int,
                IXWebinarSubscriberKeyGenerator,
                XWebinarSubscriberKeyGenerator,
                IXWebinarSubscriberRepositoryEvents,
                XWebinarSubscriberRepositoryEvents,
                XWebinarSubscriberGraphType,
                IntGraphType,
                XWebinarSubscriberGraphQuery,
                IXWebinarSubscriberGraphQLTypeHelper,
                XWebinarSubscriberGraphQLTypeHelper,
                XWebinarSubscriberGraphSchema,
                IXWebinarSubscriberRepository,
                XWebinarSubscriberEFRepository<TContext>,
                TContext
            >();

            //
            return result;
        }

        public static XEFRepositoryDescriptor<
            XWebinarSubscriber,
            int,
            IXWebinarSubscriberKeyGenerator,
            XWebinarSubscriberKeyGenerator,
            IXWebinarSubscriberRepositoryEvents,
            XWebinarSubscriberRepositoryEvents,
            XWebinarSubscriberGraphType,
            IntGraphType,
            XWebinarSubscriberGraphQuery,
            IXWebinarSubscriberGraphQLTypeHelper,
            XWebinarSubscriberGraphQLTypeHelper,
            XWebinarSubscriberGraphSchema,
            IXWebinarSubscriberRepository,
            XWebinarSubscriberEFRepository<TContext>,
            TContext,
            IXWebinarSubscriberSeeder,
            TSeederImplementation
        > GetXWebinarSubscriberEFRepositoryDescriptor<TContext, TSeederImplementation>()
        where TContext : XDbContext
        where TSeederImplementation : XBaseDbSeeder<XWebinarSubscriber, int>
        {
            //
            var result = new XEFRepositoryDescriptor<
                XWebinarSubscriber,
                int,
                IXWebinarSubscriberKeyGenerator,
                XWebinarSubscriberKeyGenerator,
                IXWebinarSubscriberRepositoryEvents,
                XWebinarSubscriberRepositoryEvents,
                XWebinarSubscriberGraphType,
                IntGraphType,
                XWebinarSubscriberGraphQuery,
                IXWebinarSubscriberGraphQLTypeHelper,
                XWebinarSubscriberGraphQLTypeHelper,
                XWebinarSubscriberGraphSchema,
                IXWebinarSubscriberRepository,
                XWebinarSubscriberEFRepository<TContext>,
                TContext,
                IXWebinarSubscriberSeeder,
                TSeederImplementation
            >();

            //
            return result;
        }
        #endregion

        //
        #region Mongo Repository Descriptor Provider(s) ...
        public static XMongoRepositoryDescriptor<
            XWebinarSubscriber,
            int,
            IXWebinarSubscriberKeyGenerator,
            XWebinarSubscriberKeyGenerator,
            IXWebinarSubscriberRepositoryEvents,
            XWebinarSubscriberRepositoryEvents,
            XWebinarSubscriberGraphType,
            IntGraphType,
            XWebinarSubscriberGraphQuery,
            IXWebinarSubscriberGraphQLTypeHelper,
            XWebinarSubscriberGraphQLTypeHelper,
            XWebinarSubscriberGraphSchema,
            IXWebinarSubscriberRepository,
            XWebinarSubscriberMongoRepository
        > GetXWebinarSubscriberMongoRepositoryDescriptor()
        {
            //
            var result = new XMongoRepositoryDescriptor<
                XWebinarSubscriber,
                int,
                IXWebinarSubscriberKeyGenerator,
                XWebinarSubscriberKeyGenerator,
                IXWebinarSubscriberRepositoryEvents,
                XWebinarSubscriberRepositoryEvents,
                XWebinarSubscriberGraphType,
                IntGraphType,
                XWebinarSubscriberGraphQuery,
                IXWebinarSubscriberGraphQLTypeHelper,
                XWebinarSubscriberGraphQLTypeHelper,
                XWebinarSubscriberGraphSchema,
                IXWebinarSubscriberRepository,
                XWebinarSubscriberMongoRepository
            >();

            //
            return result;
        }

        public static XMongoRepositoryDescriptor<
            XWebinarSubscriber,
            int,
            IXWebinarSubscriberKeyGenerator,
            XWebinarSubscriberKeyGenerator,
            IXWebinarSubscriberRepositoryEvents,
            XWebinarSubscriberRepositoryEvents,
            XWebinarSubscriberGraphType,
            IntGraphType,
            XWebinarSubscriberGraphQuery,
            IXWebinarSubscriberGraphQLTypeHelper,
            XWebinarSubscriberGraphQLTypeHelper,
            XWebinarSubscriberGraphSchema,
            IXWebinarSubscriberRepository,
            XWebinarSubscriberMongoRepository,
            IXWebinarSubscriberSeeder,
            TSeederImplementation
        > GetXWebinarSubscriberMongoRepositoryDescriptor<TSeederImplementation>()
        where TSeederImplementation : XBaseDbSeeder<XWebinarSubscriber, int>
        {
            //
            var result = new XMongoRepositoryDescriptor<
                XWebinarSubscriber,
                int,
                IXWebinarSubscriberKeyGenerator,
                XWebinarSubscriberKeyGenerator,
                IXWebinarSubscriberRepositoryEvents,
                XWebinarSubscriberRepositoryEvents,
                XWebinarSubscriberGraphType,
                IntGraphType,
                XWebinarSubscriberGraphQuery,
                IXWebinarSubscriberGraphQLTypeHelper,
                XWebinarSubscriberGraphQLTypeHelper,
                XWebinarSubscriberGraphSchema,
                IXWebinarSubscriberRepository,
                XWebinarSubscriberMongoRepository,
                IXWebinarSubscriberSeeder,
                TSeederImplementation
            >();

            //
            return result;
        }
        #endregion

        //
        #region InMemory Repository Descriptor Provider(s) ...
        public static XInMemoryRepositoryDescriptor<
            XWebinarSubscriber,
            int,
            IXWebinarSubscriberKeyGenerator,
            XWebinarSubscriberKeyGenerator,
            IXWebinarSubscriberRepositoryEvents,
            XWebinarSubscriberRepositoryEvents,
            XWebinarSubscriberGraphType,
            IntGraphType,
            XWebinarSubscriberGraphQuery,
            IXWebinarSubscriberGraphQLTypeHelper,
            XWebinarSubscriberGraphQLTypeHelper,
            XWebinarSubscriberGraphSchema,
            IXWebinarSubscriberRepository,
            XWebinarSubscriberInMemoryRepository
        > GetXWebinarSubscriberInMemoryRepositoryDescriptor()
        {
            //
            var result = new XInMemoryRepositoryDescriptor<
                XWebinarSubscriber,
                int,
                IXWebinarSubscriberKeyGenerator,
                XWebinarSubscriberKeyGenerator,
                IXWebinarSubscriberRepositoryEvents,
                XWebinarSubscriberRepositoryEvents,
                XWebinarSubscriberGraphType,
                IntGraphType,
                XWebinarSubscriberGraphQuery,
                IXWebinarSubscriberGraphQLTypeHelper,
                XWebinarSubscriberGraphQLTypeHelper,
                XWebinarSubscriberGraphSchema,
                IXWebinarSubscriberRepository,
                XWebinarSubscriberInMemoryRepository
            >();

            //
            return result;
        }

        public static XInMemoryRepositoryDescriptor<
            XWebinarSubscriber,
            int,
            IXWebinarSubscriberKeyGenerator,
            XWebinarSubscriberKeyGenerator,
            IXWebinarSubscriberRepositoryEvents,
            XWebinarSubscriberRepositoryEvents,
            XWebinarSubscriberGraphType,
            IntGraphType,
            XWebinarSubscriberGraphQuery,
            IXWebinarSubscriberGraphQLTypeHelper,
            XWebinarSubscriberGraphQLTypeHelper,
            XWebinarSubscriberGraphSchema,
            IXWebinarSubscriberRepository,
            XWebinarSubscriberInMemoryRepository,
            IXWebinarSubscriberSeeder,
            TSeederImplementation
        > GetXWebinarSubscriberInMemoryRepositoryDescriptor<TSeederImplementation>()
        where TSeederImplementation : XBaseDbSeeder<XWebinarSubscriber, int>
        {
            //
            var result = new XInMemoryRepositoryDescriptor<
                XWebinarSubscriber,
                int,
                IXWebinarSubscriberKeyGenerator,
                XWebinarSubscriberKeyGenerator,
                IXWebinarSubscriberRepositoryEvents,
                XWebinarSubscriberRepositoryEvents,
                XWebinarSubscriberGraphType,
                IntGraphType,
                XWebinarSubscriberGraphQuery,
                IXWebinarSubscriberGraphQLTypeHelper,
                XWebinarSubscriberGraphQLTypeHelper,
                XWebinarSubscriberGraphSchema,
                IXWebinarSubscriberRepository,
                XWebinarSubscriberInMemoryRepository,
                IXWebinarSubscriberSeeder,
                TSeederImplementation
            >();

            //
            return result;
        }
        #endregion        
        #endregion
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xWebinarService\Interfaces\Dtos\IXWebinarDtoHub.cs

using System;
using xPushService.Interfaces;
using xWebinarService.Models.Dtos;
using xWebinarService.Models.Entities;

namespace xWebinarService.Interfaces.Dtos
{
    public interface IXWebinarDtoHub : IXBaseDtoHub<XWebinar, XWebinarDto, Guid>
    { }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xWebinarService\Interfaces\Dtos\IXWebinarRepositoryService.cs

using System;
using xDataService.Interfaces;
using xWebinarService.Models.Dtos;
using xWebinarService.Models.Entities;

namespace xWebinarService.Interfaces.Dtos
{
    public interface IXWebinarRepositoryService : IXBaseRepositoryService<XWebinar, XWebinarDto, Guid>
    { }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xWebinarService\Interfaces\Dtos\IXWebinarServiceProvider.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using xPushService.Interfaces;
using xWebinarService.Models.Dtos;
using xWebinarService.Models.Entities;
using xWebinarService.Providers.Dtos;

namespace xWebinarService.Interfaces.Dtos
{
    public interface IXWebinarServiceProvider : IXBaseDtoProvider<XWebinar, XWebinarDto, Guid, XWebinarDtoHub>
    { }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xWebinarService\Interfaces\Dtos\IXWebinarSubscriberDtoHub.cs

using xPushService.Interfaces;
using xWebinarService.Models.Dtos;
using xWebinarService.Models.Entities;

namespace xWebinarService.Interfaces.Dtos
{
    public interface IXWebinarSubscriberDtoHub : IXBaseDtoHub<XWebinarSubscriber, XWebinarSubscriberDto, int>
    { }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xWebinarService\Interfaces\Dtos\IXWebinarSubscriberRepositoryService.cs

using xDataService.Interfaces;
using xWebinarService.Models.Dtos;
using xWebinarService.Models.Entities;

namespace xWebinarService.Interfaces.Dtos
{
    public interface IXWebinarSubscriberRepositoryService : IXBaseRepositoryService<XWebinarSubscriber, XWebinarSubscriberDto, int>
    { }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xWebinarService\Interfaces\Dtos\IXWebinarSubscriberServiceProvider.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;

namespace xWebinarService.Interfaces.Dtos
{
    public interface IXWebinarSubscriberServiceProvider
    {
        
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xWebinarService\Interfaces\Entities\IXWebinarEntityHub.cs

using System;
using xPushService.Interfaces;
using xWebinarService.Models.Entities;

namespace xWebinarService.Interfaces.Entities
{
    public interface IXWebinarEntityHub : IXBaseEntityHub<XWebinar, Guid>
    { }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xWebinarService\Interfaces\Entities\IXWebinarGraphQLTypeHelper.cs

using System;
using xDataService.Interfaces;
using xWebinarService.Models.Entities;

namespace xWebinarService.Interfaces.Entities
{
    public interface IXWebinarGraphQLTypeHelper : IXBaseGraphQLTypeHelper<XWebinar, Guid>
    { }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xWebinarService\Interfaces\Entities\IXWebinarKeyGenerator.cs

using System;
using xDataService.Interfaces;
using xWebinarService.Models.Entities;

namespace xWebinarService.Interfaces.Entities
{
    public interface IXWebinarKeyGenerator : IXKeyGenerator<XWebinar, Guid>
    { }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xWebinarService\Interfaces\Entities\IXWebinarRepository.cs

using System;
using xDataService.Interfaces;
using xWebinarService.Models.Entities;

namespace xWebinarService.Interfaces.Entities
{
    public interface IXWebinarRepository : IXBaseRepository<XWebinar, Guid>
    { }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xWebinarService\Interfaces\Entities\IXWebinarRepositoryEvents.cs

using xDataService.Interfaces;
using xWebinarService.Models.Entities;

namespace xWebinarService.Interfaces.Entities
{
    public interface IXWebinarRepositoryEvents : IXBaseRepositoryEvents<XWebinar>
    { }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xWebinarService\Interfaces\Entities\IXWebinarRepositoryProvider.cs

using System;
using xPushService.Interfaces;
using xWebinarService.Models.Entities;
using xWebinarService.Providers.Entities;

namespace xWebinarService.Interfaces.Entities
{
    public interface IXWebinarRepositoryProvider : IXBaseEntityProvider<XWebinar, Guid, XWebinarEntityHub>
    { }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xWebinarService\Interfaces\Entities\IXWebinarSeeder.cs

using System;
using xDataService.Interfaces;
using xWebinarService.Models.Entities;

namespace xWebinarService.Interfaces.Entities
{
    public interface IXWebinarSeeder : IXBaseDbSeeder<XWebinar, Guid>
    { }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xWebinarService\Interfaces\Entities\IXWebinarSubscriberEntityHub.cs

using xPushService.Interfaces;
using xWebinarService.Models.Entities;

namespace xWebinarService.Interfaces.Entities
{
    public interface IXWebinarSubscriberEntityHub : IXBaseEntityHub<XWebinarSubscriber, int>
    { }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xWebinarService\Interfaces\Entities\IXWebinarSubscriberGraphQLTypeHelper.cs

using xDataService.Interfaces;
using xWebinarService.Models.Entities;

namespace xWebinarService.Interfaces.Entities
{
    public interface IXWebinarSubscriberGraphQLTypeHelper : IXBaseGraphQLTypeHelper<XWebinarSubscriber, int>
    { }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xWebinarService\Interfaces\Entities\IXWebinarSubscriberKeyGenerator.cs

using xDataService.Interfaces;
using xWebinarService.Models.Entities;

namespace xWebinarService.Interfaces.Entities
{
    public interface IXWebinarSubscriberKeyGenerator : IXKeyGenerator<XWebinarSubscriber, int>
    { }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xWebinarService\Interfaces\Entities\IXWebinarSubscriberRepository.cs

using xDataService.Interfaces;
using xWebinarService.Models.Entities;

namespace xWebinarService.Interfaces.Entities
{
    public interface IXWebinarSubscriberRepository : IXBaseRepository<XWebinarSubscriber, int>
    { }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xWebinarService\Interfaces\Entities\IXWebinarSubscriberRepositoryEvents.cs

using xDataService.Interfaces;
using xWebinarService.Models.Entities;

namespace xWebinarService.Interfaces.Entities
{
    public interface IXWebinarSubscriberRepositoryEvents : IXBaseRepositoryEvents<XWebinarSubscriber>
    { }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xWebinarService\Interfaces\Entities\IXWebinarSubscriberRepositoryProvider.cs

using xPushService.Interfaces;
using xWebinarService.Models.Entities;
using xWebinarService.Providers.Entities;

namespace xWebinarService.Interfaces.Entities
{
    public interface IXWebinarSubscriberRepositoryProvider : IXBaseEntityProvider<XWebinarSubscriber, int, XWebinarSubscriberEntityHub>
    { }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xWebinarService\Interfaces\Entities\IXWebinarSubscriberSeeder.cs

using xDataService.Interfaces;
using xWebinarService.Models.Entities;

namespace xWebinarService.Interfaces.Entities
{
    public interface IXWebinarSubscriberSeeder : IXBaseDbSeeder<XWebinarSubscriber, int>
    { }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xWebinarService\Models\Dtos\XWebinarDto.cs

using System;
using xModels.Base;
using xModels.Dtos;
using xWebinarService.Constants;

namespace xWebinarService.Models.Dtos
{
    public class XWebinarDto : XBaseGuidIDEntityDto
    {
        public bool Enabled { get; set; }
        public string OwnerId { get; set; }
        public XPersonDto Owner { get; set; }
        public XWebinarType Type { get; set; }
        public XResourceDto Title { get; set; }
        public DateTime CreatedOn { get; set; }
        public XResourceDto Description { get; set; }
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xWebinarService\Models\Dtos\XWebinarSubscriberDto.cs

using System;
using xModels.Base;
using xModels.Dtos;

namespace xWebinarService.Models.Dtos
{
    public class XWebinarSubscriberDto : XBaseIntIDEntityDto
    {
        public Guid WebinarId { get; set; }
        public string SubscriberId { get; set; }
        public XPersonDto Subscriber { get; set; }  
        public DateTime SubscribedOn { get; set; }        
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xWebinarService\Models\Entities\XWebinar.cs

using System;
using System.ComponentModel.DataAnnotations;
using xModels.Base;
using xWebinarService.Constants;

namespace xWebinarService.Models.Entities
{
    /// <summary>
    /// Webinar Entity ...
    /// </summary>
    public class XWebinar : XBaseGuidIDEntity
    {
        /// <summary>
        /// Title (Resource ID) ...
        /// </summary>
        /// <value></value>
        [Required]
        [StringLength(255)]
        public string Title { get; set; }

        /// <summary>
        /// Description (Resource ID) ...
        /// </summary>
        /// <value></value>
        [Required]
        [StringLength(255)]
        public string Description { get; set; }

        /// <summary>
        /// User Identifier ...
        /// </summary>
        /// <value></value>
        [Required]
        public string OwnerId { get; set; }

        /// <summary>
        /// Webinar Type ...
        /// </summary>
        public XWebinarType Type { get; set; }

        /// <summary>
        /// Creation Time ...
        /// </summary>
        /// <value></value>
        [Required]
        public DateTime CreatedOn { get; set; }

        /// <summary>
        /// Specified Webinar Enabled or not ...
        /// </summary>
        /// <value></value>
        public bool Enabled { get; set; }        
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xWebinarService\Models\Entities\XWebinarSubscriber.cs

using System;
using System.ComponentModel.DataAnnotations;
using xModels.Base;

namespace xWebinarService.Models.Entities
{
    /// <summary>
    /// Webinar Subscriber ...
    /// </summary>
    public class XWebinarSubscriber : XBaseIntIDEntity
    {
        [Required]
        public string SubscriberId { get; set; }

        [Required]
        public Guid WebinarId { get; set; }
        
        public DateTime SubscribedOn { get; set; }
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xWebinarService\Providers\Dtos\XWebinarDtoHub.cs

using System;
using Microsoft.Extensions.Logging;
using xPushService.Base;
using xWebinarService.Interfaces.Dtos;
using xWebinarService.Models.Dtos;
using xWebinarService.Models.Entities;

namespace xWebinarService.Providers.Dtos
{
    public class XWebinarDtoHub : XBaseDtoHub<XWebinar, XWebinarDto, Guid>, IXWebinarDtoHub
    {
        public XWebinarDtoHub(
            ILogger<XWebinarDtoHub> logger
        ) : base(logger)
        { }
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xWebinarService\Providers\Dtos\XWebinarRepositoryService.cs

using System;
using System.Collections.Generic;
using AutoMapper;
using xDataService.Providers;
using xWebinarService.Interfaces.Dtos;
using xWebinarService.Interfaces.Entities;
using xWebinarService.Models.Dtos;
using xWebinarService.Models.Entities;

namespace xWebinarService.Providers.Dtos
{
    public class XWebinarRepositoryService : XBaseRepositoryService<XWebinar, XWebinarDto, Guid>, IXWebinarRepositoryService
    {
        public XWebinarRepositoryService(
            IXWebinarRepository repository,
            IEnumerable<Profile> mapperProfiles = null
        ) : base(
            repository,
            mapperProfiles
        )
        { }
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xWebinarService\Providers\Dtos\XWebinarServiceProvider.cs

using System;
using Microsoft.AspNetCore.SignalR;
using xDataService.Configuration;
using xIdentityService.Interfaces;
using xPushService.Base;
using xWebinarService.Interfaces.Dtos;
using xWebinarService.Models.Dtos;
using xWebinarService.Models.Entities;

namespace xWebinarService.Providers.Dtos
{
    public class XWebinarServiceProvider : XBaseDtoProvider<XWebinar, XWebinarDto, Guid, XWebinarDtoHub>, IXWebinarServiceProvider
    {
        public XWebinarServiceProvider(
            IHubContext<XWebinarDtoHub> hub,
            XDataServiceConfiguration dataConfiguration,
            IXWebinarRepositoryService service,
            IXIdentityProvider identityProvider = null
        ) : base(
            hub,
            dataConfiguration,
            service,
            identityProvider
        )
        { }
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xWebinarService\Providers\Dtos\XWebinarSubscriberDtoHub.cs

using Microsoft.Extensions.Logging;
using xPushService.Base;
using xWebinarService.Interfaces.Dtos;
using xWebinarService.Models.Dtos;
using xWebinarService.Models.Entities;

namespace xWebinarService.Providers.Dtos
{
    public class XWebinarSubscriberDtoHub : XBaseDtoHub<XWebinarSubscriber, XWebinarSubscriberDto, int>, IXWebinarSubscriberDtoHub
    {
        public XWebinarSubscriberDtoHub(
            ILogger<XWebinarSubscriberDtoHub> logger
        ) : base(logger)
        { }
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xWebinarService\Providers\Dtos\XWebinarSubscriberRepositoryService.cs

using System.Collections.Generic;
using AutoMapper;
using xDataService.Providers;
using xWebinarService.Interfaces.Dtos;
using xWebinarService.Interfaces.Entities;
using xWebinarService.Models.Dtos;
using xWebinarService.Models.Entities;

namespace xWebinarService.Providers.Dtos
{
    public class XWebinarSubscriberRepositoryService : XBaseRepositoryService<XWebinarSubscriber, XWebinarSubscriberDto, int>, IXWebinarSubscriberRepositoryService
    {
        public XWebinarSubscriberRepositoryService(
            IXWebinarSubscriberRepository repository,
            IEnumerable<Profile> mapperProfiles = null
        ) : base(
            repository,
            mapperProfiles
        )
        { }
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xWebinarService\Providers\Dtos\XWebinarSubscriberServiceProvider.cs

using Microsoft.AspNetCore.SignalR;
using xDataService.Configuration;
using xIdentityService.Interfaces;
using xPushService.Base;
using xWebinarService.Interfaces.Dtos;
using xWebinarService.Models.Dtos;
using xWebinarService.Models.Entities;

namespace xWebinarService.Providers.Dtos
{
    public class XWebinarSubscriberServiceProvider : XBaseDtoProvider<XWebinarSubscriber, XWebinarSubscriberDto, int, XWebinarSubscriberDtoHub>, IXWebinarSubscriberServiceProvider
    {
        public XWebinarSubscriberServiceProvider(
            IHubContext<XWebinarSubscriberDtoHub> hub,
            XDataServiceConfiguration dataConfiguration,
            IXWebinarSubscriberRepositoryService service,
            IXIdentityProvider identityProvider = null
        ) : base(
            hub,
            dataConfiguration,
            service,
            identityProvider
        )
        { }
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xWebinarService\Providers\Entities\XWebinarEFRepository.cs

using System;
using xDataService.Configuration;
using xDataService.Db;
using xDataService.Interfaces;
using xDataService.Providers;
using xWebinarService.Interfaces.Entities;
using xWebinarService.Models.Entities;

namespace xWebinarService.Providers.Entities
{
    public class XWebinarEFRepository<TContext> : XBaseEFRepository<XWebinar, Guid, TContext>, IXWebinarRepository
    where TContext : XDbContext
    {
        public XWebinarEFRepository(
            IXUnitOfWorks<TContext> unitOfWorks,
            XDataServiceConfiguration configuration,
            IXWebinarKeyGenerator keyGenerator = null,
            IXWebinarRepositoryEvents baseRepositoryEvents = null
        ) : base(
            unitOfWorks,
            configuration,
            keyGenerator,
            baseRepositoryEvents
        )
        { }
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xWebinarService\Providers\Entities\XWebinarEntityHub.cs

using System;
using Microsoft.Extensions.Logging;
using xPushService.Base;
using xWebinarService.Interfaces.Entities;
using xWebinarService.Models.Entities;

namespace xWebinarService.Providers.Entities
{
    public class XWebinarEntityHub : XBaseEntityHub<XWebinar, Guid>, IXWebinarEntityHub
    {
        public XWebinarEntityHub(
            ILogger<XWebinarEntityHub> logger
        ) : base(logger)
        { }
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xWebinarService\Providers\Entities\XWebinarInMemoryRepository.cs

using System;
using xDataService.Configuration;
using xDataService.Providers;
using xWebinarService.Interfaces.Entities;
using xWebinarService.Models.Entities;

namespace xWebinarService.Providers.Entities
{
    public class XWebinarInMemoryRepository : XBaseInMemoryRepository<XWebinar, Guid>, IXWebinarRepository
    {
        public XWebinarInMemoryRepository(
            XDataServiceConfiguration configuration,
            IXWebinarKeyGenerator keyGenerator = null,
            IXWebinarRepositoryEvents baseRepositoryEvents = null
        ) : base(
            configuration,
            keyGenerator,
            baseRepositoryEvents
        )
        { }
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xWebinarService\Providers\Entities\XWebinarKeyGenerator.cs

using xDataService.Providers;
using xWebinarService.Interfaces.Entities;
using xWebinarService.Models.Entities;

namespace xWebinarService.Providers.Entities
{
    public class XWebinarKeyGenerator : XGuidKeyGenerator<XWebinar>, IXWebinarKeyGenerator
    { }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xWebinarService\Providers\Entities\XWebinarMongoRepository.cs

using System;
using xDataService.Configuration;
using xDataService.Providers;
using xWebinarService.Interfaces.Entities;
using xWebinarService.Models.Entities;

namespace xWebinarService.Providers.Entities
{
    public class XWebinarMongoRepository : XBaseMongoRepository<XWebinar, Guid>, IXWebinarRepository
    {
        public XWebinarMongoRepository(
            XDataBaseConfiguration dbConfiguration,
            XDataServiceConfiguration configuration,
            string collectionName = null,
            IXWebinarKeyGenerator keyGenerator = null,
            IXWebinarRepositoryEvents baseRepositoryEvents = null
        ) : base(
            dbConfiguration,
            configuration,
            collectionName,
            keyGenerator,
            baseRepositoryEvents
        )
        { }
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xWebinarService\Providers\Entities\XWebinarRepositoryEvents.cs

using xDataService.Providers;
using xWebinarService.Interfaces.Entities;
using xWebinarService.Models.Entities;

namespace xWebinarService.Providers.Entities
{
    public class XWebinarRepositoryEvents : XBaseRepositoryEvents<XWebinar>, IXWebinarRepositoryEvents
    { }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xWebinarService\Providers\Entities\XWebinarRepositoryProvider.cs

using System;
using Microsoft.AspNetCore.SignalR;
using xDataService.Configuration;
using xIdentityService.Interfaces;
using xPushService.Base;
using xWebinarService.Interfaces.Entities;
using xWebinarService.Models.Entities;

namespace xWebinarService.Providers.Entities
{
    public class XWebinarRepositoryProvider : XBaseEntityProvider<XWebinar, Guid, XWebinarEntityHub>, IXWebinarRepositoryProvider
    {
        public XWebinarRepositoryProvider(
            IHubContext<XWebinarEntityHub> hub,
            IXWebinarRepository repository,
            XDataServiceConfiguration dataConfiguration,
            IXIdentityProvider identityProvider = null
        ) : base(
            hub,
            repository,
            dataConfiguration,
            identityProvider
        )
        { }
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xWebinarService\Providers\Entities\XWebinarSeederBase.cs

using System;
using xDataService.Configuration;
using xDataService.Providers;
using xWebinarService.Interfaces.Entities;
using xWebinarService.Models.Entities;

namespace xWebinarService.Providers.Entities
{
    public abstract class XWebinarSeederBase : XBaseDbSeeder<XWebinar, Guid>, IXWebinarSeeder
    {
        public XWebinarSeederBase(
            string entity,
            string database,
            IXWebinarRepository repository,
            XDataServiceConfiguration dataServiceConfiguration
        ) : base(
            entity,
            database,
            repository,
            dataServiceConfiguration
        )
        { }
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xWebinarService\Providers\Entities\XWebinarSubscriberEFRepository.cs

using xDataService.Configuration;
using xDataService.Db;
using xDataService.Interfaces;
using xDataService.Providers;
using xWebinarService.Interfaces.Entities;
using xWebinarService.Models.Entities;

namespace xWebinarService.Providers.Entities
{
    public class XWebinarSubscriberEFRepository<TContext> : XBaseEFRepository<XWebinarSubscriber, int, TContext>, IXWebinarSubscriberRepository
    where TContext : XDbContext
    {
        public XWebinarSubscriberEFRepository(
            IXUnitOfWorks<TContext> unitOfWorks,
            XDataServiceConfiguration configuration,
            IXWebinarSubscriberKeyGenerator keyGenerator = null,
            IXWebinarSubscriberRepositoryEvents baseRepositoryEvents = null
        ) : base(
            unitOfWorks,
            configuration,
            keyGenerator,
            baseRepositoryEvents
        )
        { }
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xWebinarService\Providers\Entities\XWebinarSubscriberEntityHub.cs

using Microsoft.Extensions.Logging;
using xPushService.Base;
using xWebinarService.Interfaces.Entities;
using xWebinarService.Models.Entities;

namespace xWebinarService.Providers.Entities
{
    public class XWebinarSubscriberEntityHub : XBaseEntityHub<XWebinarSubscriber, int>, IXWebinarSubscriberEntityHub
    {
        public XWebinarSubscriberEntityHub(
            ILogger<XWebinarSubscriberEntityHub> logger
        ) : base(logger)
        { }
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xWebinarService\Providers\Entities\XWebinarSubscriberInMemoryRepository.cs

using xDataService.Configuration;
using xDataService.Providers;
using xWebinarService.Interfaces.Entities;
using xWebinarService.Models.Entities;

namespace xWebinarService.Providers.Entities
{
    public class XWebinarSubscriberInMemoryRepository : XBaseInMemoryRepository<XWebinarSubscriber, int>, IXWebinarSubscriberRepository
    {
        public XWebinarSubscriberInMemoryRepository(
            XDataServiceConfiguration configuration,
            IXWebinarSubscriberKeyGenerator keyGenerator = null,
            IXWebinarSubscriberRepositoryEvents baseRepositoryEvents = null
        ) : base(
            configuration,
            keyGenerator,
            baseRepositoryEvents
        )
        { }
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xWebinarService\Providers\Entities\XWebinarSubscriberKeyGenerator.cs

using xDataService.Providers;
using xWebinarService.Interfaces.Entities;
using xWebinarService.Models.Entities;

namespace xWebinarService.Providers.Entities
{
    public class XWebinarSubscriberKeyGenerator : XIntKeyGenerator<XWebinarSubscriber>, IXWebinarSubscriberKeyGenerator
    { }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xWebinarService\Providers\Entities\XWebinarSubscriberMongoRepository.cs

using xDataService.Configuration;
using xDataService.Providers;
using xWebinarService.Interfaces.Entities;
using xWebinarService.Models.Entities;

namespace xWebinarService.Providers.Entities
{
    public class XWebinarSubscriberMongoRepository : XBaseMongoRepository<XWebinarSubscriber, int>, IXWebinarSubscriberRepository
    {
        public XWebinarSubscriberMongoRepository(
            XDataBaseConfiguration dbConfiguration,
            XDataServiceConfiguration configuration,
            string collectionName = null,
            IXWebinarSubscriberKeyGenerator keyGenerator = null,
            IXWebinarSubscriberRepositoryEvents baseRepositoryEvents = null
        ) : base(
            dbConfiguration,
            configuration,
            collectionName,
            keyGenerator,
            baseRepositoryEvents
        )
        { }
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xWebinarService\Providers\Entities\XWebinarSubscriberRepositoryEvents.cs

using xDataService.Providers;
using xWebinarService.Interfaces.Entities;
using xWebinarService.Models.Entities;

namespace xWebinarService.Providers.Entities
{
    public class XWebinarSubscriberRepositoryEvents : XBaseRepositoryEvents<XWebinarSubscriber>, IXWebinarSubscriberRepositoryEvents
    { }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xWebinarService\Providers\Entities\XWebinarSubscriberRepositoryProvider.cs

using System;
using Microsoft.AspNetCore.SignalR;
using xDataService.Configuration;
using xIdentityService.Interfaces;
using xPushService.Base;
using xWebinarService.Interfaces.Entities;
using xWebinarService.Models.Entities;

namespace xWebinarService.Providers.Entities
{
    public class XWebinarSubscriberRepositoryProvider : XBaseEntityProvider<XWebinarSubscriber, int, XWebinarSubscriberEntityHub>, IXWebinarSubscriberRepositoryProvider
    {
        public XWebinarSubscriberRepositoryProvider(
            IHubContext<XWebinarSubscriberEntityHub> hub,
            IXWebinarSubscriberRepository repository,
            XDataServiceConfiguration dataConfiguration,
            IXIdentityProvider identityProvider = null
        ) : base(
            hub,
            repository,
            dataConfiguration,
            identityProvider
        )
        { }
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xWebinarService\Providers\Entities\XWebinarSubscriberSeederBase.cs

using xDataService.Configuration;
using xDataService.Providers;
using xWebinarService.Interfaces.Entities;
using xWebinarService.Models.Entities;

namespace xWebinarService.Providers.Entities
{
    public abstract class XWebinarSubscriberSeederBase : XBaseDbSeeder<XWebinarSubscriber, int>, IXWebinarSubscriberSeeder
    {
        public XWebinarSubscriberSeederBase(
            string entity,
            string database,
            IXWebinarSubscriberRepository repository,
            XDataServiceConfiguration dataServiceConfiguration
        ) : base(
            entity,
            database,
            repository,
            dataServiceConfiguration
        )
        { }
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xWebinarService\Providers\GraphQL\XWebinarGraphQLTypeHelper.cs

using System;
using xDataService.Configuration;
using xDataService.GraphQL;
using xWebinarService.Constants;
using xWebinarService.Interfaces.Entities;
using xWebinarService.Models.Entities;

namespace xWebinarService.Providers.GraphQL
{
    public class XWebinarGraphQLTypeHelper : XBaseGraphQLTypeHelper<XWebinar, Guid>, IXWebinarGraphQLTypeHelper
    {
        public XWebinarGraphQLTypeHelper(
            XDataServiceConfiguration configuration
        ) : base(configuration)
        { }

        public override string GetInQueryCollectionName()
        {
            return XWebinarServiceConstants.XWebinarCollectionName;
        }

        public override string GetInQuerySingleName()
        {
            return XWebinarServiceConstants.XWebinarSingleName;
        }
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xWebinarService\Providers\GraphQL\XWebinarGraphQuery.cs

using System;
using GraphQL.Types;
using xDataService.Configuration;
using xDataService.GraphQL;
using xWebinarService.Interfaces.Entities;
using xWebinarService.Models.Entities;

namespace xWebinarService.Providers.GraphQL
{
    public class XWebinarGraphQuery : XBaseGraphQLQuery<XWebinar, Guid, XWebinarGraphType, GuidGraphType>
    {
        public XWebinarGraphQuery(
            XDataServiceConfiguration configuration,
            IXWebinarRepository repository,
            IXWebinarGraphQLTypeHelper helper
        ) : base(
            configuration,
            repository,
            helper
        )
        { }
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xWebinarService\Providers\GraphQL\XWebinarGraphSchema.cs

using System;
using GraphQL.Types;

namespace xWebinarService.Providers.GraphQL
{
    public class XWebinarGraphSchema : Schema
    {
        public XWebinarGraphSchema(IServiceProvider services) : base(services)
        {
            Query = (XWebinarGraphQuery)services.GetService(typeof(XWebinarGraphQuery));
        }
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xWebinarService\Providers\GraphQL\XWebinarGraphType.cs

using System;
using xDataService.GraphQL;
using xWebinarService.Models.Entities;

namespace xWebinarService.Providers.GraphQL
{
    public class XWebinarGraphType : XBaseGraphObjectType<XWebinar, Guid>
    {
        public XWebinarGraphType() : base()
        {
            Field(x => x.Type);
            Field(x => x.Title);
            Field(x => x.OwnerId);
            Field(x => x.Enabled);
            Field(x => x.CreatedOn);
            Field(x => x.Description);
        }
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xWebinarService\Providers\GraphQL\XWebinarSubscriberGraphQLTypeHelper.cs

using System;
using xDataService.Configuration;
using xDataService.GraphQL;
using xWebinarService.Constants;
using xWebinarService.Interfaces.Entities;
using xWebinarService.Models.Entities;

namespace xWebinarService.Providers.GraphQL
{
    public class XWebinarSubscriberGraphQLTypeHelper : XBaseGraphQLTypeHelper<XWebinarSubscriber, int>, IXWebinarSubscriberGraphQLTypeHelper
    {
        public XWebinarSubscriberGraphQLTypeHelper(
            XDataServiceConfiguration configuration
        ) : base(configuration)
        { }

        public override string GetInQueryCollectionName()
        {
            return XWebinarServiceConstants.XWebinarSubscriberCollectionName;
        }

        public override string GetInQuerySingleName()
        {
            return XWebinarServiceConstants.XWebinarSubscriberSingleName;
        }
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xWebinarService\Providers\GraphQL\XWebinarSubscriberGraphQuery.cs

using GraphQL.Types;
using xDataService.Configuration;
using xDataService.GraphQL;
using xWebinarService.Interfaces.Entities;
using xWebinarService.Models.Entities;

namespace xWebinarService.Providers.GraphQL
{
    public class XWebinarSubscriberGraphQuery : XBaseGraphQLQuery<XWebinarSubscriber, int, XWebinarSubscriberGraphType, IntGraphType>
    {
        public XWebinarSubscriberGraphQuery(
            XDataServiceConfiguration configuration,
            IXWebinarSubscriberRepository repository,
            IXWebinarSubscriberGraphQLTypeHelper helper
        ) : base(
            configuration,
            repository,
            helper
        )
        { }
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xWebinarService\Providers\GraphQL\XWebinarSubscriberGraphSchema.cs

using System;
using GraphQL.Types;

namespace xWebinarService.Providers.GraphQL
{
    public class XWebinarSubscriberGraphSchema : Schema
    {
        public XWebinarSubscriberGraphSchema(IServiceProvider services) : base(services)
        {
            Query = (XWebinarSubscriberGraphQuery)services.GetService(typeof(XWebinarSubscriberGraphQuery));
        }
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xWebinarService\Providers\GraphQL\XWebinarSubscriberGraphType.cs

using xDataService.GraphQL;
using xWebinarService.Models.Entities;

namespace xWebinarService.Providers.GraphQL
{
    public class XWebinarSubscriberGraphType : XBaseGraphObjectType<XWebinarSubscriber, int>
    {
        public XWebinarSubscriberGraphType() : base()
        {
            Field(x => x.WebinarId);
            Field(x => x.SubscribedOn);
            Field(x => x.SubscriberId);
        }
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xWebinarService\Providers\XWebinarEntityRegisterar.cs

using System;
using Microsoft.EntityFrameworkCore;
using xDataService.Interfaces;
using xDataService.Providers;
using xWebinarService.Configurations.Entities;
using xWebinarService.Models.Entities;

namespace xWebinarService.Providers
{
    public class XWebinarEntityRegisterar : XBaseEntityRegisterar, IXEntityRegisterar
    {
        public XWebinarEntityRegisterar()
        : base(nameof(XWebinarEntityRegisterar))
        {
            //
            // Add Entity ...
            AddEntity<XWebinar, Guid>();
        }

        /// <summary>
        /// Configure Entities ...
        /// </summary>
        /// <param name="modelBuilder"></param>
        public override void ConfigureEntities(ModelBuilder modelBuilder)
        {
            //
            // Configure Entity Using Provided ...
            modelBuilder
                .ApplyConfigurationsFromAssembly(typeof(XWebinarEntityConfiguration).Assembly);

            //
            base.ConfigureEntities(modelBuilder);
        }
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xWebinarService\Providers\XWebinarSubscriberEntityRegisterar.cs

using Microsoft.EntityFrameworkCore;
using xDataService.Interfaces;
using xDataService.Providers;
using xWebinarService.Configurations.Entities;
using xWebinarService.Models.Entities;

namespace xWebinarService.Providers
{
    public class XWebinarSubscriberEntityRegisterar : XBaseEntityRegisterar, IXEntityRegisterar
    {
        public XWebinarSubscriberEntityRegisterar()
        : base(nameof(XWebinarSubscriberEntityRegisterar))
        {
            //
            // Add Entity ...
            AddEntity<XWebinarSubscriber, int>();
        }

        /// <summary>
        /// Configure Entities ...
        /// </summary>
        /// <param name="modelBuilder"></param>
        public override void ConfigureEntities(ModelBuilder modelBuilder)
        {
            //
            // Configure Entity Using Provided ...
            modelBuilder
                .ApplyConfigurationsFromAssembly(typeof(XWebinarSubscriberEntityConfiguration).Assembly);

            //
            base.ConfigureEntities(modelBuilder);
        }
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\xAiApi\Constants\XAiApiConstants.cs

namespace xAiApi.Constants
{
    public struct XAiApiConstants
    {
        //
        // Database Descriptor ...
        public const string XAiApiDbIdentifier = "xAiApiDb";
        public const string XAiApiMigrationsAssemblyIdentifier = "xAiApi";
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\xAiApi\Controllers\StartupController.cs

using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Logging;
using xCommons.Configurations;
using xCommons.Controllers;
using xCommons.Providers;

namespace xAiApi.Controllers
{
    /// <summary>
    /// Runing when application start ...
    /// </summary>
    [Route("")]
    [AllowAnonymous]
    public class StartupController : XBaseController
    {

        public StartupController(
            ILogger<StartupController> logger,
            XAppConfiguration appConfiguration,
            XValidationProvider validationProvider
        ) : base(
            logger,
            appConfiguration,
            validationProvider
        )
        { }

        /// <summary>
        /// Show Configured Welcome Message 
        /// </summary>
        /// <returns></returns>
        [HttpGet("")]
        [AllowAnonymous]
        public virtual ActionResult<string> Index()
        {
            //
            var controllerName = GetControllerName();
            var message = $"{AppConfiguration.WelcomeMessage}";

            //
            return Ok(message);
        }
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\xAiApi\Database\XAiApiDatabaseDescriptor.cs

using xAiApi.Constants;
using xDataService.Interfaces;
using xDataService.Models;

namespace xAiApi.Database
{
    /// <summary>
    /// Ai Api Database Descriptor ... 
    /// </summary>
    public class XAiApiDatabaseDescriptor : XDatabaseDescriptor<XAiApiDbContext>, IXDatabaseDescriptor<XAiApiDbContext>
    {
        public XAiApiDatabaseDescriptor() : base(
            name: XAiApiConstants.XAiApiDbIdentifier,
            repositories: []
        )
        {
            OptionsBuilder = b => b.MigrationsAssembly(XAiApiConstants.XAiApiMigrationsAssemblyIdentifier);
        }
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\xAiApi\Database\XAiApiDbContext.cs

using Microsoft.EntityFrameworkCore;
using xAiApi.Constants;
using xAiModels.Providers;
using xDataService.Configuration;
using xDataService.Db;
using xDataService.Providers;
using xFileService.Providers;
using xStringService.Providers;
using xTagService.Providers;

namespace xAiApi.Database
{
    /// <summary>
    /// Db Context of AiApi ...
    /// </summary>
    public class XAiApiDbContext : XDbContext
    {
        //
        #region DbSets ...
        #endregion

        //
        #region Navigation Property Entities ...
        #endregion

        //
        #region Constructor ...
        public XAiApiDbContext(
            DbContextOptions options,
            XDataServiceConfiguration config,
            XEntityRegisterarHandlerService dynamicEntityHandlers
        ) : base(
            config: config,
            options: options,
            database: XAiApiConstants.XAiApiDbIdentifier,
            dynamicEntityHandlers: dynamicEntityHandlers,
            dynamicEntityRegisterarsNames: [
                nameof(XTagEntityRegisterar),
                nameof(XFileEntityRegisterar),
                nameof(XStringEntityRegisterar),
                nameof(XAiMessageEntityRegisterar),
                nameof(XAiProjectEntityRegisterar),
                nameof(XAiConversationEntityRegisterar),
            ]
        )
        { }
        #endregion

        //
        #region Overrides ...
        //
        public override void OnXModelCreating(ModelBuilder modelBuilder)
        { }

        //
        public override void OnXConfiguring(DbContextOptionsBuilder optionsBuilder)
        { }
        #endregion
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\xAiApi\Extensions\XProgramExtensions.cs

using System.Collections.Generic;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.HttpOverrides;
using Microsoft.Extensions.DependencyInjection;
using xCommons.Authorization;
using xCommons.Extensions;
using xIdentityHelper;

namespace xAiApi.Extensions
{
    public static class XProgramExtensions
    {
        /// <summary>
        /// Register Authorization Policies
        /// </summary>
        /// <param name="services"></param>
        /// <param name="policies"></param>
        public static void AddXAuthorization(
            this IServiceCollection services,
            IDictionary<string, AuthorizationPolicy> policies = null
        )
        {
            //
            services.AddAuthorization(options =>
            {
                //
                if (!policies.IsNull())
                {
                    //
                    // Fill Policies ...
                    using (var policiesEnumerator = policies.GetEnumerator())
                    {
                        while (policiesEnumerator.MoveNext())
                        {
                            var policyDescriptor = policiesEnumerator.Current;
                            options.AddPolicy(policyDescriptor.Key, policyDescriptor.Value);
                        }
                    }
                }

                //
                var xPolicies = XAuthorizationHelper.GetXAuthorizationPolicies();
                if (!xPolicies.IsNull())
                {
                    //
                    // Fill Policies ...
                    using (var policiesEnumerator = xPolicies.GetEnumerator())
                    {
                        while (policiesEnumerator.MoveNext())
                        {
                            var policyDescriptor = policiesEnumerator.Current;
                            options.AddPolicy(policyDescriptor.Key, policyDescriptor.Value);
                        }
                    }
                }
            });

            //
            services.AddSingleton<IAuthorizationHandler, RequiredRolesHandler>();
        }

        /// <summary>
        /// Use Forward Headers Options for resolving behind a proxy issues ...
        /// </summary>
        /// <param name="source"></param>
        /// <returns></returns>
        public static void UseXForwardOptions(this IApplicationBuilder source)
        {
            //
            var forwardOptions = new ForwardedHeadersOptions
            {
                ForwardedHeaders = ForwardedHeaders.XForwardedFor | ForwardedHeaders.XForwardedProto,
                RequireHeaderSymmetry = false
            };

            //
            forwardOptions.KnownNetworks.Clear();
            forwardOptions.KnownProxies.Clear();

            //
            // ref: https://github.com/aspnet/Docs/issues/2384
            source.UseForwardedHeaders(forwardOptions);
        }
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\xAiApi\Interfaces\IXAIApiServiceBase.cs

using System;
using System.Collections.Generic;
using System.Net.Http;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.Extensions.AI;

namespace xAiApi.Interfaces
{
    /// <summary>
    /// Describe a Base Service Actions of any Ai Based Services ...
    /// </summary>
    public interface IAIServiceBase : IDisposable
    {
        /// <summary>
        /// Base Method for Communicate with LLM ...
        /// </summary>
        /// <param name="prompt"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        Task<string> AskAsync(
            string prompt,
            CancellationToken cancellationToken = default
        );

        /// <summary>
        /// Base Method for Communicate with LLM ...
        /// </summary>
        /// <param name="prompt"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        IAsyncEnumerable<string> AskAsEnumerable(
            string prompt,
            CancellationToken cancellationToken = default
        );

        /// <summary>
        /// Get LLM Client instance for Communicating with LLM ...
        /// </summary>
        /// <param name="llm"></param>
        /// <returns></returns>
        IChatClient GetClient(string llm = null);

        /// <summary>
        /// Create Custom HttpClient for Communicating with LLM API ...
        /// </summary>
        /// <param name="url"></param>
        /// <returns></returns>
        HttpClient GetHttpClient(string url = null);

        /// <summary>
        /// Prepare a Message History List for LLM Communication based on Prompt ...
        /// </summary>
        /// <param name="prompt"></param>
        /// <param name="forcePrompt"></param>
        /// <returns></returns>
        IList<ChatMessage> GetHistory(
            string prompt = null,
            bool forcePrompt = true
        );

        /// <summary>
        /// Prepare a Message History List for LLM Communication based on Prompt ...
        /// </summary>
        /// <param name="message"></param>
        /// <param name="forceMessage"></param>
        /// <returns></returns>
        IList<ChatMessage> GetHistory(
            ChatMessage message = null,
            bool forceMessage = true
        );
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\xAiApi\Program.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;

namespace xAiApi
{
    public class Program
    {
        public static void Main(string[] args)
        {
            CreateHostBuilder(args).Build().Run();
        }

        public static IHostBuilder CreateHostBuilder(string[] args) =>
            Host.CreateDefaultBuilder(args)
                .ConfigureWebHostDefaults(webBuilder =>
                {
                    webBuilder.UseStartup<Startup>();
                });
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\xAiApi\Startup.cs

using System;
using System.IO;
using System.Linq;
using xTagService.DI;
using System.Net.Http;
using xAiApi.Database;
using xHttpService.DI;
using xPushService.DI;
using xFileService.DI;
using xDataService.DI;
using Newtonsoft.Json;
using System.Reflection;
using xAiApi.Extensions;
using xStringService.DI;
using xStorageService.DI;
using xIdentityService.DI;
using xDataService.Models;
using xCommons.Extensions;
using xCommons.Configurations;
using System.Collections.Generic;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Hosting;
using Newtonsoft.Json.Serialization;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using IdentityModel.AspNetCore.OAuth2Introspection;
using xPushService.Helpers;

namespace xAiApi
{
    public class Startup
    {
        //
        #region Props ...
        public IConfiguration Configuration { get; }
        private readonly List<XDatabaseDescriptor> databases;
        private readonly XAiApiDatabaseDescriptor apiDatabaseDescriptor;
        #endregion

        //
        #region Constructor(s) ...
        public Startup(IConfiguration configuration)
        {
            //
            Configuration = configuration;

            //
            // Create an Api Descriptor Class Instance ...
            apiDatabaseDescriptor = new XAiApiDatabaseDescriptor();
            databases = new List<XDatabaseDescriptor>
            {
                apiDatabaseDescriptor
            };
        }
        #endregion

        public void ConfigureServices(IServiceCollection services)
        {
            //
            // Register Validation Provider and all XCommons Module Services ...
            services.AddXCommons();

            //
            // Register App Configuration ...
            services.AddXAppConfiguration(Configuration);
            var appConfiguration = services.GetRegisteredService<XAppConfiguration>();

            //
            // Register Allowed Origins ...
            services.AddXCors(appConfiguration.AllowedOrigins);

            //
            // Register Swagger ...
            var xmlFile = $"{Assembly.GetExecutingAssembly().GetName().Name}.xml";
            var xmlPath = Path.Combine(AppContext.BaseDirectory, xmlFile);
            services.AddXSwagger(Configuration, xmlFilePath: xmlPath);

            //
            // Register HttpService ...
            services.AddXHttpService(Configuration);

            //
            // Add Api V1 Versioning ...
            services.AddXApiV1Versioning();

            //
            // OAuthIntrospectin Http Client Handler ...
            // this is for handling SSLErrors ...
            services.AddHttpClient(OAuth2IntrospectionDefaults.BackChannelHttpClientName)
                .ConfigurePrimaryHttpMessageHandler(() =>
                {
                    return new HttpClientHandler
                    {
                        ServerCertificateCustomValidationCallback = (sender, certificate, chain, sslPolicyErrors) => true
                    };
                });

            //
            // Register Authorizations ...
            services.AddXAuthorization();

            //
            services.AddControllers()
                .AddNewtonsoftJson(x =>
                {
                    x.SerializerSettings.ReferenceLoopHandling = ReferenceLoopHandling.Ignore;
                    x.SerializerSettings.ContractResolver = new CamelCasePropertyNamesContractResolver();
                });

            //
            var lifeTime = ServiceLifetime.Scoped;
            var repositoryType = xDataService.Constants.XRepositoryType.EF;

            //
            // Register XIdentity Service ...
            services.AddXIdentityService(
                lifeTime: lifeTime,
                configuration: Configuration
            );

            //
            // Storage Service ...
            services.AddXStorageService(Configuration);

            //
            // Push Service ...
            services.AddXPushService(
                lifeTime: lifeTime,
                config: Configuration
            );

            //
            // Preparing DataBases ...
            if (databases.HasChild())
            {
                //
                databases
                    .ToList()
                    .ForEach(database =>
                    {
                        //
                        // Register DataBase ...
                        services.AddXDatabase(
                            lifeTime: lifeTime,
                            descriptor: database,
                            configuration: Configuration
                        );
                    });
            }

            //
            // Register String Service ...
            services.AddXStringService<XAiApiDbContext>(
                lifeTime: lifeTime,
                repositoryType: repositoryType
            );

            //
            // Register Tag Service ...
            services.AddXTagService<XAiApiDbContext>(
                lifeTime: lifeTime,
                repositoryType: repositoryType
            );

            //
            // Register File Service ...
            services.AddXFileService<XAiApiDbContext>(
                lifeTime: lifeTime,
                repositoryType: repositoryType
            );
        }

        public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
        {
            //
            // Configure the HTTP request pipeline.
            var isDevelopmentEnvironment = false;
            if (env.IsDevelopment())
            {
                isDevelopmentEnvironment = true;
                app.UseDeveloperExceptionPage();
            }

            //
            // Use Swagger Middleware ...
            app.UseXSwagger();

            //
            // Force Https Redirection ...
            app.UseHttpsRedirection();

            //
            // Using Cors ...
            app.UseXCors();

            //
            // Using Routing ...
            app.UseRouting();

            //
            // Use xIdentityService ...
            app.UseXIdentityService();

            //
            // Use Authorization ...
            app.UseAuthorization();

            //
            app.UseEndpoints(endpoints =>
            {
                endpoints.MapControllers();
            });

            //
            // Use Storage Service ...
            app.UseXStorageService();

            //
            // Use PushService ...
            var pushHelper = new XPushServiceHelper();
            app.UseXPushService(pushHelper);

            //
            // Using DataBase ...
            if (databases.HasChild())
            {
                //
                databases
                    .ToList()
                    .ForEach(database =>
                    {
                        //
                        app.UseXDatabase(
                            descriptor: database,
                            isDevelopmentEnvironment: isDevelopmentEnvironment
                        );
                    });
            }

            //
            // Using String Service ...
            app.UseXStringService(
                isDevelopmentEnvironment: isDevelopmentEnvironment
            );

            //
            // Using XTag Service ...
            app.UseXTagService(
                isDevelopmentEnvironment: isDevelopmentEnvironment
            );

            //
            // Using File Service ...
            app.UseXFileService(
                isDevelopmentEnvironment: isDevelopmentEnvironment
            );
        }
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\xApi\Controllers\Account\AccountController+Admin.cs

using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using xIdentityHelper;
using xCommons.Attributes;
using xCommons.Extensions;
using xIdentityModels.Dtos;

namespace xApi.Controllers {
    public partial class AccountController {
        //
        #region Admin Actions ...
        /// <summary>
        /// Ban Specific Users
        /// </summary>
        /// <param name="model">an instance of <see>XUserNameIdRequest</see> which represents user identifier list to Ban</param>
        /// <returns>a list of banned users identifiers</returns>
        [RequireXPowered]
        [HttpPost ("Ban")]
        [Authorize (Policy = XPolicies.EnabledAdmin)]
        public async Task<ActionResult<IEnumerable<string>>> Ban (
            [FromBody] XUserNameIdRequest model
        ) {
            //
            // Do Action ...
            try {
                //
                // Validate Args ...
                await ValidationProvider
                    .GroupValidationBuilder ()
                    .AddNotNull (model)
                    .AddNotZeroChilds (model.Ids)
                    .ValidateGroupAsync ();

                //
                var tokens = await RetrieveTokensAsXTokenResponse ();
                var result = await identityProvider
                    .Ban (
                        tokens,
                        model
                    );

                //
                return Ok (result)
                    .ToDynamicObject ();
            } catch (Exception ex) {
                //
                var exResult = GetExceptionActionResult (ex);
                return exResult;
            }
        }

        /// <summary>
        /// UnBann Specific Users 
        /// </summary>
        /// <param name="model">an instance of <see>XUserNameIdRequest</see> which represents user identifier list to Ban</param>
        /// <returns>a list of unbanned users identifiers</returns>
        [RequireXPowered]
        [HttpPost ("UnBan")]
        [Authorize (Policy = XPolicies.EnabledAdmin)]
        public async Task<ActionResult<IEnumerable<string>>> UnBan (
            [FromBody] XUserNameIdRequest model
        ) {
            //
            // Do Action ...
            try {
                //
                // Validate Args ...
                await ValidationProvider
                    .GroupValidationBuilder ()
                    .AddNotNull (model)
                    .AddNotZeroChilds (model.Ids)
                    .ValidateGroupAsync ();

                //
                var tokens = await RetrieveTokensAsXTokenResponse ();
                var result = await identityProvider
                    .UnBan (
                        tokens,
                        model
                    );

                //
                return Ok (result
                    .ToDynamicObject ());
            } catch (Exception ex) {
                //
                var exResult = GetExceptionActionResult (ex);
                return exResult;
            }
        }

        /// <summary>
        /// Check Specific User is Banned or not
        /// </summary>
        /// <param name="userSelectByParam">specified user's identifier</param>
        /// <returns>a boolean value which represent user banned or not</returns>
        [RequireXPowered]
        [HttpGet ("IsBanned/{userSelectByParam?}")]
        [Authorize (Policy = XPolicies.EnabledAdmin)]
        [Authorize (Policy = XPolicies.EnabledAgent)]
        public async Task<ActionResult<bool>> IsBanned (
            [FromRoute] string userSelectByParam = null
        ) {
            //
            // Do Action ...
            try {
                //
                // Validate Args ...
                if (userSelectByParam.IsNullOrEmpty ()) {
                    userSelectByParam = User.Identity.Name;
                }
                ValidationProvider.NotEmpty (userSelectByParam);

                //
                var tokens = await RetrieveTokensAsXTokenResponse ();
                var result = await identityProvider
                    .IsBanned (
                        tokens,
                        userSelectByParam
                    );

                //
                return Ok (result);
            } catch (Exception ex) {
                //
                var exResult = GetExceptionActionResult (ex);
                return exResult;
            }
        }
        #endregion
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\xApi\Controllers\Account\AccountController+Authentication.cs

using System;
using System.Threading.Tasks;
using IdentityModel.Client;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using xIdentityHelper;
using xCommons.Attributes;
using xCommons.Extensions;
using xExceptions.Constants;
using xIdentityModels.Models;
using xModels.Dtos;
using static xIdentityHelper.XApiScopeHelper;

namespace xApi.Controllers {
    public partial class AccountController {
        //
        #region Authentication Actions ...
        /// <summary>
        /// Retrieve OAuth Discovery Document
        /// </summary>
        /// <returns>an instance of <see>DiscoveryDocumentResponse</see></returns>
        [AllowAnonymous]
        [RequireXPowered]
        [HttpGet ("DiscoveryDocument")]
        public async Task<ActionResult<DiscoveryDocumentResponse>> GetDiscoveryDocument () {
            //
            try {
                //
                var result = await identityProvider
                    .RequestDiscoveryDocument ();

                //
                // Ceck Response Result ...
                if (result.IsError) {
                    XException.InvalidConfiguration.Throw ();
                }

                //
                return Ok (result
                    .ToDynamicObject ());
            } catch (Exception ex) {
                //
                var result = GetExceptionActionResult (ex);
                return result;
            }
        }

        /// <summary>
        /// Request AccessToken for Specific XApiScope
        /// </summary>
        /// <param name="scope">a member of <see>XApiScope</see></param>
        /// <returns>an instance of <see>XTokenResponse</see></returns>
        [AllowAnonymous]
        [RequireXPowered]
        [HttpPost ("RequestScopeAccessToken")]
        public async Task<ActionResult<XTokenResponse>> RequestScopeAccessToken (
            [FromHeader] XApiScope scope
        ) {
            //
            // Do Action ...
            try {
                //
                // Validate Args ...
                var scopeName = string.Empty;
                try {
                    scopeName = scope.GetStringValue ();
                } catch { }
                ValidationProvider.NotEmpty (scopeName);

                //
                var result = await identityProvider
                    .RequestScopeAccessToken (scopeName);

                //
                return Ok (result
                    .ToDynamicObject ());
            } catch (Exception ex) {
                //
                var result = GetExceptionActionResult (ex);
                return result;
            }
        }

        /// <summary>
        /// Authenticate User
        /// </summary>
        /// <remarks>
        /// Sample request:
        /// 
        ///     {
        ///         "password": "",
        ///         "userSelectBy": "",
        ///     }
        /// 
        /// </remarks>
        /// <param name="model">User Login Required Info, an instance of <see>XLoginRequest</see></param>
        /// <returns>an instance of <see>XTokenResponse</see></returns>
        [AllowAnonymous]
        [RequireXPowered]
        [HttpPost ("Authenticate")]
        public async Task<ActionResult<XTokenResponse>> Authenticate (
            [FromBody] XLoginRequest model
        ) {
            try {
                //
                // Validate Args ...
                if (!ModelState.IsValid) {
                    XException.InvalidArgs.Throw ();
                }
                await ValidationProvider
                    .GroupValidationBuilder ()
                    .AddNotNull (model)
                    .AddNotEmpty (
                        model.UserSelectBy,
                        model.Password
                    )
                    .ValidateGroupAsync ();

                //
                var result = await identityProvider
                    .Authenticate (model);

                //
                return Ok (result
                    .ToDynamicObject ());
            } catch (Exception ex) {
                //
                var result = GetExceptionActionResult (ex);
                return result;
            }
        }

        /// <summary>
        /// Authenticate User
        /// </summary>
        /// <remarks>
        /// Sample request:
        /// 
        ///     {
        ///         "language": "fa-IR"
        ///         "password": "",
        ///         "userSelectBy": "",
        ///         "device": {
        ///             "os":"Mac",
        ///             "browser":"Chrome",
        ///             "osVersion":"mac-os-x-15",
        ///             "userAgent":"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_3) AppleWebKit/537.36 (KHTML, like Gecko) x-framework-test/0.0.0 Chrome/87.0.4280.141 Electron/11.2.0 Safari/537.36",
        ///             "deviceType":3,
        ///             "identifier":"[Mac]-[mac-os-x-15]-[3]-[Chrome]-[Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_3) AppleWebKit/537.36 (KHTML, like Gecko) x-framework-test/0.0.0 Chrome/87.0.4280.141 Electron/11.2.0 Safari/537.36]",
        ///             "token":"96f400dd9aa5c57a8cec9d6f4775bad3"
        ///         }
        ///     }
        /// 
        /// </remarks>
        /// <param name="model">User Login Required Info, an instance of <see>XLoginRequest</see></param>
        /// <returns>an instance of <see>XLoginResponse</see></returns>
        [AllowAnonymous]
        [RequireXPowered]
        [HttpPost ("Login")]
        public async Task<ActionResult<XLoginResponse>> Login (
            [FromBody] XLoginRequest model
        ) {
            try {
                //
                // Validate Args ...
                if (!ModelState.IsValid) {
                    XException.InvalidArgs.Throw ();
                }
                await ValidationProvider
                    .GroupValidationBuilder ()
                    .AddNotNull (
                        model,
                        model.Device)
                    .AddNotEmpty (
                        model.Language,
                        model.UserSelectBy,
                        model.Password
                    )
                    .ValidateGroupAsync ();

                //
                var result = await identityProvider
                    .Login (model);

                //
                return Ok (result
                    .ToDynamicObject ());
            } catch (Exception ex) {
                //
                var result = GetExceptionActionResult (ex);
                return result;
            }
        }

        /// <summary>
        /// Logout User
        /// </summary>
        [RequireXPowered]
        [HttpPost ("Logout")]
        [Authorize (Policy = XPolicies.User)]
        public async Task<ActionResult> Logout () {
            try {
                //
                var tokens = await RetrieveTokensAsXTokenResponse ();
                await identityProvider
                    .Logout (tokens);

                //
                return Ok ();
            } catch (Exception ex) {
                //
                var result = GetExceptionActionResult (ex);
                return result;
            }
        }

        /// <summary>
        /// Refresh Expired Tokens
        /// </summary>
        /// <remarks>
        /// in addition to AccessToken, you had to pass RefreshToken due to Headers
        /// </remarks>
        /// <returns>an instance of <see>XTokenResponse</see></returns>
        [AllowAnonymous]
        [RequireXPowered]
        [HttpPost ("RefreshTokens")]
        public async Task<ActionResult<XTokenResponse>> RefreshTokens () {
            //
            try {
                //
                // Retrieve Toke Response ...
                var model = await RetrieveTokensAsXTokenResponse ();

                //
                // Validate Args ...
                ValidationProvider
                    .GroupValidationBuilder ()
                    .AddNotNull (model)
                    .AddNotEmpty (
                        model.AccessToken,
                        model.RefreshToken)
                    .ValidateGroup ();

                //
                var result = await identityProvider
                    .RefreshTokens (model);

                //
                return Ok (result
                    .ToDynamicObject ());
            } catch (Exception ex) {
                //
                var result = GetExceptionActionResult (ex);
                return result;
            }
        }

        /// <summary>
        /// Validate a Revision Checksum
        /// </summary>
        /// <param name="model"></param>
        /// <returns></returns>
        [HttpPost ("Validate")]
        [Authorize (Policy = XPolicies.EnabledUser)]
        public async Task<ActionResult<bool>> Validate (
            [FromBody] XValidateRevisionRequest model
        ) {
            //
            // Do Action ...
            try {
                //
                // Validate Args ...
                await ValidationProvider
                    .GroupValidationBuilder ()
                    .AddNotNull (model)
                    .AddNotEmpty (model.Revision)
                    .ValidateGroupAsync ();

                //
                // Get Request ...
                var tokens = await RetrieveTokensAsXTokenResponse ();
                var result = tokens.ValidateRevisionChecksum (
                    model.Revision,
                    identityProvider.RevisionSecretKey
                );

                //
                // Return Result
                return Ok (result);
            } catch (Exception ex) {
                //
                var result = GetExceptionActionResult (ex);
                return result;
            }
        }
        #endregion

        //
        #region Password Actions ...
        /// <summary>
        /// Change a User's Password ...
        /// </summary>
        /// <remarks>
        ///     for this action you have to provide:
        ///         - Lang: client device currently used locale, such as: en-US.
        ///         - Password: user's current active password.
        ///         - NewPassword: user's new password to change.
        ///         - Device: user's client device which is an instance of XDevice.
        ///         - ReturnUrl: client application Login URL.
        /// 
        /// Sample request:
        /// 
        ///     {
        ///         "lang": "fa-IR",
        ///         "password": ""
        ///         "newPassword": "",
        ///         "returnUrl": "http://localhost/login",
        ///         "device": {
        ///             "os":"Mac",
        ///             "browser":"Chrome",
        ///             "osVersion":"mac-os-x-15",
        ///             "userAgent":"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_3) AppleWebKit/537.36 (KHTML, like Gecko) x-framework-test/0.0.0 Chrome/87.0.4280.141 Electron/11.2.0 Safari/537.36",
        ///             "deviceType":3,
        ///             "identifier":"[Mac]-[mac-os-x-15]-[3]-[Chrome]-[Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_3) AppleWebKit/537.36 (KHTML, like Gecko) x-framework-test/0.0.0 Chrome/87.0.4280.141 Electron/11.2.0 Safari/537.36]",
        ///             "token":"96f400dd9aa5c57a8cec9d6f4775bad3"
        ///         }
        ///     }
        /// 
        /// </remarks>
        /// <param name="model">an instance of <see>XActionRequest</see> class which provider requirement for action</param>
        /// <returns></returns>
        [RequireXPowered]
        [HttpPost ("ChangePassword")]
        [Authorize (Policy = XPolicies.User)]
        [Authorize (Policy = XPolicies.EnabledUser)]
        public async Task<ActionResult> ChangePassword (
            [FromBody] XActionRequest model
        ) {
            //
            // Do Action ...
            try {
                //
                // Validate Args ...
                if (!ModelState.IsValid) {
                    XException.InvalidArgs.Throw ();
                }
                await ValidationProvider
                    .GroupValidationBuilder ()
                    .AddNotNull (
                        model,
                        model.Device
                    )
                    .AddNotEmpty (
                        model.Lang,
                        model.Password,
                        model.NewPassword,
                        model.ReturnUrl
                    )
                    .ValidateGroupAsync ();

                //
                // Get User Select By ...
                var userSelectByParam = GetUserSelectByParam (
                    model,
                    forceNotNull : false
                );
                if (userSelectByParam.IsNullOrEmpty ()) {
                    userSelectByParam = User.Identity.Name;
                }
                ValidationProvider.NotEmpty (userSelectByParam);

                //
                // Get Request ...
                var tokens = await RetrieveTokensAsXTokenResponse ();
                await identityProvider
                    .ChangePassword (tokens, model);

                //
                return Ok ();
            } catch (Exception ex) {
                //
                var exResult = GetExceptionActionResult (ex);
                return exResult;
            }
        }
        #endregion
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\xApi\Controllers\Account\AccountController+Friendship.cs

using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using xIdentityHelper;
using xCommons.Attributes;
using xCommons.Extensions;
using xIdentityModels.Constants;
using xIdentityModels.Dtos;
using xIdentityModels.Navigations;
using xModels.Dtos;
using System.Linq;
using xExceptions.Constants;

namespace xApi.Controllers
{
    public partial class AccountController
    {
        //
        #region Friendship Actions ...
        /// <summary>
        /// Follow a User
        /// </summary>
        /// <param name="destUser">a user identifier which represent destination user</param>
        /// <returns>an instance of <see>XFriendshipFollowing</see></returns>
        [RequireXPowered]
        [HttpPost("Friendship/{destUser}/Follow")]
        [Authorize(Policy = XPolicies.EnabledUser)]
        public async Task<ActionResult<XFriendshipFollowing>> Follow(
            [FromRoute] string destUser
        )
        {
            //
            // Do Action ...
            try
            {
                //
                // Validate Args ...
                ValidationProvider.NotEmpty(destUser);

                //
                var tokens = await RetrieveTokensAsXTokenResponse();
                var result = await identityProvider
                    .Follow(
                        tokens,
                        destUser
                    );

                //
                // Prepare Push Message ...

                //
                return Ok(result
                    .ToDynamicObject());
            }
            catch (Exception ex)
            {
                //
                var exResult = GetExceptionActionResult(ex);
                return exResult;
            }
        }

        /// <summary>
        /// Cancel Following Request 
        /// </summary>
        /// <param name="destUser">a user identifier which represent destination user</param>
        /// <returns>a boolean value</returns>
        [Authorize(Policy = XPolicies.EnabledUser)]
        [HttpPost("Friendship/{destUser}/Cancel")]
        public async Task<ActionResult<bool>> Cancel(
            [FromRoute] string destUser
        )
        {
            //
            // Do Action ...
            try
            {
                //
                // Validate Args ...
                ValidationProvider.NotEmpty(destUser);

                //
                var tokens = await RetrieveTokensAsXTokenResponse();
                var result = await identityProvider
                    .Cancel(
                        tokens,
                        destUser
                    );

                //
                // Prepare Push Message ...

                //
                return Ok(result);
            }
            catch (Exception ex)
            {
                //
                var exResult = GetExceptionActionResult(ex);
                return exResult;
            }
        }

        /// <summary>
        /// Unfollow a Follower
        /// </summary>
        /// <param name="destUser">a user identifier which represent destination user</param>
        /// <returns></returns>
        [Authorize(Policy = XPolicies.EnabledUser)]
        [HttpPost("Friendship/{destUser}/UnFollowFollower")]
        public async Task<ActionResult> UnFollowFollower(
            [FromRoute] string destUser
        )
        {
            //
            // Do Action ...
            try
            {
                //
                // Validate Args ...
                ValidationProvider.NotEmpty(destUser);

                //
                var tokens = await RetrieveTokensAsXTokenResponse();
                await identityProvider
                    .UnFollowFollower(
                        tokens,
                        destUser
                    );

                //
                // Prepare Push Message ...

                //
                return Ok();
            }
            catch (Exception ex)
            {
                //
                var exResult = GetExceptionActionResult(ex);
                return exResult;
            }
        }

        /// <summary>
        /// Unfollow Following
        /// </summary>
        /// <param name="destUser">a user identifier which represent destination user</param>
        /// <returns></returns>
        [Authorize(Policy = XPolicies.EnabledUser)]
        [HttpPost("Friendship/{destUser}/UnFollowFollowing")]
        public async Task<ActionResult> UnFollowFollowing(
            [FromRoute] string destUser
        )
        {
            //
            // Do Action ...
            try
            {
                //
                // Validate Args ...
                ValidationProvider.NotEmpty(destUser);

                //
                var tokens = await RetrieveTokensAsXTokenResponse();
                await identityProvider
                    .UnFollowFollowing(
                        tokens,
                        destUser
                    );

                //
                // Prepare Push Message ...

                //
                return Ok();
            }
            catch (Exception ex)
            {
                //
                var exResult = GetExceptionActionResult(ex);
                return exResult;
            }
        }

        /// <summary>
        /// Block a Follower
        /// </summary>
        /// <param name="destUser">a user identifier which represent destination user</param>
        /// <returns>an instance of <see>XFriendshipFollowing</see></returns>
        [HttpPost("Friendship/{destUser}/Block")]
        [Authorize(Policy = XPolicies.EnabledUser)]
        public async Task<ActionResult<XFriendshipFollowing>> Block(
            [FromRoute] string destUser
        )
        {
            //
            // Do Action ...
            try
            {
                //
                // Validate Args ...
                ValidationProvider.NotEmpty(destUser);

                //
                var tokens = await RetrieveTokensAsXTokenResponse();
                var result = await identityProvider
                    .Block(
                        tokens,
                        destUser
                    );

                //
                // Prepare Push Message ...

                //
                return Ok(result
                    .ToDynamicObject());
            }
            catch (Exception ex)
            {
                //
                var exResult = GetExceptionActionResult(ex);

                //
                return exResult;
            }
        }

        /// <summary>
        /// Unblock a Blocked User
        /// </summary>
        /// <param name="destUser">a user identifier which represent destination user</param>
        /// <returns>an instance of <see>XFriendshipFollowing</see></returns>
        [HttpPost("Friendship/{destUser}/UnBlock")]
        [Authorize(Policy = XPolicies.EnabledUser)]
        public async Task<ActionResult<XFriendshipFollowing>> UnBlock(
            [FromRoute] string destUser
        )
        {
            //
            // Do Action ...
            try
            {
                //
                // Validate Args ...
                ValidationProvider.NotEmpty(destUser);

                //
                var tokens = await RetrieveTokensAsXTokenResponse();
                var result = await identityProvider
                    .UnBlock(
                        tokens,
                        destUser
                    );

                //
                // Prepare Push Message ...

                //
                return Ok(result
                    .ToDynamicObject());
            }
            catch (Exception ex)
            {
                //
                var exResult = GetExceptionActionResult(ex);
                return exResult;
            }
        }

        /// <summary>
        /// Accept a Following Request 
        /// </summary>
        /// <param name="destUser">a user identifier which represent destination user</param>
        /// <returns>an instance of <see>XFriendshipFollower</see></returns>
        [Authorize(Policy = XPolicies.EnabledUser)]
        [HttpPost("Friendship/{destUser}/AcceptRequest")]
        public async Task<ActionResult<XFriendshipFollower>> AcceptRequest(
            [FromRoute] string destUser
        )
        {
            //
            // Do Action ...
            try
            {
                //
                // Validate Args ...
                ValidationProvider.NotEmpty(destUser);

                //
                var tokens = await RetrieveTokensAsXTokenResponse();
                var result = await identityProvider
                    .AcceptRequest(
                        tokens,
                        destUser
                    );

                //
                // Prepare Push Message ...

                //
                return Ok(result
                    .ToDynamicObject());
            }
            catch (Exception ex)
            {
                //
                var exResult = GetExceptionActionResult(ex);
                return exResult;
            }
        }

        /// <summary>
        /// Reject a Following Request
        /// </summary>
        /// <param name="destUser">a user identifier which represent destination user</param>
        /// <returns>an instance of <see>XFriendshipFollower</see></returns>
        [Authorize(Policy = XPolicies.EnabledUser)]
        [HttpPost("Friendship/{destUser}/RejectRequest")]
        public async Task<ActionResult<XFriendshipFollower>> RejectRequest(
            [FromRoute] string destUser
        )
        {
            //
            // Do Action ...
            try
            {
                //
                // Validate Args ...
                ValidationProvider.NotEmpty(destUser);

                //
                var tokens = await RetrieveTokensAsXTokenResponse();
                var result = await identityProvider
                    .RejectRequest(
                        tokens,
                        destUser
                    );

                //
                return Ok(result
                    .ToDynamicObject());
            }
            catch (Exception ex)
            {
                //
                var exResult = GetExceptionActionResult(ex);
                return exResult;
            }
        }
        #endregion

        //
        #region Friendship Getters ...

        /// <summary>
        /// Get Friendship Info Model between Specific User and Current User
        /// </summary>
        /// <param name="destUser">a user identifier which represent destination user</param>
        /// <returns>an instance of <see>XFriendshipInfoDto</see></returns>
        [Authorize(Policy = XPolicies.EnabledUser)]
        [HttpGet("Friendship/{destUser}/FriendshipInfo")]
        public async Task<ActionResult<XFriendshipInfoDto>> FriendshipInfo(
            [FromRoute] string destUser
        )
        {
            //
            // Do Action ...
            try
            {
                //
                // Validate Args ...
                ValidationProvider.NotEmpty(destUser);

                //
                var tokens = await RetrieveTokensAsXTokenResponse();
                var result = await identityProvider
                    .GetFriendshipInfo(
                        tokens,
                        destUser
                    );

                //
                return Ok(result
                    .ToDynamicObject());
            }
            catch (Exception ex)
            {
                //
                var exResult = GetExceptionActionResult(ex);
                return exResult;
            }
        }

        /// <summary>
        /// Check a User IsFollower of Requested User 
        /// </summary>
        /// <param name="destUser">a user identifier which represent destination user</param>
        /// <returns>a boolean value</returns>
        [Authorize(Policy = XPolicies.EnabledUser)]
        [HttpGet("Friendship/{destUser}/IsFollower")]
        public async Task<ActionResult<bool>> IsFollower(
            [FromRoute] string destUser
        )
        {
            //
            // Do Action ...
            try
            {
                //
                // Validate Args ...
                ValidationProvider.NotEmpty(destUser);

                //
                var tokens = await RetrieveTokensAsXTokenResponse();
                var result = await identityProvider
                    .IsFollower(
                        tokens,
                        destUser
                    );

                //
                return Ok(result);
            }
            catch (Exception ex)
            {
                //
                var exResult = GetExceptionActionResult(ex);
                return exResult;
            }
        }

        /// <summary>
        /// Get Follower State of a User
        /// </summary>
        /// <param name="destUser">a user identifier which represent destination user</param>
        /// <returns>an instance of <see>XFriendshipState</see></returns>
        [Authorize(Policy = XPolicies.EnabledUser)]
        [HttpGet("Friendship/{destUser}/FollowerState")]
        public async Task<ActionResult<XFriendshipState>> FollowerState(
            [FromRoute] string destUser
        )
        {
            //
            // Do Action ...
            try
            {
                //
                // Validate Args ...
                ValidationProvider.NotEmpty(destUser);

                //
                var tokens = await RetrieveTokensAsXTokenResponse();
                var result = await identityProvider
                    .GetFollowerState(
                        tokens,
                        destUser
                    );

                //
                return Ok(result);
            }
            catch (Exception ex)
            {
                //
                var exResult = GetExceptionActionResult(ex);
                return exResult;
            }
        }

        /// <summary>
        /// Get Specific Follower 
        /// </summary>
        /// <param name="destUser">a user identifier which represent destination user</param>
        /// <returns>an instance of <see>XFriendshipFollower</see></returns>
        [Authorize(Policy = XPolicies.EnabledUser)]
        [HttpGet("Friendship/{destUser}/Follower")]
        public async Task<ActionResult<XFriendshipFollower>> Follower(
            [FromRoute] string destUser
        )
        {
            //
            // Do Action ...
            try
            {
                //
                // Validate Args ...
                ValidationProvider.NotEmpty(destUser);

                //
                var tokens = await RetrieveTokensAsXTokenResponse();
                var result = await identityProvider
                    .GetFollower(
                        tokens,
                        destUser
                    );

                //
                return Ok(result
                    .ToDynamicObject());
            }
            catch (Exception ex)
            {
                //
                var exResult = GetExceptionActionResult(ex);
                return exResult;
            }
        }

        /// <summary>
        /// Get Followers List Of Current User 
        /// </summary>
        /// <returns>a collection of <see>XFriendshipFollower</see></returns>
        [HttpGet("Friendship/Followers")]
        [Authorize(Policy = XPolicies.EnabledUser)]
        public async Task<ActionResult<IEnumerable<XFriendshipFollower>>> Followers()
        {
            //
            // Do Action ...
            try
            {
                //
                var tokens = await RetrieveTokensAsXTokenResponse();
                var result = await identityProvider
                    .GetFollowers(tokens);

                //
                return Ok(result
                    .ToDynamicObject());
            }
            catch (Exception ex)
            {
                //
                var exResult = GetExceptionActionResult(ex);

                //
                return exResult;
            }
        }

        /// <summary>
        /// Get All Followers List Includes Blocked, Requested and etc 
        /// of Current User
        /// </summary>
        /// <returns>a collection of <see>XFriendshipFollower</see></returns>
        [HttpGet("Friendship/AllFollowers")]
        [Authorize(Policy = XPolicies.EnabledUser)]
        public async Task<ActionResult<IEnumerable<XFriendshipFollower>>> AllFollowers()
        {
            //
            // Do Action ...
            try
            {
                //
                var tokens = await RetrieveTokensAsXTokenResponse();
                var result = await identityProvider
                    .GetAllFollowers(tokens);

                //
                return Ok(result
                    .ToDynamicObject());
            }
            catch (Exception ex)
            {
                //
                var exResult = GetExceptionActionResult(ex);
                return exResult;
            }
        }

        /// <summary>
        /// Get All Followers List Includes Blocked, Requested and etc 
        /// of Current User based On Query Model ...
        /// </summary>
        /// <returns>a Query Result of <see>XFriendDto</see></returns>
        [HttpGet("Friendship/QueryFollowers")]
        [Authorize(Policy = XPolicies.EnabledUser)]
        public async Task<ActionResult<XQueryResult<XFriendDto>>> QueryFollowers(
            [FromQuery] XQuery query,
            [FromQuery] string destUser
        )
        {
            //
            // Do Action ...
            try
            {
                //
                // Normalizing Dest User ...
                var userInfo = await GetUserInfo();
                bool isAdmin = userInfo.Roles.Contains(XUserRoles.ADMIN);
                if (destUser.IsNullOrEmpty())
                {
                    destUser = userInfo.UserName;
                }
                bool isDestUserValid = isAdmin || destUser == userInfo.UserId || destUser == userInfo.Email || destUser == userInfo.PhoneNumber || destUser == userInfo.UserName;
                if (!isDestUserValid)
                {
                    XException.NotAllowed.Throw();
                }

                //
                var tokens = await RetrieveTokensAsXTokenResponse();
                var result = await identityProvider
                    .QueryFollowers(
                        query: query,
                        tokens: tokens,
                        destUser: destUser
                    );

                //
                return Ok(result
                    .ToDynamicObject());
            }
            catch (Exception ex)
            {
                //
                var exResult = GetExceptionActionResult(ex);
                return exResult;
            }
        }

        /// <summary>
        /// Check a User is in Followings of Current User
        /// </summary>
        /// <param name="destUser">a user identifier which represent destination user</param>
        /// <returns>a boolean value</returns>
        [Authorize(Policy = XPolicies.EnabledUser)]
        [HttpGet("Friendship/{destUser}/IsFollowing")]
        public async Task<ActionResult<bool>> IsFollowing(
            [FromRoute] string destUser
        )
        {
            //
            // Do Action ...
            try
            {
                //
                // Validate Args ...
                ValidationProvider.NotEmpty(destUser);

                //
                var tokens = await RetrieveTokensAsXTokenResponse();
                var result = await identityProvider
                    .IsFollowing(
                        tokens,
                        destUser
                    );

                //
                return Ok(result);
            }
            catch (Exception ex)
            {
                //
                var exResult = GetExceptionActionResult(ex);
                return exResult;
            }
        }

        /// <summary>
        /// Get Following State Relation between Specific User 
        /// and Current User
        /// </summary>
        /// <param name="destUser">a user identifier which represent destination user</param>
        /// <returns>an instance of <see>XFriendshipState</see></returns>
        [Authorize(Policy = XPolicies.EnabledUser)]
        [HttpGet("Friendship/{destUser}/FollowingState")]
        public async Task<ActionResult<XFriendshipState>> FollowingState(
            [FromRoute] string destUser
        )
        {
            //
            // Do Action ...
            try
            {
                //
                // Validate Args ...
                ValidationProvider.NotEmpty(destUser);

                //
                var tokens = await RetrieveTokensAsXTokenResponse();
                var result = await identityProvider
                    .GetFollowingState(
                        tokens,
                        destUser
                    );

                //
                return Ok(result);
            }
            catch (Exception ex)
            {
                //
                var exResult = GetExceptionActionResult(ex);
                return exResult;
            }
        }

        /// <summary>
        /// Get Specific Following Model
        /// </summary>
        /// <param name="destUser">a user identifier which represent destination user</param>
        /// <returns>an instance of <see>XFriendshipFollowing</see></returns>
        [Authorize(Policy = XPolicies.EnabledUser)]
        [HttpGet("Friendship/{destUser}/Following")]
        public async Task<ActionResult<XFriendshipFollowing>> Following(
            [FromRoute] string destUser
        )
        {
            //
            // Do Action ...
            try
            {
                //
                // Validate Args ...
                ValidationProvider.NotEmpty(destUser);

                //
                var tokens = await RetrieveTokensAsXTokenResponse();
                var result = await identityProvider
                    .GetFollowing(
                        tokens,
                        destUser
                    );

                //
                return Ok(result
                    .ToDynamicObject());
            }
            catch (Exception ex)
            {
                //
                var exResult = GetExceptionActionResult(ex);
                return exResult;
            }
        }

        /// <summary>
        /// Get Followings of Current User
        /// </summary>
        /// <returns>a collection of <see>XFriendshipFollowing</see></returns>
        [HttpGet("Friendship/Followings")]
        [Authorize(Policy = XPolicies.EnabledUser)]
        public async Task<ActionResult<IEnumerable<XFriendshipFollowing>>> Followings()
        {
            //
            // Do Action ...
            try
            {
                //
                var tokens = await RetrieveTokensAsXTokenResponse();
                var result = await identityProvider
                    .GetFollowings(tokens);

                //
                return Ok(result
                    .ToDynamicObject());
            }
            catch (Exception ex)
            {
                //
                var exResult = GetExceptionActionResult(ex);
                return exResult;
            }
        }

        /// <summary>
        /// Get All Following List Includes Blocked, Requested and etc 
        /// of Current User
        /// </summary>
        /// <returns>a collection of <see>XFriendshipFollowing</see></returns>
        [HttpGet("Friendship/AllFollowings")]
        [Authorize(Policy = XPolicies.EnabledUser)]
        public async Task<ActionResult<IEnumerable<XFriendshipFollowing>>> AllFollowings()
        {
            //
            // Do Action ...
            try
            {
                //
                var tokens = await RetrieveTokensAsXTokenResponse();
                var result = await identityProvider
                    .GetAllFollowings(tokens);

                //
                return Ok(result
                    .ToDynamicObject());
            }
            catch (Exception ex)
            {
                //
                var exResult = GetExceptionActionResult(ex);
                return exResult;
            }
        }

        /// <summary>
        /// Return Following UserName's List of Current User 
        /// </summary>
        /// <returns>a collection of UserNames</returns>
        [HttpGet("Friendship/FollowingsList")]
        [Authorize(Policy = XPolicies.EnabledUser)]
        public async Task<ActionResult<IEnumerable<string>>> FollowingsList()
        {
            //
            // Do Action ...
            try
            {
                //
                var tokens = await RetrieveTokensAsXTokenResponse();
                var result = await identityProvider
                    .GetFollowingList(tokens);

                //
                return Ok(result
                    .ToDynamicObject());
            }
            catch (Exception ex)
            {
                //
                var exResult = GetExceptionActionResult(ex);
                return exResult;
            }
        }

        /// <summary>
        /// Return Followers UserName's List of Current User 
        /// </summary>
        /// <returns>a collection of UserNames</returns>
        [HttpGet("Friendship/FollowersList")]
        [Authorize(Policy = XPolicies.EnabledUser)]
        public async Task<ActionResult<IEnumerable<string>>> FollowersList()
        {
            //
            // Do Action ...
            try
            {
                //
                var tokens = await RetrieveTokensAsXTokenResponse();
                var result = await identityProvider
                    .GetFollowersList(tokens);

                //
                return Ok(result
                    .ToDynamicObject());
            }
            catch (Exception ex)
            {
                //
                var exResult = GetExceptionActionResult(ex);
                return exResult;
            }
        }

        /// <summary>
        /// Get All Followings List Includes Blocked, Requested and etc 
        /// of Current User based On Query Model ...
        /// </summary>
        /// <returns>a Query Result of <see>XFriendDto</see></returns>
        [HttpGet("Friendship/QueryFollowings")]
        [Authorize(Policy = XPolicies.EnabledUser)]
        public async Task<ActionResult<XQueryResult<XFriendDto>>> QueryFollowings(
            [FromQuery] XQuery query,
            [FromQuery] string destUser
       )
        {
            //
            // Do Action ...
            try
            {
                //
                // Normalizing Dest User ...
                var userInfo = await GetUserInfo();
                bool isAdmin = userInfo.Roles.Contains(XUserRoles.ADMIN);
                if (destUser.IsNullOrEmpty())
                {
                    destUser = userInfo.UserName;
                }
                bool isDestUserValid = isAdmin || destUser == userInfo.UserId || destUser == userInfo.Email || destUser == userInfo.PhoneNumber || destUser == userInfo.UserName;
                if (!isDestUserValid)
                {
                    XException.NotAllowed.Throw();
                }

                //
                var tokens = await RetrieveTokensAsXTokenResponse();
                var result = await identityProvider
                    .QueryFollowings(
                        query: query,
                        tokens: tokens,
                        destUser: destUser
                    );

                //
                return Ok(result
                    .ToDynamicObject());
            }
            catch (Exception ex)
            {
                //
                var exResult = GetExceptionActionResult(ex);
                return exResult;
            }
        }
        #endregion
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\xApi\Controllers\Account\AccountController+Open.cs

using System;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using xCommons.Attributes;
using xCommons.Extensions;
using xModels.Dtos;

namespace xApi.Controllers
{
    public partial class AccountController
    {
        #region Open Actions ...
        [AllowAnonymous]
        [RequireXPowered]
        [HttpGet("GetUserInfo")]
        public async Task<ActionResult<string>> GetUserInfo(
            [FromHeader] string token,
            [FromQuery] string request
        )
        {
            //
            // Do Action ...
            try
            {
                //
                // Validate Args ...
                await ValidationProvider
                    .GroupValidationBuilder()
                    .AddNotEmpty(token)
                    .AddNotEmpty(request)
                    .ValidateGroupAsync();

                //
                var result = await identityProvider.GetUserInfo(
                    token: token,
                    request: request
                );

                //
                // Return Result
                return Ok(result
                    .ToDynamicObject());
            }
            catch (Exception ex)
            {
                //
                var result = GetExceptionActionResult(ex);
                return result;
            }
        }

        [AllowAnonymous]
        [RequireXPowered]
        [HttpGet("GetUserInfoByDevice")]
        public async Task<ActionResult<string>> GetUserInfoByDevice(
            [FromQuery] string userSelectByParam,
            [FromBody] XDeviceDto device
        )
        {
            //
            // Do Action ...
            try
            {
                //
                // Validate Args ...
                await ValidationProvider
                    .GroupValidationBuilder()
                    .AddNotEmpty(userSelectByParam)
                    .AddNotNull(device)
                    .ValidateGroupAsync();

                //
                var result = await identityProvider.GetUserInfo(
                    userSelectByParam: userSelectByParam,
                    device: device
                );

                //
                // Return Result
                return Ok(result
                    .ToDynamicObject());
            }
            catch (Exception ex)
            {
                //
                var result = GetExceptionActionResult(ex);
                return result;
            }
        }
        #endregion
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\xApi\Controllers\Account\AccountController+Profile.cs

using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using xIdentityHelper;
using xCommons.Attributes;
using xCommons.Extensions;
using xIdentityModels.Dtos;
using xIdentityModels.Models;
using xModels.Dtos;

namespace xApi.Controllers
{
    public partial class AccountController
    {
        //
        #region Retrieve Actions ...
        /// <summary>
        /// Retrieve User Names based on UserIds
        /// </summary>
        /// <param name="ids">a comma seperated list of UserIds</param>
        /// <returns>a collection of UserNames</returns>
        [RequireXPowered]
        [HttpGet("Profile/{ids}/GetNames")]
        [Authorize(Policy = XPolicies.User)]
        [Authorize(Policy = XPolicies.EnabledUser)]
        public async Task<ActionResult<IEnumerable<string>>> GetNames(
            [FromRoute] string ids
        )
        {
            //
            // Do Action ...
            try
            {
                //
                ValidationProvider.NotEmpty(ids);

                //
                var tokens = await RetrieveTokensAsXTokenResponse();
                var result = await identityProvider.GetUserNames(
                    tokens,
                    ids
                );

                //
                // Return Result
                return Ok(result
                    .ToDynamicObject());
            }
            catch (Exception ex)
            {
                //
                var result = GetExceptionActionResult(ex);
                return result;
            }
        }

        /// <summary>
        /// get user ids and retrieve corresponding user names
        /// </summary>
        /// <param name="model">an instance of <see>XUserNameIdRequest</see> which represent required UserIds collection</param>
        /// <returns>a collection of <see>XUserNameIdResponse</see> instance</returns>
        [RequireXPowered]
        [HttpPost("Profile/GetNameIds")]
        [Authorize(Policy = XPolicies.User)]
        [Authorize(Policy = XPolicies.EnabledUser)]
        public async Task<ActionResult<IEnumerable<XUserNameIdResponse>>> GetNameIds(
            [FromBody] XUserNameIdRequest model
        )
        {
            //
            // Do Action ...
            try
            {
                //
                ValidationProvider.NotNull(model);

                //
                var tokens = await RetrieveTokensAsXTokenResponse();
                var result = await identityProvider.GetUserNameIds(
                    tokens,
                    model
                );

                //
                // Return Result
                return Ok(result
                    .ToDynamicObject());
            }
            catch (Exception ex)
            {
                //
                var result = GetExceptionActionResult(ex);
                return result;
            }
        }

        /// <summary>
        /// Get Profile Object of Specific User 
        /// </summary>
        /// <param name="userSelectByParam">determine's which user profile must be retrieved</param>
        /// <returns>an instance of <see>XUserProfileDto</see></returns>
        [RequireXPowered]
        [Authorize(Policy = XPolicies.User)]
        [HttpGet("Profile/{userSelectByParam?}")]
        [Authorize(Policy = XPolicies.EnabledUser)]
        public async Task<ActionResult<XUserProfileDto>> GetProfile(
            [FromRoute] string userSelectByParam = ""
        )
        {
            //
            // Do Action ...
            try
            {
                //
                // Validate Args ...
                if (userSelectByParam.IsNullOrEmpty())
                {
                    userSelectByParam = User.Identity.Name;
                }
                ValidationProvider.NotEmpty(userSelectByParam);

                //
                var tokens = await RetrieveTokensAsXTokenResponse();
                var result = await identityProvider
                    .GetUserProfile(
                        tokens,
                        userSelectByParam
                    );

                //
                // Return Result
                return Ok(result
                    .ToDynamicObject());
            }
            catch (Exception ex)
            {
                //
                var result = GetExceptionActionResult(ex);
                return result;
            }
        }

        /// <summary>
        /// Query Users 
        /// for specifiy users role for query user 'role: string' and 'forceRole: boolean' in header
        /// </summary>
        /// <param name="query">how to filter results based on <see>XQuery</see> structure</param>
        /// <param name="role">an string which represent user role</param>
        /// <param name="forceRole">if it's true the user must has exact role, otherwise top level users also listed</param>
        /// <returns>an instance of <see>XQueryResult</see> of <see>XUserProfileDto</see></returns>
        [RequireXPowered]
        [HttpGet("Profile/Query")]
        [Authorize(Policy = XPolicies.EnabledAdmin)]
        [Authorize(Policy = XPolicies.EnabledAgent)]
        public async Task<ActionResult<XQueryResult<XUserProfileDto>>> QueryProfiles(
            [FromQuery] XQuery query, [FromHeader] string role, [FromHeader] bool forceRole = false
        )
        {
            //
            // Do Action ...
            try
            {
                //
                var tokens = await RetrieveTokensAsXTokenResponse();
                var result = new XQueryResult<XUserProfileDto>();
                if (role.IsNullOrEmpty())
                {
                    //
                    result = await identityProvider.QueryUsers(
                        tokens,
                        query
                    );
                }
                else
                {
                    //
                    result = await identityProvider.QueryInRoleUsers(
                        tokens,
                        role,
                        query,
                        forceRole
                    );
                }

                //
                return Ok(result
                    .ToDynamicObject());
            }
            catch (Exception ex)
            {
                //
                var exception = GetExceptionActionResult(ex);
                return exception;
            }
        }

        /// <summary>
        /// Query Specified User's Profile Images
        /// </summary>
        /// <param name="userSelectByParam">determine's which user profile must be retrieved</param>
        /// <param name="query">how to filter results based on <see>XQuery</see> structure</param>
        /// <returns>an instance of <see>XQueryResult</see> of <see>XProfileImage</see></returns>
        [RequireXPowered]
        [Authorize(Policy = XPolicies.User)]
        [Authorize(Policy = XPolicies.EnabledUser)]
        [Authorize(Policy = XPolicies.EnabledAdmin)]
        [HttpGet("Profile/Avatars/Query/{userSelectByParam?}")]
        public async Task<ActionResult<XQueryResult<XProfileImageDto>>> QueryAvatars(
            [FromQuery] XQuery query, [FromRoute] string userSelectByParam = null
        )
        {
            //
            // Do Action ...
            try
            {
                //
                if (userSelectByParam.IsNullOrEmpty())
                {
                    userSelectByParam = User.Identity.Name;
                }
                ValidationProvider.NotEmpty(userSelectByParam);

                //
                var tokens = await RetrieveTokensAsXTokenResponse();
                var result = await identityProvider.QueryAvatars(
                    tokens,
                    userSelectByParam,
                    query
                );

                //
                return Ok(result
                    .ToDynamicObject());
            }
            catch (Exception ex)
            {
                //
                var exception = GetExceptionActionResult(ex);
                return exception;
            }
        }
        #endregion

        //
        #region Update Actions ...
        /// <summary>
        /// Update User Profile based on <see>XProfileUpdateRequest</see> (FirstName/LastName/DateOfBirth)
        /// </summary>
        /// <param name="model">user update info, an instance of <see>XProfileUpdateRequest</see></param>
        /// <param name="userSelectByParam">determine's which user profile must be retrieved</param>
        /// <returns>an instance of <see>XUserProfileDto</see></returns>
        [RequireXPowered]
        [Authorize(Policy = XPolicies.EnabledUser)]
        [HttpPost("Profile/Update/{userSelectByParam?}")]
        public async Task<ActionResult<XUserProfileDto>> UpdateProfile(
            [FromBody] XProfileUpdateRequest model, [FromRoute] string userSelectByParam = null
        )
        {
            //
            // Do Action ...
            try
            {
                //
                // Validate Args ...
                if (userSelectByParam.IsNullOrEmpty())
                {
                    userSelectByParam = User.Identity.Name;
                }
                ValidationProvider.NotEmpty(userSelectByParam);

                //
                var tokens = await RetrieveTokensAsXTokenResponse();
                var result = await identityProvider.ProfileUpdateAsync(
                    tokens,
                    userSelectByParam,
                    model
                );

                //
                // Prepare Push Message ...

                //
                // Return Result
                return Ok(result
                    .ToDynamicObject());
            }
            catch (Exception ex)
            {
                //
                var result = GetExceptionActionResult(ex);
                return result;
            }
        }

        /// <summary>
        /// Update a User Profile based on <see>XProfileUpdateRequest</see> Full
        /// </summary>
        /// <param name="model">user update info, an instance of <see>XProfileUpdateRequest</see></param>
        /// <param name="userSelectByParam">determine's which user profile must be retrieved</param>
        /// <returns>an instance of <see>XUserProfileDto</see></returns>
        [RequireXPowered]
        [HttpPost("Profile/{userSelectByParam?}")]
        [Authorize(Policy = XPolicies.EnabledAdminOrAgent)]
        public async Task<ActionResult<XUserProfileDto>> FullUpdateProfile(
            [FromBody] XProfileUpdateRequest model, [FromRoute] string userSelectByParam = null
        )
        {
            //
            // Do Action ...
            try
            {
                //
                // Validate Args ...
                if (userSelectByParam.IsNullOrEmpty())
                {
                    userSelectByParam = User.Identity.Name;
                }
                ValidationProvider.NotEmpty(userSelectByParam);

                //
                var tokens = await RetrieveTokensAsXTokenResponse();
                var result = await identityProvider.FullProfileUpdateAsync(
                    tokens,
                    userSelectByParam,
                    model
                );

                //
                // Prepare Push Message ...

                //
                // Return Result
                return Ok(result
                    .ToDynamicObject());
            }
            catch (Exception ex)
            {
                //
                var result = GetExceptionActionResult(ex);
                return result;
            }
        }
        #endregion

        //
        #region Avatar Actions ...
        /// <summary>
        /// Add a New Profile Image
        /// </summary>
        /// <param name="file">an specific File to upload, <see>IFormFile</see></param>
        /// <returns>an instance of <see>XUserProfileDto</see></returns>
        [RequireXPowered]
        [HttpPost("Profile/Avatar")]
        [RequestSizeLimit(966_367_641)]
        [Authorize(Policy = XPolicies.User)]
        [Authorize(Policy = XPolicies.EnabledUser)]
        public async Task<ActionResult<XUserProfileDto>> AddAvatar(
            [FromForm] IFormFile file
        )
        {
            //
            // Do Action ...
            try
            {
                //
                // Validate Args ...
                ValidationProvider.NotNull(file);

                //
                // Get Request ...
                var tokens = await RetrieveTokensAsXTokenResponse();
                var result = await identityProvider
                    .AddAvatar(
                        tokens,
                        file
                    );

                //
                // Prepare Push Message ...

                //
                return Ok(result
                    .ToDynamicObject());
            }
            catch (Exception ex)
            {
                //
                var exResult = GetExceptionActionResult(ex);
                return exResult;
            }
        }

        /// <summary>
        /// Add a New Collection of Profile Images
        /// </summary>
        /// <param name="files">a collection of Files to upload, <see>IFormFileCollection</see></param>
        /// <returns>an instance of <see>XUserProfileDto</see></returns>
        [RequireXPowered]
        [HttpPost("Profile/Avatars")]
        [RequestSizeLimit(966_367_641)]
        [Authorize(Policy = XPolicies.User)]
        [Authorize(Policy = XPolicies.EnabledUser)]
        public async Task<ActionResult<XUserProfileDto>> AddAvatars(
            [FromForm] IFormFileCollection files
        )
        {
            //
            // Do Action ...
            try
            {
                //
                // Validate Args ...
                ValidationProvider.NotZeroChilds(files);

                //
                // Get Request ...
                var tokens = await RetrieveTokensAsXTokenResponse();
                var result = await identityProvider.AddAvatars(
                    tokens,
                    files
                );

                //
                // Prepare Push Message ...

                //
                return Ok(result
                    .ToDynamicObject());
            }
            catch (Exception ex)
            {
                //
                var exResult = GetExceptionActionResult(ex);
                return exResult;
            }
        }

        /// <summary>
        /// set Specified Profile Image as Avatar
        /// </summary>
        /// <param name="id">an integer which reperesent AvatarId to set as current Avatar</param>
        /// <returns>an instance of <see>XUserProfileDto</see></returns>
        [RequireXPowered]
        [HttpPost("Profile/Avatars/{id:int}/Set")]
        [Authorize(Policy = XPolicies.User)]
        [Authorize(Policy = XPolicies.EnabledUser)]
        public async Task<ActionResult<XUserProfileDto>> SetAvatar(
            [FromRoute] int id
        )
        {
            //
            // Do Action ...
            try
            {
                //
                // Get Request ...
                var tokens = await RetrieveTokensAsXTokenResponse();
                var result = await identityProvider
                    .SetAvatar(
                        tokens,
                        id
                    );

                //
                // Prepare Push Message ...

                //
                return Ok(result
                    .ToDynamicObject());
            }
            catch (Exception ex)
            {
                //
                var exception = GetExceptionActionResult(ex);
                return exception;
            }
        }

        /// <summary>
        /// Remove Profile Images
        /// </summary>
        /// <param name="ids">a comma seperated list of avatarIds to remove</param>
        /// <returns>an instance of <see>XUserProfileDto</see></returns>
        [RequireXPowered]
        [Authorize(Policy = XPolicies.User)]
        [HttpDelete("Profile/Avatars/{ids}")]
        [Authorize(Policy = XPolicies.EnabledUser)]
        public async Task<ActionResult<XUserProfileDto>> RemoveAvatars(
            [FromRoute] string ids
        )
        {
            //
            // Do Action ...
            try
            {
                //
                // Validate Args ...
                ValidationProvider.NotEmpty(ids);

                //
                // Get Request ...
                var tokens = await RetrieveTokensAsXTokenResponse();
                var result = await identityProvider
                    .RemoveAvatars(
                        tokens,
                        ids
                    );

                //
                // Prepare Push Message ...

                //
                return Ok(result
                    .ToDynamicObject());
            }
            catch (Exception ex)
            {
                //
                var result = GetExceptionActionResult(ex);
                return result;
            }
        }
        #endregion        
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\xApi\Controllers\Account\AccountController+Registration.cs

using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using xIdentityHelper;
using xCommons.Attributes;
using xCommons.Extensions;
using xExceptions.Constants;
using xIdentityModels.Constants;
using xIdentityModels.Extensions;
using xIdentityModels.Models;

namespace xApi.Controllers {
    public partial class AccountController {
        //
        #region Registration ...
        /// <summary>
        /// Check a UserName is Available For Registration or not
        /// </summary>
        /// <param name="userName">an string value which represent desired username</param>
        /// <returns>a boolean value</returns>
        [AllowAnonymous]
        [RequireXPowered]
        [HttpGet ("CanRegisterUserName/{userName?}")]
        public async Task<ActionResult<bool>> CanRegisterUserName (
            [FromRoute] string userName
        ) {
            //
            // Do Action ...
            try {
                //
                // Validate Args ...
                ValidationProvider.NotEmpty (userName);

                //
                // Validate Type ...
                var type = userName.GetUserSelectByType ();
                if (type != XUserSelectBy.Username) {
                    XException.InvalidArgs.Throw ();
                }

                //
                var result = await identityProvider
                    .CanRegister (userName);

                //
                // Return Result
                return Ok (result);
            } catch (Exception ex) {
                //
                var result = GetExceptionActionResult (ex);

                //
                return result;
            }
        }

        /// <summary>
        /// Check a Mobile Number is Available For Registration or not
        /// </summary>
        /// <param name="mobileNumber">an string value which represent desired mobile number</param>
        /// <returns>a boolean value</returns>
        [AllowAnonymous]
        [RequireXPowered]
        [HttpGet ("CanRegisterMobileNumber/{mobileNumber?}")]
        public async Task<ActionResult<bool>> CanRegisterMobileNumber (
            [FromRoute] string mobileNumber
        ) {
            //
            // Do Action ...
            try {
                //
                // Validate Args ...
                ValidationProvider.NotEmpty (mobileNumber);

                //
                // Validate Type ...
                var type = mobileNumber.GetUserSelectByType ();
                if (type != XUserSelectBy.MobileNumber) {
                    XException.InvalidArgs.Throw ();
                }

                //
                var result = await identityProvider
                    .CanRegister (mobileNumber);

                //
                // Return Result
                return Ok (result);
            } catch (Exception ex) {
                //
                var result = GetExceptionActionResult (ex);

                //
                return result;
            }
        }

        /// <summary>
        /// Check a Email Address is Available For Registration or not
        /// </summary>
        /// <param name="email">an string value which represent desired email address</param>
        /// <returns>a boolean value</returns>
        [AllowAnonymous]
        [RequireXPowered]
        [HttpGet ("CanRegisterEmail/{email?}")]
        public async Task<ActionResult<bool>> CanRegisterEmail (
            [FromRoute] string email
        ) {
            //
            // Do Action ...
            try {
                //
                // Validate Args ...
                ValidationProvider.NotEmpty (email);

                //
                // Validate Type ...
                var type = email.GetUserSelectByType ();
                if (type != XUserSelectBy.Email) {
                    XException.InvalidArgs.Throw ();
                }

                //
                var result = await identityProvider
                    .CanRegister (email);

                //
                // Return Result
                return Ok (result);
            } catch (Exception ex) {
                //
                var result = GetExceptionActionResult (ex);

                //
                return result;
            }
        }

        /// <summary>
        /// Invite a User to Register on Dashboard
        /// </summary>
        /// <remarks>
        ///     for this action you have to provide: 
        ///         - Lang: client device currently used locale, such as: en-US.
        ///         - Email: which email address is going to invite.
        ///         - Device: user's client device which is an instance of XDevice.
        ///         - ReturnUrl: client application Registration URL.
        ///     notice in this step you had to provide all this informations as FormData
        /// 
        /// Sample request:
        /// 
        ///     {
        ///         "lang": "fa-IR",
        ///         "email": "",
        ///         "returnUrl": "",
        ///         "device": {
        ///             "os":"Mac",
        ///             "browser":"Chrome",
        ///             "osVersion":"mac-os-x-15",
        ///             "userAgent":"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_3) AppleWebKit/537.36 (KHTML, like Gecko) x-framework-test/0.0.0 Chrome/87.0.4280.141 Electron/11.2.0 Safari/537.36",
        ///             "deviceType":3,
        ///             "identifier":"[Mac]-[mac-os-x-15]-[3]-[Chrome]-[Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_3) AppleWebKit/537.36 (KHTML, like Gecko) x-framework-test/0.0.0 Chrome/87.0.4280.141 Electron/11.2.0 Safari/537.36]",
        ///             "token":"96f400dd9aa5c57a8cec9d6f4775bad3"
        ///         }
        ///     }
        /// 
        /// </remarks>
        /// <param name="model">an instance of <see>XActionRequest</see> class which provider requirement for action</param>
        /// <returns>an instance of <see>XActionResponse</see></returns>
        [RequireXPowered]
        [HttpPost ("InviteUser")]
        [Authorize (Policy = XPolicies.EnabledAdmin)]
        [Authorize (Policy = XPolicies.EnabledAgent)]
        public async Task<ActionResult<XActionResponse>> InviteUser (
            [FromBody] XActionRequest model
        ) {
            //
            // Do Action ...
            try {
                //
                // Validate Args ...
                if (!ModelState.IsValid) {
                    XException.InvalidArgs.Throw ();
                }

                //
                await ValidationProvider
                    .GroupValidationBuilder ()
                    .AddNotEmpty (
                        model.Lang,
                        model.Email,
                        model.ReturnUrl)
                    .AddEmailAddress (model.Email)
                    .AddNotNull (model.Device)
                    .ValidateGroupAsync ();

                //
                // Get Request ...
                var tokens = await RetrieveTokensAsXTokenResponse ();
                var result = await identityProvider
                    .InviteUser (
                        tokens,
                        model
                    );

                //
                return Ok (result
                    .ToDynamicObject ());
            } catch (Exception ex) {
                //
                var result = GetExceptionActionResult (ex);
                return result;
            }
        }

        /// <summary>
        /// Recieve some Basic Informations and Start Registration Proccess
        /// if they Valid 
        /// 
        /// Registration Proccess Starts with Invoking this Action
        /// </summary>
        /// <remarks>
        ///     for this action you have to provide: 
        ///         - Lang: client device currently used locale, such as: en-US.
        ///         - FirstName: user's FirstName.
        ///         - LastName: user's LastName.
        ///         - DateOfBirth: user's dob date.
        ///         - MobileNumber: user's MobileNumber optional.
        ///         - Email: user's Email optional.
        ///         - ActionToken: user's requested action token for this action (if user invited). 
        ///         - Device: user's client device which is an instance of XDevice.
        /// 
        /// Sample request:
        /// 
        ///     {
        ///         "lang": "fa-IR",
        ///         "firstName": "",
        ///         "lastName": "",
        ///         "dateOfBirth": "",
        ///         "email": "",
        ///         "mobileNumber": "",
        ///         "actionToken": "",
        ///         "device": {
        ///             "os":"Mac",
        ///             "browser":"Chrome",
        ///             "osVersion":"mac-os-x-15",
        ///             "userAgent":"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_3) AppleWebKit/537.36 (KHTML, like Gecko) x-framework-test/0.0.0 Chrome/87.0.4280.141 Electron/11.2.0 Safari/537.36",
        ///             "deviceType":3,
        ///             "identifier":"[Mac]-[mac-os-x-15]-[3]-[Chrome]-[Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_3) AppleWebKit/537.36 (KHTML, like Gecko) x-framework-test/0.0.0 Chrome/87.0.4280.141 Electron/11.2.0 Safari/537.36]",
        ///             "token":"96f400dd9aa5c57a8cec9d6f4775bad3"
        ///         }
        ///     }
        /// 
        /// </remarks>
        /// <param name="model">an instance of <see>XActionRequest</see> class which provider requirement for action</param>
        /// <returns>an instance of <see>XActionResponse</see></returns>
        [AllowAnonymous]
        [RequireXPowered]
        [HttpPost ("RequestRegistration")]
        public async Task<ActionResult<XActionResponse>> RequestRegistration (
            [FromBody] XActionRequest model
        ) {
            //
            // Do Action ...
            try {
                //
                // Validate Args ...
                if (!ModelState.IsValid) {
                    XException.InvalidArgs.Throw ();
                }
                await ValidationProvider
                    .GroupValidationBuilder ()
                    .AddNotEmpty (
                        model.Lang,
                        model.FirstName,
                        model.LastName)
                    .AddNotNull (
                        model.Device,
                        model.DateOfBirth)
                    .ValidateGroupAsync ();

                //
                // Get Request ...
                var result = await identityProvider
                    .RequestRegistration (
                        model
                    );

                //
                return Ok (result
                    .ToDynamicObject ());
            } catch (Exception ex) {
                //
                var exResult = GetExceptionActionResult (ex);

                //
                return exResult;
            }
        }

        /// <summary>
        /// Add User Account Informations
        /// </summary>
        /// <remarks>
        ///     for this action you have to provide: 
        ///         - Lang: client device currently used locale, such as: en-US.
        ///         - ActionToken: user's requested action token for this action.
        ///         - UserName: user name.
        ///         - Password: assigne password.
        ///         - Device: user's client device which is an instance of XDevice.
        /// 
        /// Sample request:
        /// 
        ///     {
        ///         "lang": "fa-IR",
        ///         "userName": "",
        ///         "password": "",
        ///         "actionToken": "",
        ///         "device": {
        ///             "os":"Mac",
        ///             "browser":"Chrome",
        ///             "osVersion":"mac-os-x-15",
        ///             "userAgent":"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_3) AppleWebKit/537.36 (KHTML, like Gecko) x-framework-test/0.0.0 Chrome/87.0.4280.141 Electron/11.2.0 Safari/537.36",
        ///             "deviceType":3,
        ///             "identifier":"[Mac]-[mac-os-x-15]-[3]-[Chrome]-[Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_3) AppleWebKit/537.36 (KHTML, like Gecko) x-framework-test/0.0.0 Chrome/87.0.4280.141 Electron/11.2.0 Safari/537.36]",
        ///             "token":"96f400dd9aa5c57a8cec9d6f4775bad3"
        ///         }
        ///     }
        /// 
        /// </remarks>
        /// <param name="model">an instance of <see>XActionRequest</see> class which provider requirement for action</param>
        /// <returns>an instance of <see>XActionResponse</see></returns>
        [AllowAnonymous]
        [RequireXPowered]
        [HttpPost ("AddAccountInfo")]
        public async Task<ActionResult<XActionResponse>> AddAccountInfo (
            [FromBody] XActionRequest model
        ) {
            //
            // Do Action ...
            try {
                //
                // Validate Args ...
                if (!ModelState.IsValid) {
                    XException.InvalidArgs.Throw ();
                }
                await ValidationProvider
                    .GroupValidationBuilder ()
                    .AddNotEmpty (
                        model.Lang,
                        model.ActionToken,
                        model.UserName,
                        model.Password)
                    .AddNotNull (model.Device)
                    .ValidateGroupAsync ();

                //
                // Get Request ...
                var result = await identityProvider
                    .AddAccountInfo (
                        model
                    );

                //
                return Ok (result
                    .ToDynamicObject ());
            } catch (Exception ex) {
                //
                var exResult = GetExceptionActionResult (ex);
                return exResult;
            }
        }

        /// <summary>
        /// Upload and Attach a Profile Image for User. this is an Optional Step
        /// </summary>
        /// <param name="actionToken">user's requested action token</param>
        /// <param name="file">an instance of <see>IFormFile</see> for user's Avatar</param>
        /// <returns>an instance of <see>XActionResponse</see></returns>
        [AllowAnonymous]
        [RequireXPowered]
        [HttpPost ("AttachProfileImage")]
        public async Task<ActionResult<XActionResponse>> AttachProfileImage (
            [FromForm] string actionToken, [FromForm] IFormFile file
        ) {
            //
            // Do Action ...
            try {
                // 
                // Validate Args ...
                await ValidationProvider
                    .GroupValidationBuilder ()
                    .AddNotEmpty (actionToken)
                    .AddNotNull (file)
                    .ValidateGroupAsync ();

                //
                var result = await identityProvider
                    .AttachProfileImage (
                        actionToken,
                        file
                    );

                //
                return Ok (result
                    .ToDynamicObject ());
            } catch (Exception ex) {
                //
                var exResult = GetExceptionActionResult (ex);
                return exResult;
            }
        }

        /// <summary>
        /// Finish Registrationn Proccess 
        /// </summary>
        /// <remarks>
        ///     for this action you have to provide: 
        ///         - a proper User Identifier such as: (UserId, UserName, Email or MobileNumber).
        ///         - Lang: client device currently used locale, such as: en-US.
        ///         - ActionToken: user's requested action token for this action.
        ///         - Password: assigne password.
        ///         - Device: user's client device which is an instance of XDevice.
        ///         - ReturnUrl: client application Login URL.
        /// 
        /// Sample request:
        /// 
        ///     {
        ///         "lang": "fa-IR",
        ///         "userName": "",
        ///         "password": "",
        ///         "returnUrl": "",
        ///         "device": {
        ///             "os":"Mac",
        ///             "browser":"Chrome",
        ///             "osVersion":"mac-os-x-15",
        ///             "userAgent":"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_3) AppleWebKit/537.36 (KHTML, like Gecko) x-framework-test/0.0.0 Chrome/87.0.4280.141 Electron/11.2.0 Safari/537.36",
        ///             "deviceType":3,
        ///             "identifier":"[Mac]-[mac-os-x-15]-[3]-[Chrome]-[Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_3) AppleWebKit/537.36 (KHTML, like Gecko) x-framework-test/0.0.0 Chrome/87.0.4280.141 Electron/11.2.0 Safari/537.36]",
        ///             "token":"96f400dd9aa5c57a8cec9d6f4775bad3"
        ///         }
        ///     }
        /// 
        /// </remarks>
        /// <param name="model">an instance of <see>XActionRequest</see> class which provider requirement for action</param>
        /// <returns></returns>
        [AllowAnonymous]
        [RequireXPowered]
        [HttpPost ("FinishRegistration")]
        public async Task<ActionResult> FinishRegistration (
            [FromBody] XActionRequest model
        ) {
            //
            // Do Action ...
            try {
                //
                // Validate Args ...
                if (!ModelState.IsValid) {
                    XException.InvalidArgs.Throw ();
                }
                await ValidationProvider
                    .GroupValidationBuilder ()
                    .AddNotEmpty (
                        model.Lang,
                        model.Password,
                        model.ReturnUrl)
                    .AddNotNull (model.Device)
                    .AddUrl (model.ReturnUrl)
                    .ValidateGroupAsync ();

                //
                var userSelectByParam = identityProvider
                    .GetUserSelectByParam (model);
                ValidationProvider
                    .NotEmpty (userSelectByParam);

                //
                // Get Request ...
                await identityProvider
                    .FinishRegistration (model);

                //
                return Ok ();
            } catch (Exception ex) {
                //
                var exResult = GetExceptionActionResult (ex);

                //
                return exResult;
            }
        }

        /// <summary>
        /// Check User is Confirmed Email or not
        /// </summary>
        /// <returns>a boolean value</returns>
        [RequireXPowered]
        [HttpGet ("IsConfirmedEmail")]
        [Authorize (Policy = XPolicies.User)]
        public async Task<ActionResult<bool>> IsConfirmedEmail () {
            //
            // Do Action ...
            try {
                //
                // Get Result ...
                var tokens = await RetrieveTokensAsXTokenResponse ();
                var result = await identityProvider
                    .IsConfirmedEmail (
                        tokens,
                        User.Identity.Name
                    );

                //
                // Return Result
                return Ok (result);
            } catch (Exception ex) {
                //
                var result = GetExceptionActionResult (ex);

                //
                return result;
            }
        }

        /// <summary>
        /// Check User is Confirmed Mobile or not
        /// </summary>
        /// <returns>a boolean value</returns>
        [RequireXPowered]
        [HttpGet ("IsConfirmedMobile")]
        [Authorize (Policy = XPolicies.User)]
        public async Task<ActionResult<bool>> IsConfirmedMobile () {
            //
            // Do Action ...
            try {
                //
                // Get Result ...
                var tokens = await RetrieveTokensAsXTokenResponse ();
                var result = await identityProvider
                    .IsConfirmedMobile (
                        tokens,
                        User.Identity.Name
                    );

                //
                // Return Result
                return Ok (result);
            } catch (Exception ex) {
                //
                var result = GetExceptionActionResult (ex);

                //
                return result;
            }
        }

        /// <summary>
        /// Request Registration Confirm
        /// </summary>
        /// <remarks>
        ///     for this action you have to provide:
        ///         - a UserSelectedBy identifier which represet User.
        ///         - Lang: client device currently used locale, such as: en-US.
        ///         - Password: user's current active password.
        ///         - Device: user's client device which is an instance of XDevice.
        ///         - ReturnUrl: client application Confirm Registration URL.
        /// 
        /// Sample request:
        /// 
        ///     {
        ///         "lang": "fa-IR",
        ///         "userId": ""
        ///         "password": "",
        ///         "returnUrl": "http://localhost/confirm",
        ///         "device": {
        ///             "os":"Mac",
        ///             "browser":"Chrome",
        ///             "osVersion":"mac-os-x-15",
        ///             "userAgent":"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_3) AppleWebKit/537.36 (KHTML, like Gecko) x-framework-test/0.0.0 Chrome/87.0.4280.141 Electron/11.2.0 Safari/537.36",
        ///             "deviceType":3,
        ///             "identifier":"[Mac]-[mac-os-x-15]-[3]-[Chrome]-[Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_3) AppleWebKit/537.36 (KHTML, like Gecko) x-framework-test/0.0.0 Chrome/87.0.4280.141 Electron/11.2.0 Safari/537.36]",
        ///             "token":"96f400dd9aa5c57a8cec9d6f4775bad3"
        ///         }
        ///     }
        /// 
        /// </remarks>
        /// <param name="model">an instance of <see>XActionRequest</see> class which provider requirement for action</param>
        /// <returns></returns>
        [AllowAnonymous]
        [RequireXPowered]
        [HttpPost ("RequestConfirmRegistration")]
        public async Task<ActionResult> RequestConfirmRegistration (
            [FromBody] XActionRequest model
        ) {
            //
            // Do Action ...
            try {
                //
                // Validate Args ...
                if (!ModelState.IsValid) {
                    XException.InvalidArgs.Throw ();
                }
                await ValidationProvider
                    .GroupValidationBuilder ()
                    .AddNotEmpty (
                        model.Lang,
                        model.Password,
                        model.ReturnUrl)
                    .AddNotNull (model.Device)
                    .AddUrl (model.ReturnUrl)
                    .ValidateGroupAsync ();

                //
                // Get UserSelect By Param ...
                var userSelectByParam = model.GetUserSelectByParam ();
                ValidationProvider.NotEmpty (userSelectByParam);

                //
                await identityProvider
                    .RequestConfirmRegistration (model);

                //
                return Ok ();
            } catch (Exception ex) {
                //
                var exResult = GetExceptionActionResult (ex);
                return exResult;
            }
        }

        /// <summary>
        /// Confirm Registration
        /// </summary>
        /// <remarks>
        ///     for this action you have to provide:
        ///         - Lang: client device currently used locale, such as: en-US.
        ///         - ActionToken: user's requested action token for this action.
        ///         - Device: user's client device which is an instance of XDevice.
        ///         - ReturnUrl: client application Login URL.
        /// 
        /// Sample request:
        /// 
        ///     {
        ///         "lang": "fa-IR",
        ///         "actionToken": ""
        ///         "returnUrl": "http://localhost/login",
        ///         "device": {
        ///             "os":"Mac",
        ///             "browser":"Chrome",
        ///             "osVersion":"mac-os-x-15",
        ///             "userAgent":"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_3) AppleWebKit/537.36 (KHTML, like Gecko) x-framework-test/0.0.0 Chrome/87.0.4280.141 Electron/11.2.0 Safari/537.36",
        ///             "deviceType":3,
        ///             "identifier":"[Mac]-[mac-os-x-15]-[3]-[Chrome]-[Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_3) AppleWebKit/537.36 (KHTML, like Gecko) x-framework-test/0.0.0 Chrome/87.0.4280.141 Electron/11.2.0 Safari/537.36]",
        ///             "token":"96f400dd9aa5c57a8cec9d6f4775bad3"
        ///         }
        ///     }
        /// 
        /// </remarks>
        /// <param name="model">an instance of <see>XActionRequest</see> class which provider requirement for action</param>
        /// <returns></returns>
        [AllowAnonymous]
        [RequireXPowered]
        [HttpPost ("ConfirmRegistration")]
        public async Task<ActionResult> ConfirmRegistration (
            [FromBody] XActionRequest model
        ) {
            //
            // Do Action ...
            try {
                //
                // Validate Args ...
                if (!ModelState.IsValid) {
                    XException.InvalidArgs.Throw ();
                }
                await ValidationProvider
                    .GroupValidationBuilder ()
                    .AddNotEmpty (
                        model.Lang,
                        model.ActionToken,
                        model.ReturnUrl
                    )
                    .AddNotNull (model.Device)
                    .ValidateGroupAsync ();

                //
                // Get Request ...
                await identityProvider
                    .ConfirmRegistration (model);

                //
                return Ok ();
            } catch (Exception ex) {
                //
                var exResult = GetExceptionActionResult (ex);
                return exResult;
            }
        }

        /// <summary>
        /// Request For Mobile Number Change/Confirm 
        /// </summary>
        /// <remarks>
        ///     for this action you have to provide: 
        ///         - Lang: client device currently used locale, such as: en-US.
        ///         - Password: user's current active password.
        ///         - MobileNumber: which phone number is going to confirm.
        ///         - Device: user's client device which is an instance of XDevice.
        /// 
        /// Sample request:
        /// 
        ///     {
        ///         "lang": "fa-IR",
        ///         "password": "",
        ///         "mobileNumber": "",
        ///         "device": {
        ///             "os":"Mac",
        ///             "browser":"Chrome",
        ///             "osVersion":"mac-os-x-15",
        ///             "userAgent":"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_3) AppleWebKit/537.36 (KHTML, like Gecko) x-framework-test/0.0.0 Chrome/87.0.4280.141 Electron/11.2.0 Safari/537.36",
        ///             "deviceType":3,
        ///             "identifier":"[Mac]-[mac-os-x-15]-[3]-[Chrome]-[Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_3) AppleWebKit/537.36 (KHTML, like Gecko) x-framework-test/0.0.0 Chrome/87.0.4280.141 Electron/11.2.0 Safari/537.36]",
        ///             "token":"96f400dd9aa5c57a8cec9d6f4775bad3"
        ///         }
        ///     }
        /// 
        /// </remarks>
        /// <param name="model">an instance of <see>XActionRequest</see> class which provider requirement for action</param>
        /// <returns>an instance of <see>XActionResponse</see></returns>
        [AllowAnonymous]
        [RequireXPowered]
        [HttpPost ("RequestConfirmMobile")]
        public async Task<ActionResult<XActionResponse>> RequestConfirmMobile (
            [FromBody] XActionRequest model
        ) {
            //
            // Do Action ...
            try {
                //
                // Validate Args ...
                if (!ModelState.IsValid) {
                    XException.InvalidArgs.Throw ();
                }
                await ValidationProvider
                    .GroupValidationBuilder ()
                    .AddNotEmpty (
                        model.Lang,
                        model.Password,
                        model.MobileNumber)
                    .AddNotNull (model.Device)
                    .AddMobileNumber (model.MobileNumber)
                    .ValidateGroupAsync ();

                //
                // Get UserSelect By Param ...
                var userSelectByParam = GetUserSelectByParam (
                    model,
                    excludes : new List<XUserSelectBy> {
                        XUserSelectBy.Email,
                        XUserSelectBy.MobileNumber
                    });

                //
                // Get Request ...
                var result = await identityProvider
                    .RequestConfirmMobile (model);

                //
                return Ok (result
                    .ToDynamicObject ());
            } catch (Exception ex) {
                //
                var exResult = GetExceptionActionResult (ex);
                return exResult;
            }
        }

        /// <summary>
        /// Confirm Requested Mobile Number
        /// </summary>
        /// <remarks>
        ///     for this action you have to provide:
        ///         - Lang: client device currently used locale, such as: en-US. 
        ///         - ActionToken: user's requested action token for this action. 
        ///         - Device: user's client device which is an instance of XDevice. 
        ///         - MobileVerificationCode: a verification code which produced due Request Action.
        /// 
        /// Sample request:
        /// 
        ///     {
        ///         "lang": "fa-IR",
        ///         "actionToken": ""
        ///         "mobileVerificationCode": "",
        ///         "device": {
        ///             "os":"Mac",
        ///             "browser":"Chrome",
        ///             "osVersion":"mac-os-x-15",
        ///             "userAgent":"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_3) AppleWebKit/537.36 (KHTML, like Gecko) x-framework-test/0.0.0 Chrome/87.0.4280.141 Electron/11.2.0 Safari/537.36",
        ///             "deviceType":3,
        ///             "identifier":"[Mac]-[mac-os-x-15]-[3]-[Chrome]-[Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_3) AppleWebKit/537.36 (KHTML, like Gecko) x-framework-test/0.0.0 Chrome/87.0.4280.141 Electron/11.2.0 Safari/537.36]",
        ///             "token":"96f400dd9aa5c57a8cec9d6f4775bad3"
        ///         }
        ///     }
        /// 
        /// </remarks>
        /// <param name="model">an instance of <see>XActionRequest</see> class which provider requirement for action</param>
        /// <returns>an instance of <see>XActionResponse</see></returns>
        [AllowAnonymous]
        [RequireXPowered]
        [HttpPost ("ConfirmMobileNumber")]
        public async Task<ActionResult<XActionResponse>> ConfirmMobileNumber (
            [FromBody] XActionRequest model
        ) {
            //
            // Do Action ...
            try {
                //
                // Validate Args ...
                if (!ModelState.IsValid) {
                    XException.InvalidArgs.Throw ();
                }
                await ValidationProvider
                    .GroupValidationBuilder ()
                    .AddNotEmpty (
                        model.Lang,
                        model.MobileVerificationCode,
                        model.ActionToken
                    )
                    .AddNotNull (model.Device)
                    .ValidateGroupAsync ();

                //
                // Get Request ...
                var result = await identityProvider
                    .ConfirmMobileNumber (model);

                //
                return Ok (result
                    .ToDynamicObject ());
            } catch (Exception ex) {
                //
                var exResult = GetExceptionActionResult (ex);
                return exResult;
            }
        }

        /// <summary>
        /// Request For Email Address Change/Confirm
        /// </summary>
        /// <remarks>
        ///     for this action you have to provide:
        ///         - Lang: client device currently used locale, such as: en-US.
        ///         - Password: user's current active password.
        ///         - Email: which email address is going to confirm.
        ///         - Device: user's client device which is an instance of XDevice.
        /// 
        /// Sample request:
        /// 
        ///     {
        ///         "lang": "fa-IR",
        ///         "password": "",
        ///         "email": "",
        ///         "device": {
        ///             "os":"Mac",
        ///             "browser":"Chrome",
        ///             "osVersion":"mac-os-x-15",
        ///             "userAgent":"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_3) AppleWebKit/537.36 (KHTML, like Gecko) x-framework-test/0.0.0 Chrome/87.0.4280.141 Electron/11.2.0 Safari/537.36",
        ///             "deviceType":3,
        ///             "identifier":"[Mac]-[mac-os-x-15]-[3]-[Chrome]-[Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_3) AppleWebKit/537.36 (KHTML, like Gecko) x-framework-test/0.0.0 Chrome/87.0.4280.141 Electron/11.2.0 Safari/537.36]",
        ///             "token":"96f400dd9aa5c57a8cec9d6f4775bad3"
        ///         }
        ///     }
        /// 
        /// </remarks>
        /// <param name="model">an instance of <see>XActionRequest</see> class which provider requirement for action</param>
        /// <returns>an instance of <see>XActionResponse</see></returns>
        [AllowAnonymous]
        [RequireXPowered]
        [HttpPost ("RequestConfirmEmail")]
        public async Task<ActionResult<XActionResponse>> RequestConfirmEmail (
            [FromBody] XActionRequest model
        ) {
            //
            // Do Action ...
            try {
                //
                // Validate Args ...
                if (!ModelState.IsValid) {
                    XException.InvalidArgs.Throw ();
                }
                await ValidationProvider
                    .GroupValidationBuilder ()
                    .AddNotEmpty (
                        model.Lang,
                        model.Email,
                        model.Password)
                    .AddNotNull (model.Device)
                    .AddEmailAddress (model.Email)
                    .ValidateGroupAsync ();

                //
                // Get UserSelect By Param ...
                var userSelectByParam = GetUserSelectByParam (
                    model,
                    excludes : new List<XUserSelectBy> {
                        XUserSelectBy.Email,
                        XUserSelectBy.MobileNumber
                    });

                //
                // Get Request ...
                var result = await identityProvider
                    .RequestConfirmEmail (model);

                //
                return Ok (result
                    .ToDynamicObject ());
            } catch (Exception ex) {
                //
                var exResult = GetExceptionActionResult (ex);
                return exResult;
            }
        }

        /// <summary>
        /// Confirm Requested Email Address
        /// </summary>
        /// <remarks>
        ///     for this action you have to provide: 
        ///         - Lang: client device currently used locale, such as: en-US. 
        ///         - ActionToken: user's requested action token for this action. 
        ///         - Device: user's client device which is an instance of XDevice. 
        ///         - EmailVerificationCode: a verification code which produced due Request Action.
        /// 
        /// Sample request:
        /// 
        ///     {
        ///         "lang": "fa-IR",
        ///         "actionToken": ""
        ///         "emailVerificationCode": "",
        ///         "device": {
        ///             "os":"Mac",
        ///             "browser":"Chrome",
        ///             "osVersion":"mac-os-x-15",
        ///             "userAgent":"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_3) AppleWebKit/537.36 (KHTML, like Gecko) x-framework-test/0.0.0 Chrome/87.0.4280.141 Electron/11.2.0 Safari/537.36",
        ///             "deviceType":3,
        ///             "identifier":"[Mac]-[mac-os-x-15]-[3]-[Chrome]-[Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_3) AppleWebKit/537.36 (KHTML, like Gecko) x-framework-test/0.0.0 Chrome/87.0.4280.141 Electron/11.2.0 Safari/537.36]",
        ///             "token":"96f400dd9aa5c57a8cec9d6f4775bad3"
        ///         }
        ///     }
        /// 
        /// </remarks>
        /// <param name="model">an instance of <see>XActionRequest</see> class which provider requirement for action</param>
        /// <returns>an instance of <see>XActionResponse</see></returns>
        [AllowAnonymous]
        [RequireXPowered]
        [HttpPost ("ConfirmEmailAddress")]
        public async Task<ActionResult<XActionResponse>> ConfirmEmailAddress (
            [FromBody] XActionRequest model
        ) {
            //
            // Do Action ...
            try {
                //
                // Validate Args ...
                if (!ModelState.IsValid) {
                    XException.InvalidArgs.Throw ();
                }
                await ValidationProvider
                    .GroupValidationBuilder ()
                    .AddNotEmpty (
                        model.Lang,
                        model.EmailVerificationCode,
                        model.ActionToken
                    )
                    .AddNotNull (model.Device)
                    .ValidateGroupAsync ();

                //
                // Get Request ...
                var result = await identityProvider
                    .ConfirmEmailAddress (model);

                //
                return Ok (result
                    .ToDynamicObject ());
            } catch (Exception ex) {
                //
                var exResult = GetExceptionActionResult (ex);
                return exResult;
            }
        }

        /// <summary>
        /// Request Reset Password Action
        /// </summary>
        /// <remarks>
        ///     for this action you have to provide:
        ///         - Lang: client device currently used locale, such as: en-US.
        ///         - Device: user's client device which is an instance of XDevice.
        ///         - ReturnUrl: client application ResetPassword URL.
        /// 
        /// Sample request:
        /// 
        ///     {
        ///         "lang": "fa-IR",
        ///         "returnUrl": "http://localhost/reset-password",
        ///         "device": {
        ///             "os":"Mac",
        ///             "browser":"Chrome",
        ///             "osVersion":"mac-os-x-15",
        ///             "userAgent":"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_3) AppleWebKit/537.36 (KHTML, like Gecko) x-framework-test/0.0.0 Chrome/87.0.4280.141 Electron/11.2.0 Safari/537.36",
        ///             "deviceType":3,
        ///             "identifier":"[Mac]-[mac-os-x-15]-[3]-[Chrome]-[Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_3) AppleWebKit/537.36 (KHTML, like Gecko) x-framework-test/0.0.0 Chrome/87.0.4280.141 Electron/11.2.0 Safari/537.36]",
        ///             "token":"96f400dd9aa5c57a8cec9d6f4775bad3"
        ///         }
        ///     }
        /// 
        /// </remarks>
        /// <param name="model">an instance of <see>XActionRequest</see> class which provider requirement for action</param>
        /// <returns>an instance of <see>XActionResponse</see></returns>
        [AllowAnonymous]
        [RequireXPowered]
        [HttpPost ("RequestResetPassword")]
        public async Task<ActionResult<XActionResponse>> RequestResetPassword (
            [FromBody] XActionRequest model
        ) {
            //
            // Do Action ...
            try {
                //
                // Validate Args ...
                if (!ModelState.IsValid) {
                    XException.InvalidArgs.Throw ();
                }
                await ValidationProvider
                    .GroupValidationBuilder ()
                    .AddNotEmpty (
                        model.Lang,
                        model.ReturnUrl)
                    .AddNotNull (model.Device)
                    .AddUrl (model.ReturnUrl)
                    .ValidateGroupAsync ();

                //
                // Get UserSelect By Param ...
                var userSelectByParam = GetUserSelectByParam (
                    model,
                    excludes : new List<XUserSelectBy> {
                        XUserSelectBy.Email,
                        XUserSelectBy.MobileNumber
                    });

                //
                // Get Request ...
                var result = await identityProvider
                    .RequestResetPassword (model);

                //
                return Ok (result
                    .ToDynamicObject ());
            } catch (Exception ex) {
                //
                var exResult = GetExceptionActionResult (ex);
                return exResult;
            }
        }

        /// <summary>
        /// Reset a User's Password
        /// </summary>
        /// <remarks>
        ///     for this action you have to provide:
        ///         - Lang: client device currently used locale, such as: en-US.
        ///         - ActionToken: user's requested action token for this action.
        ///         - NewPassword: user's new password to change.
        ///         - Device: user's client device which is an instance of XDevice.
        ///         - ReturnUrl: client application Login URL.
        /// 
        /// Sample request:
        /// 
        ///     {
        ///         "lang": "fa-IR",
        ///         "actionToken": "",
        ///         "newPassword": "",
        ///         "returnUrl": "http://localhost/login",
        ///         "device": {
        ///             "os":"Mac",
        ///             "browser":"Chrome",
        ///             "osVersion":"mac-os-x-15",
        ///             "userAgent":"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_3) AppleWebKit/537.36 (KHTML, like Gecko) x-framework-test/0.0.0 Chrome/87.0.4280.141 Electron/11.2.0 Safari/537.36",
        ///             "deviceType":3,
        ///             "identifier":"[Mac]-[mac-os-x-15]-[3]-[Chrome]-[Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_3) AppleWebKit/537.36 (KHTML, like Gecko) x-framework-test/0.0.0 Chrome/87.0.4280.141 Electron/11.2.0 Safari/537.36]",
        ///             "token":"96f400dd9aa5c57a8cec9d6f4775bad3"
        ///         }
        ///     }
        /// 
        /// </remarks>
        /// <param name="model">an instance of <see>XActionRequest</see> class which provider requirement for action</param>
        /// <returns></returns>
        [AllowAnonymous]
        [RequireXPowered]
        [HttpPost ("ResetPassword")]
        public async Task<ActionResult> ResetPassword (
            [FromBody] XActionRequest model
        ) {
            //
            // Do Action ...
            try {
                //
                // Validate Args ...
                if (!ModelState.IsValid) {
                    XException.InvalidArgs.Throw ();
                }
                await ValidationProvider
                    .GroupValidationBuilder ()
                    .AddNotEmpty (
                        model.Lang,
                        model.ActionToken,
                        model.NewPassword,
                        model.ReturnUrl)
                    .AddNotNull (model.Device)
                    .ValidateGroupAsync ();

                //
                // Get Request ...
                await identityProvider
                    .ResetPassword (model);

                //
                return Ok ();
            } catch (Exception ex) {
                //
                var exResult = GetExceptionActionResult (ex);
                return exResult;
            }
        }
        #endregion
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\xApi\Controllers\Account\AccountController+Search.cs

using System;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using xCommons.Attributes;
using xCommons.Extensions;
using xIdentityHelper;
using xIdentityModels.Dtos;
using xModels.Dtos;

namespace xApi.Controllers
{
    public partial class AccountController
    {
        //
        #region Actions ...
        /// <summary>
        /// Query Open To Search Users Profiles ... 
        /// Query all Users Which their Profiles is Open To Search ...
        /// </summary>
        /// <param name="query">how to filter results based on <see>XQuery</see> structure</param>
        /// <returns>an instance of <see>XQueryResult</see> of <see>XUserProfileDto</see></returns>
        [RequireXPowered]
        [HttpGet("OpenToSearch/Query")]
        [Authorize(Policy = XPolicies.EnabledUser)]
        public async Task<ActionResult<XQueryResult<XUserProfileDto>>> QueryOpenToSearchProfiles(
            [FromQuery] XQuery query 
        )
        {
            //
            // Do Action ...
            try
            {
                //
                var tokens = await RetrieveTokensAsXTokenResponse();
                var result = await identityProvider.QueryOpenToSearchUsers(
                    tokens,
                    query
                );

                //
                return Ok(result
                    .ToDynamicObject());
            }
            catch (Exception ex)
            {
                //
                var exception = GetExceptionActionResult(ex);
                return exception;
            }
        }
        #endregion
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\xApi\Controllers\AccountController.cs

using Microsoft.AspNetCore.Authorization;
using Microsoft.Extensions.Logging;
using xCommons.Attributes;
using xCommons.Configurations;
using xCommons.Providers;
using xIdentityService.Controllers;
using xIdentityService.Interfaces;

namespace xApi.Controllers
{
    /// <summary>
    /// Handle all Account Related Actions ...
    /// </summary>
    [AllowAnonymous]
    [RequireXPowered(true)]
    public partial class AccountController : XBaseIdentityController
    {
        //
        #region Props ...
        private readonly IXIdentityProvider identityProvider;
        #endregion

        //
        #region Constructor ...
        public AccountController(
            ILogger<AccountController> logger,
            XAppConfiguration appConfiguration,
            IXIdentityProvider identityProvider,
            XValidationProvider validationProvider
        ) : base(
            logger,
            appConfiguration,
            identityProvider,
            validationProvider
        )
        {
            //
            this.identityProvider = identityProvider;
        }
        #endregion
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\xApi\Controllers\StartupController.cs

using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Logging;
using xCommons.Configurations;
using xCommons.Controllers;
using xCommons.Providers;

namespace xApi.Controllers {
    /// <summary>
    /// Runing when application start ...
    /// </summary>
    [Route ("")]
    [AllowAnonymous]
    public class StartupController : XBaseController {

        public StartupController (
            ILogger<StartupController> logger,
            XAppConfiguration appConfiguration,
            XValidationProvider validationProvider
        ) : base (
            logger,
            appConfiguration,
            validationProvider
        ) { }

        /// <summary>
        /// Show Configured Welcome Message 
        /// </summary>
        /// <returns></returns>
        [HttpGet ("")]
        [AllowAnonymous]
        public virtual ActionResult<string> Index () {
            //
            var controllerName = GetControllerName ();
            var message = $"{AppConfiguration.WelcomeMessage}";

            //
            return Ok (message);
        }
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\xApi\Controllers\TestFeaturesController.cs

using System.Threading.Tasks;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Logging;
using xCategoryService.Interfaces;
using xCommons.Configurations;
using xCommons.Controllers;
using xCommons.Providers;

namespace xApi.Controllers
{
    [AllowAnonymous]
    public class TestFeaturesController : XBaseApiController
    {
        private readonly IXSubCategoryTitleResourceProvider subCategoryTitleResourceProvider;

        public TestFeaturesController(
            ILogger<TestFeaturesController> logger,
            XAppConfiguration appConfiguration,
            XValidationProvider validationProvider,
            IXSubCategoryTitleResourceProvider subCategoryTitleResourceProvider
        ) : base(
            logger,
            appConfiguration,
            validationProvider
        )
        {
            this.subCategoryTitleResourceProvider = subCategoryTitleResourceProvider;
        }

        [HttpGet]
        public async Task<ActionResult> TestFeature()
        {
            //
            var result = await subCategoryTitleResourceProvider.GetLanguages(
                identifier: "SSSSAAALLLAAAM"
            );

            //
            return Ok(result);
        }
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\xApi\Controllers\TestIdentity.cs

using System.Linq;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Logging;
using xCommons.Attributes;
using xCommons.Configurations;
using xCommons.Providers;
using xIdentityHelper;
using xIdentityService.Controllers;
using xIdentityService.Interfaces;

namespace xApi.Controllers {
    /// <summary>
    /// Test all Authentication Policies ...
    /// </summary>
    [RequireXPowered (false)]
    public class TestIdentity : XBaseIdentityController {
        public TestIdentity (
            ILogger<TestIdentity> logger,
            XAppConfiguration appConfiguration,
            IXIdentityProvider identityProvider,
            XValidationProvider validationProvider
        ) : base (
            logger,
            appConfiguration,
            identityProvider,
            validationProvider
        ) { }

        //
        #region Test Actions ...
        /// <summary>
        /// API Read Scope
        /// </summary>
        /// <returns>string message</returns>
        [HttpGet ("PassReadAccess")]
        [Authorize (Policy = XPolicies.ReadAccess)]
        public ActionResult<string> PassReadAccess () {
            return Ok ("Read Access Passed ...");
        }

        /// <summary>
        /// API Write Scope
        /// </summary>
        /// <returns>string message</returns>
        [HttpGet ("PassWriteAccess")]
        [Authorize (Policy = XPolicies.WriteAccess)]
        public ActionResult<string> PassWriteAccess () {
            return Ok ("Write Access Passed ...");
        }

        /// <summary>
        /// API Admin Scope
        /// </summary>
        /// <returns>string message</returns>
        [HttpGet ("PassAdminAccess")]
        [Authorize (Policy = XPolicies.AdminAccess)]
        public ActionResult<string> PassAdminAccess () {
            return Ok ("Admin Access Passed ...");
        }

        /// <summary>
        /// API Manage Scop
        /// </summary>
        /// <returns>string message</returns>
        [HttpGet ("PassManageAccess")]
        [Authorize (Policy = XPolicies.ManageAccess)]
        public ActionResult<string> PassManageAccess () {
            return Ok ("Manage Access Passed ...");
        }

        /// <summary>
        /// a simple Action which returns a List of Authenticated User Claims
        /// </summary>
        /// <returns>string message which represent current user's claims</returns>
        [HttpGet ("HiClaims")]
        [Authorize (Policy = XPolicies.User)]
        public ActionResult<string> HiClaims () {
            //
            var result = new {
            name = User.Identity.Name,
            claims = User.Claims.Select (c => new {
            c.Type, c.Value
            })
            };

            //
            return Ok (result);
        }

        /// <summary>
        /// a simple Hello User for Checking Authentication and Policy 
        /// </summary>
        /// <returns>string message which contains authenticated user name</returns>
        [HttpGet ("HiUser")]
        [Authorize (Policy = XPolicies.User)]
        public ActionResult<string> HiUser () {
            //
            var result = $"Hi User: {User.Identity.Name} ...";

            //
            return Ok (result);
        }

        /// <summary>
        /// a simple Hello User for Checking Authentication and Policy 
        /// </summary>
        /// <returns>string message which contains authenticated user name</returns>
        [HttpGet ("HiEnabledUser")]
        [Authorize (Policy = XPolicies.EnabledUser)]
        public ActionResult<string> HiEnabledUser () {
            //
            var result = $"Hi User: {User.Identity.Name} is Enabled ...";

            //
            return Ok (result);
        }

        /// <summary>
        /// a simple Hello User for Checking Authentication and Policy 
        /// </summary>
        /// <returns>string message which contains authenticated user name</returns>
        [HttpGet ("HiAgent")]
        [Authorize (Policy = XPolicies.Agent)]
        public ActionResult<string> HiAgent () {
            //
            var result = $"Hi Agent: {User.Identity.Name} ...";

            //
            return Ok (result);
        }

        /// <summary>
        /// a simple Hello User for Checking Authentication and Policy 
        /// </summary>
        /// <returns>string message which contains authenticated user name</returns>
        [HttpGet ("HiEnabledAgent")]
        [Authorize (Policy = XPolicies.EnabledAgent)]
        public ActionResult<string> HiEnabledAgent () {
            //
            var result = $"Hi Agent: {User.Identity.Name} is Enabled ...";

            //
            return Ok (result);
        }

        /// <summary>
        /// a simple Hello User for Checking Authentication and Policy 
        /// </summary>
        /// <returns>string message which contains authenticated user name</returns>
        [HttpGet ("HiAdmin")]
        [Authorize (Policy = XPolicies.Admin)]
        public ActionResult<string> HiAdmin () {
            //
            var result = $"Hi Admin: {User.Identity.Name} ...";

            //
            return Ok (result);
        }

        /// <summary>
        /// a simple Hello User for Checking Authentication and Policy 
        /// </summary>
        /// <returns>string message which contains authenticated user name</returns>
        [HttpGet ("HiEnabledAdmin")]
        [Authorize (Policy = XPolicies.EnabledAdmin)]
        public ActionResult<string> HiEnabledAdmin () {
            //
            var result = $"Hi Admin: {User.Identity.Name} is Enabled ...";

            //
            return Ok (result);
        }
        #endregion        
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\xApi\Extensions\XStartupExtensions.cs

using System.Collections.Generic;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.HttpOverrides;
using Microsoft.Extensions.DependencyInjection;
using xIdentityHelper;
using xCommons.Authorization;
using xCommons.Extensions;

namespace xApi.Extensions {
    public static class XStartupExtensions {
        /// <summary>
        /// Register Authorization Policies
        /// </summary>
        /// <param name="services"></param>
        /// <param name="policies"></param>
        public static void AddXAuthorization (
            this IServiceCollection services,
            IDictionary<string, AuthorizationPolicy> policies = null
        ) {
            //
            services.AddAuthorization (options => {
                //
                if (!policies.IsNull ()) {
                    //
                    // Fill Policies ...
                    using (var policiesEnumerator = policies.GetEnumerator ()) {
                        while (policiesEnumerator.MoveNext ()) {
                            var policyDescriptor = policiesEnumerator.Current;
                            options.AddPolicy (policyDescriptor.Key, policyDescriptor.Value);
                        }
                    }
                }

                //
                var xPolicies = XAuthorizationHelper.GetXAuthorizationPolicies ();
                if (!xPolicies.IsNull ()) {
                    //
                    // Fill Policies ...
                    using (var policiesEnumerator = xPolicies.GetEnumerator ()) {
                        while (policiesEnumerator.MoveNext ()) {
                            var policyDescriptor = policiesEnumerator.Current;
                            options.AddPolicy (policyDescriptor.Key, policyDescriptor.Value);
                        }
                    }
                }
            });

            //
            services.AddSingleton<IAuthorizationHandler, RequiredRolesHandler> ();
        }

        /// <summary>
        /// Use Forward Headers Options for resolving behind a proxy issues ...
        /// </summary>
        /// <param name="source"></param>
        /// <returns></returns>
        public static void UseXForwardOptions (this IApplicationBuilder source) {
            //
            var forwardOptions = new ForwardedHeadersOptions {
                ForwardedHeaders = ForwardedHeaders.XForwardedFor | ForwardedHeaders.XForwardedProto,
                RequireHeaderSymmetry = false
            };

            //
            forwardOptions.KnownNetworks.Clear ();
            forwardOptions.KnownProxies.Clear ();

            //
            // ref: https://github.com/aspnet/Docs/issues/2384
            source.UseForwardedHeaders (forwardOptions);
        }
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\xApi\Extensions\XUserClaimsInfoDtoExtensions.cs

using xCommons.Extensions;
using xIdentityModels.Constants;
using xIdentityModels.Models;

namespace xApi.Extensions {
    public static class XUserClaimsInfoDtoExtensions {
        public static string GetUserSelectByParam (
            this XUserClaimsInfoDto source,
            XUserSelectBy userSelectBy = XUserSelectBy.Username
        ) {
            //
            var result = "";

            //
            switch (userSelectBy) {
                //
                case XUserSelectBy.ID:
                    result = source.UserId;
                    break;

                    //
                case XUserSelectBy.Username:
                    result = source.UserName;
                    break;

                    //
                case XUserSelectBy.Email:
                    result = source.Email;
                    break;

                    //
                case XUserSelectBy.MobileNumber:
                    result = source.PhoneNumber;
                    break;
            }

            //
            if (result.IsNullOrEmpty ()) {
                //
                if (!source.UserId.IsNullOrEmpty ()) {
                    result = source.UserId;
                } else if (!source.UserName.IsNullOrEmpty ()) {
                    result = source.UserName;
                } else if (!source.Email.IsNullOrEmpty ()) {
                    result = source.Email;
                } else if (!source.PhoneNumber.IsNullOrEmpty ()) {
                    result = source.PhoneNumber;
                }
            }

            //
            return result;
        }
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\xApi\Program.cs

using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Hosting;

namespace xApi
{
    public class Program
    {
        public static void Main(string[] args)
        {
            CreateHostBuilder(args).Build().Run();
        }

        public static IHostBuilder CreateHostBuilder(string[] args) =>
            Host.CreateDefaultBuilder(args)
            .ConfigureWebHostDefaults(webBuilder =>
            {
                webBuilder.UseStartup<Startup>();
            });
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\xApi\Startup.cs

using System;
using System.Collections.Generic;
using System.IO;
using System.Net.Http;
using System.Reflection;
using IdentityModel.AspNetCore.OAuth2Introspection;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Server.Kestrel.Core;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Newtonsoft.Json;
using Newtonsoft.Json.Serialization;
using xApi.Extensions;
using xCommons.Configurations;
using xCommons.Extensions;
using xDataService.Models;
using xHttpService.DI;
using xIdentityService.DI;
using xServices.Databases;
using xServices.DI;

namespace xApi
{
    public class Startup
    {
        //
        public IConfiguration Configuration { get; }
        private readonly XApiDatabaseDescriptor apiDatabaseDescriptor;

        public Startup(IConfiguration configuration)
        {
            //
            Configuration = configuration;

            //
            // Create an Api Descriptor Class Instance ...
            apiDatabaseDescriptor = new XApiDatabaseDescriptor();
        }

        public void ConfigureServices(IServiceCollection services)
        {
            //
            // Register Validation Provider and all XCommons Module Services ...
            services.AddXCommons();

            //
            // Register App Configuration ...
            services.AddXAppConfiguration(Configuration);
            var appConfiguration = services.GetRegisteredService<XAppConfiguration>();

            //
            // Register Allowed Origins ...
            services.AddXCors(appConfiguration.AllowedOrigins);

            //
            // Register Swagger ...
            var xmlFile = $"{Assembly.GetExecutingAssembly().GetName().Name}.xml";
            var xmlPath = Path.Combine(AppContext.BaseDirectory, xmlFile);
            services.AddXSwagger(Configuration, xmlFilePath: xmlPath);

            //
            // Register HttpService ...
            services.AddXHttpService(Configuration);

            //
            // Add Api V1 Versioning ...
            services.AddXApiV1Versioning();

            //
            // OAuthIntrospectin Http Client Handler ...
            // this is for handling SSLErrors ...
            services.AddHttpClient(OAuth2IntrospectionDefaults.BackChannelHttpClientName)
                .ConfigurePrimaryHttpMessageHandler(() =>
                {
                    return new HttpClientHandler
                    {
                        ServerCertificateCustomValidationCallback = (sender, certificate, chain, sslPolicyErrors) => true
                    };
                });

            //
            // Register Authorizations ...
            services.AddXAuthorization();

            //
            services.AddControllers()
                .AddNewtonsoftJson(x =>
                {
                    x.SerializerSettings.ReferenceLoopHandling = ReferenceLoopHandling.Ignore;
                    x.SerializerSettings.ContractResolver = new CamelCasePropertyNamesContractResolver();
                });

            //
            // Custom ...

            //
            services.Configure<IISServerOptions>(options =>
            {
                options.AllowSynchronousIO = true;
            });

            //
            services.Configure<KestrelServerOptions>(options =>
            {
                options.AllowSynchronousIO = true;
            });

            //
            // Register Services ...
            services.AddXServices(
                configuration: Configuration,
                databases: new List<XDatabaseDescriptor>
                {
                    apiDatabaseDescriptor
                },
                lifeTime: ServiceLifetime.Scoped
            );
        }

        public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
        {
            //
            if (env.IsDevelopment())
            {
                app.UseDeveloperExceptionPage();
            }

            //
            // Use Swagger Middleware ...
            app.UseXSwagger();

            //
            app.UseHttpsRedirection();

            //
            // Using Cors ...
            app.UseXCors();

            //
            app.UseRouting();

            //
            // Use xIdentityService ...
            app.UseXIdentityService();

            //
            app.UseAuthorization();

            //
            app.UseEndpoints(endpoints =>
            {
                endpoints.MapControllers();
            });

            //
            // Use xDataService Middleware ...
            app.UseXServices(
                databases: new List<XDatabaseDescriptor>
                {
                    apiDatabaseDescriptor
                },
                isDevelopmentEnvironment: env.IsDevelopment()
            );
        }
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\xClient\plugins\cordova-plugin-splashscreen\src\wp\ResolutionHelper.cs

/*
    Licensed under the Apache License, Version 2.0 (the "License");
    you may not use this file except in compliance with the License.
    You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

    Unless required by applicable law or agreed to in writing, software
    distributed under the License is distributed on an "AS IS" BASIS,
    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    See the License for the specific language governing permissions and
    limitations under the License.
*/

using Microsoft.Phone.Info;
using System;
using System.Windows;

namespace WPCordovaClassLib.Cordova.Commands
{
    public enum Resolutions { WVGA, WXGA, HD };

    public static class ResolutionHelper
    { 
       public static Resolutions CurrentResolution
        {
            get
            {
                switch (Application.Current.Host.Content.ScaleFactor) 
                {
                    case 100: return Resolutions.WVGA;
                    case 160: return Resolutions.WXGA;
                    case 150: return Resolutions.HD;
                }
                throw new InvalidOperationException("Unknown resolution");
            }
        }
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\xClient\plugins\cordova-plugin-splashscreen\src\wp\SplashScreen.cs

/*
    Licensed under the Apache License, Version 2.0 (the "License");
    you may not use this file except in compliance with the License.
    You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

    Unless required by applicable law or agreed to in writing, software
    distributed under the License is distributed on an "AS IS" BASIS,
    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    See the License for the specific language governing permissions and
    limitations under the License.
*/

using System;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Ink;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using Microsoft.Phone.Info;
using System.Windows.Controls.Primitives;
using System.Diagnostics;
using System.Windows.Media.Imaging;
using System.Windows.Resources;
using System.IO;
using System.Xml.Linq;
using System.Linq;
using System.Windows.Threading;

namespace WPCordovaClassLib.Cordova.Commands
{
    /// <summary>
    /// Listens for changes to the state of the battery on the device.
    /// Currently only the "isPlugged" parameter available via native APIs.
    /// </summary>
    public class SplashScreen : BaseCommand
    {
        private Popup popup;

        // Time until we dismiss the splashscreen
        private int prefDelay = 3000;

        // Whether we hide it by default
        private bool prefAutoHide = true;

        // Path to image to use
        private string prefImagePath = "SplashScreenImage.jpg";

        // static because autodismiss is only ever applied once, at app launch
        // subsequent page loads should not cause the SplashScreen to be shown.
        private static bool WasShown = false;

        public SplashScreen()
        {
            LoadConfigPrefs();

            Image SplashScreen = new Image()
            {
                Height = Application.Current.Host.Content.ActualHeight,
                Width = Application.Current.Host.Content.ActualWidth,
                Stretch = Stretch.Fill
            };

            var imageResource = GetSplashScreenImageResource();
            if (imageResource != null)
            {
                BitmapImage splash_image = new BitmapImage();
                splash_image.SetSource(imageResource.Stream);
                SplashScreen.Source = splash_image;
            }

            // Instansiate the popup and set the Child property of Popup to SplashScreen
            popup = new Popup() { IsOpen = false,
                                  Child = SplashScreen,
                                  HorizontalAlignment = HorizontalAlignment.Stretch,
                                  VerticalAlignment = VerticalAlignment.Center

            };
        }

        public override void OnInit()
        {
            // we only want to autoload on the first page load.
            // but OnInit is called for every page load.
            if (!SplashScreen.WasShown)
            {
                SplashScreen.WasShown = true;
                show();
            }
        }

        private void LoadConfigPrefs()
        {
            StreamResourceInfo streamInfo = Application.GetResourceStream(new Uri("config.xml", UriKind.Relative));
            if (streamInfo != null)
            {
                using (StreamReader sr = new StreamReader(streamInfo.Stream))
                {
                    //This will Read Keys Collection for the xml file
                    XDocument configFile = XDocument.Parse(sr.ReadToEnd());

                    string configAutoHide = configFile.Descendants()
                                        .Where(x => x.Name.LocalName == "preference")
                                        .Where(x => (string)x.Attribute("name") == "AutoHideSplashScreen")
                                        .Select(x => (string)x.Attribute("value"))
                                        .FirstOrDefault();

                    bool bVal;
                    prefAutoHide = bool.TryParse(configAutoHide, out bVal) ? bVal : prefAutoHide;

                    string configDelay = configFile.Descendants()
                                      .Where(x => x.Name.LocalName == "preference")
                                      .Where(x => (string)x.Attribute("name") == "SplashScreenDelay")
                                      .Select(x => (string)x.Attribute("value"))
                                      .FirstOrDefault();
                    int nVal;
                    prefDelay = int.TryParse(configDelay, out nVal) ? nVal : prefDelay;

                    string configImage = configFile.Descendants()
                                        .Where(x => x.Name.LocalName == "preference")
                                        .Where(x => (string)x.Attribute("name") == "SplashScreen")
                                        .Select(x => (string)x.Attribute("value"))
                                        .FirstOrDefault();

                    if (!String.IsNullOrEmpty(configImage))
                    {
                        prefImagePath = configImage;
                    }
                }
            }
        }

        private StreamResourceInfo GetSplashScreenImageResource()
        {
            // Get the base filename for the splash screen images
            string imageName = System.IO.Path.GetFileNameWithoutExtension(prefImagePath);
            Uri imageUri = null;
            StreamResourceInfo imageResource = null;

            // First, try to get a resolution-specific splashscreen
            try
            {
                // Determine the device's resolution
                switch (ResolutionHelper.CurrentResolution)
                {
                    case Resolutions.HD:
                        imageUri = new Uri(imageName + ".screen-720p.jpg", UriKind.Relative);
                        break;

                    case Resolutions.WVGA:
                        imageUri = new Uri(imageName + ".screen-WVGA.jpg", UriKind.Relative);
                        break;

                    case Resolutions.WXGA:
                    default:
                        imageUri = new Uri(imageName + ".screen-WXGA.jpg", UriKind.Relative);
                        break;
                }

                imageResource = Application.GetResourceStream(imageUri);
            }
            catch (Exception)
            {
                // It's OK if we didn't get a resolution-specific image
            }

            // Fallback to the default image name without decoration
            if (imageResource == null)
            {
                imageUri = new Uri(prefImagePath, UriKind.Relative);
                imageResource = Application.GetResourceStream(imageUri);
            }

            if (imageUri != null) Debug.WriteLine("INFO :: SplashScreen: using image {0}", imageUri.OriginalString);

            return imageResource;
        }

        public void show(string options = null)
        {
            Deployment.Current.Dispatcher.BeginInvoke(() =>
            {
                if (!popup.IsOpen)
                {
                    popup.Child.Opacity = 0;

                    Storyboard story = new Storyboard();
                    DoubleAnimation animation = new DoubleAnimation()
                                                    {
                                                        From = 0.0,
                                                        To = 1.0,
                                                        Duration = new Duration(TimeSpan.FromSeconds(0.2))
                                                    };

                    Storyboard.SetTarget(animation, popup.Child);
                    Storyboard.SetTargetProperty(animation, new PropertyPath("Opacity"));
                    story.Children.Add(animation);

                    story.Begin();

                    popup.IsOpen = true;

                    if (prefAutoHide)
                    {
                        StartAutoHideTimer();
                    }
                }
            });
        }

        public void hide(string options = null)
        {
            Deployment.Current.Dispatcher.BeginInvoke(() =>
            {
                if (popup.IsOpen)
                {
                    popup.Child.Opacity = 1.0;

                    Storyboard story = new Storyboard();
                    DoubleAnimation animation = new DoubleAnimation()
                                                    {
                                                        From = 1.0,
                                                        To = 0.0,
                                                        Duration = new Duration(TimeSpan.FromSeconds(0.4))
                                                    };

                    Storyboard.SetTarget(animation, popup.Child);
                    Storyboard.SetTargetProperty(animation, new PropertyPath("Opacity"));
                    story.Children.Add(animation);
                    story.Completed += (object sender, EventArgs e) =>
                    {
                        popup.IsOpen = false;
                    };
                    story.Begin();
                }
            });
        }

        private void StartAutoHideTimer()
        {
            var timer = new DispatcherTimer() { Interval = TimeSpan.FromMilliseconds(prefDelay) };
            timer.Tick += (object sender, EventArgs e) =>
            {
                hide();
                timer.Stop();
            };
            timer.Start();
        }
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\xClient\plugins\cordova-plugin-statusbar\src\wp\StatusBar.cs

/*  
	Licensed under the Apache License, Version 2.0 (the "License");
	you may not use this file except in compliance with the License.
	You may obtain a copy of the License at
	
	http://www.apache.org/licenses/LICENSE-2.0
	
	Unless required by applicable law or agreed to in writing, software
	distributed under the License is distributed on an "AS IS" BASIS,
	WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
	See the License for the specific language governing permissions and
	limitations under the License.
*/


using Microsoft.Phone.Shell;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.Threading;
using System.Windows;
using System.Windows.Media;
using System.Windows.Threading;


/*
 *   http://www.idev101.com/code/User_Interface/StatusBar.html
 *   https://developer.apple.com/library/ios/documentation/userexperience/conceptual/transitionguide/Bars.html
 *   https://developer.apple.com/library/ios/documentation/uikit/reference/UIApplication_Class/Reference/Reference.html#//apple_ref/c/econst/UIStatusBarStyleDefault
 * */


namespace WPCordovaClassLib.Cordova.Commands
{
    public class StatusBar : BaseCommand
    {

        // returns an argb value, if the hex is only rgb, it will be full opacity
        protected Color ColorFromHex(string hexString)
        {
            string cleanHex = hexString.Replace("#", "").Replace("0x", "");
            // turn #FFF into #FFFFFF
            if (cleanHex.Length == 3)
            {
                cleanHex = "" + cleanHex[0] + cleanHex[0] + cleanHex[1] + cleanHex[1] + cleanHex[2] + cleanHex[2];
            }
            // add an alpha 100% if it is missing
            if (cleanHex.Length == 6)
            {
                cleanHex = "FF" + cleanHex;
            }
            int argb = Int32.Parse(cleanHex, NumberStyles.HexNumber);
            Color clr = Color.FromArgb((byte)((argb & 0xff000000) >> 0x18),
                              (byte)((argb & 0xff0000) >> 0x10),
                              (byte)((argb & 0xff00) >> 8),
                              (byte)(argb & 0xff));
            return clr;
        }

        public void _ready(string options)
        {
            Deployment.Current.Dispatcher.BeginInvoke(() =>
            {
                bool isVis = SystemTray.IsVisible;
                // TODO: pass this to JS
                //Debug.WriteLine("Result::" + res);
                DispatchCommandResult(new PluginResult(PluginResult.Status.OK, isVis));
            });
        }

        public void overlaysWebView(string options)
        {    //exec(null, null, "StatusBar", "overlaysWebView", [doOverlay]);
             // string arg = JSON.JsonHelper.Deserialize<string[]>(options)[0];
        }

        public void styleDefault(string options)
        {    //exec(null, null, "StatusBar", "styleDefault", []);
            Deployment.Current.Dispatcher.BeginInvoke(() =>
            {
                SystemTray.ForegroundColor = Colors.Black;
            });
        }

        public void styleLightContent(string options)
        {    //exec(null, null, "StatusBar", "styleLightContent", []);
            
            Deployment.Current.Dispatcher.BeginInvoke(() =>
            {
                SystemTray.ForegroundColor = Colors.White;
            });
        }

        public void styleBlackTranslucent(string options)
        {    //exec(null, null, "StatusBar", "styleBlackTranslucent", []);
            styleLightContent(options);
        }

        public void styleBlackOpaque(string options)
        {    //exec(null, null, "StatusBar", "styleBlackOpaque", []);
            styleLightContent(options);
        }

        public void backgroundColorByName(string options)
        {    //exec(null, null, "StatusBar", "backgroundColorByName", [colorname]);
             // this should NOT be called, js should now be using/converting color names to hex 
        }

        public void backgroundColorByHexString(string options)
        {    //exec(null, null, "StatusBar", "backgroundColorByHexString", [hexString]);
            string argb = JSON.JsonHelper.Deserialize<string[]>(options)[0];

            Color clr = ColorFromHex(argb);
              
            Deployment.Current.Dispatcher.BeginInvoke(() =>
            {
                SystemTray.Opacity = clr.A / 255.0d;
                SystemTray.BackgroundColor = clr;
                
            });
        }

        public void hide(string options)
        {    //exec(null, null, "StatusBar", "hide", []);
            Deployment.Current.Dispatcher.BeginInvoke(() =>
            {
                SystemTray.IsVisible = false;
            });

        }

        public void show(string options)
        {    //exec(null, null, "StatusBar", "show", []);
            Deployment.Current.Dispatcher.BeginInvoke(() =>
            {
                SystemTray.IsVisible = true;
            });
        }
	}
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\xIds\Configurations\CertificatesConfigurations.cs

namespace xIds.Configurations
{
    public class CertificatesConfigurations
    {
        public struct CertificateNames
        {
            public const string IdentityServerSigning = "IdentityServerSigning";
        }
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\xIds\Configurations\XDataServiceConfiguration.cs

using xIds.Constants;

namespace xIds.Configurations
{
    /// <summary>
    /// Represent Configurations of DataService Module ...
    /// </summary>
    public partial class XDataServiceConfiguration
    {
        /// <summary>
        /// Provider Type ...
        /// </summary>
        /// <value></value>
        public XDbProviders Provider { get; set; }

        /// <summary>
        /// Connection String which provide Requires Data to Connect to Db Provider ...
        /// </summary>
        /// <value></value>
        public string ConnectionString { get; set; }

        /// <summary>
        /// Enable Tracking of Entities ...
        /// Only Used on EFCore ...
        /// </summary>
        /// <value></value>
        public bool EnableTracking { get; set; } = false;

        /// <summary>
        /// Enable Logging Details of Errors ...
        /// Only Used on EFCore ...
        /// </summary>
        /// <value></value>
        public bool EnableDetailedErrors { get; set; } = false;

        /// <summary>
        /// Enable Logging Sensitive Data ...
        /// Only Used on EFCore ...
        /// </summary>
        /// <value></value>
        public bool EnableSensitiveDataLogging { get; set; } = false;

        /// <summary>
        /// this is a way to provide Default Pagination Data on XQuery based requests ...
        /// </summary>
        /// <returns></returns>
        public PagingConfiguration PagingConfiguration { get; set; } = new PagingConfiguration();
    }

    /// <summary>
    /// this is a way to provide Default Pagination Data on XQuery based requests ...
    /// </summary>
    public partial class PagingConfiguration
    {
        /// <summary>
        /// Default Page Size ...
        /// </summary>
        /// <value></value>
        public int DefaultPageSize { get; set; } = XDataServiceConstants.DEFAULT_PAGE_SIZE;

        /// <summary>
        /// restrict Maximum Page Size ...
        /// </summary>
        /// <value></value>
        public int MaxAvailablePageSize { get; set; } = XDataServiceConstants.MAX_AVAILABLE_PAGE_SIZE;

        /// <summary>
        /// restrice Minimum Page Size ...
        /// </summary>
        /// <value></value>
        public int MinAvailablePageSize { get; set; } = XDataServiceConstants.MIN_AVAILABLE_PAGE_SIZE;
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\xIds\Configurations\XIdentityResourceConfiguration.cs

namespace xIds.Configurations
{
    /// <summary>
    /// determines a resource and it's connection info
    /// </summary>
    public partial class XIdentityResourceConfiguration
    {
        public string Authority { get; set; }
        public string ApiName { get; set; }
        public string ApiSecret { get; set; }

        public string ClientId { get; set; }
        public string ClientSecret { get; set; }

        public string XPoweredValue { get; set; }
        public string XRevisionSecretKey { get; set; }
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\xIds\Constants\ConfigurationNodeNames.cs

namespace xIds.Constants
{
    public struct ConfigurationNodeNames
    {
        public const string DB_SEED_NODE_NAME = "DbSeeder";
        public const string PROVIDER_NODE_NAME = "DbProvider";
        public const string IDENTITY_NODE_NAME = "IdentityConfiguration";
        public const string DATA_SERVICE_NODE_NAME = "DataServiceConfiguration";
        public const string IDENTITY_RESOURCE_NODE_NAME = "IdentityResourceConfiguration";
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\xIds\Constants\ConnectionStringNames.cs

namespace xIds.Constants
{
    public struct ConnectionStringNames
    {
        public const string IDENTITY_CONNECTION_NAME = "IdentityDb";
        public const string CONFIGURATION_CONNECTION_NAME = "ConfigurationDb";
        public const string PRESISTED_GRANTS_CONNECTION_NAME = "PersistedGrantDb";
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\xIds\Constants\IdentityMessagesKeys.cs

namespace xIds.Constants
{
    public struct IdentityMessagesKeys
    {
        public const string Terms = "terms";
        public const string InviteMsg = "user_invite_msg";
        public const string RegistrationApproveMsg = "registration_approve_msg";
        public const string RegisteredMsg = "registered_msg";
        public const string VerificationCodeMsg = "verification_code_msg";
        public const string ChangePasswordMsg = "change_password_msg";
        public const string PasswordChangedMsg = "password_changed_msg";
        public const string NewDeviceLoggedInMsg = "new_device_logged_in_msg";
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\xIds\Constants\XDataServiceConstants.cs

namespace xIds.Constants
{
    /// <summary>
    /// /// Default Pagination Values ...
    /// </summary>
    public partial struct XDataServiceConstants
    {
        public static int DEFAULT_PAGE_SIZE = 50;
        public static int MAX_AVAILABLE_PAGE_SIZE = 500;
        public static int MIN_AVAILABLE_PAGE_SIZE = 20;
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\xIds\Constants\XDbProviderConfigurations.cs

namespace xIds.Constants
{
    public partial class XDbProviderConfigurations
    {
        /// <summary>
        /// Default ConnectionString Name ...
        /// </summary>
        public const string DEFAULT_CONNECTION_NAME = "DataConnection";
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\xIds\Constants\XDbProviders.cs

namespace xIds.Constants
{
    /// <summary>
    /// /// Represent Supported DBMS for Managing Data ...
    /// </summary>
    public enum XDbProviders
    {
        None,
        MySQL,
        SQLite,
        SQLServer,
    }

    /// <summary>
    /// Represent Supported DBMS for Managing Data ...
    /// </summary>
    public partial struct ProviderType
    {
        public const string MySQL = "MYSQL";
        public const string SQLite = "SQLITE";
        public const string SQLServer = "SQLSERVER";
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\xIds\Controllers\Account\AccountController+Admin.cs

using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using xIdentityHelper;
using xCommons.Attributes;
using xCommons.Extensions;
using xIdentityModels.Dtos;
using static IdentityServer4.IdentityServerConstants;

namespace xIds.Controllers
{
    public partial class AccountController
    {
        //
        #region Admin Actions ...
        /// <summary>
        /// Ban Specific Users
        /// </summary>
        /// <param name="model">an instance of <see>XUserNameIdRequest</see> which represents user identifier list to Ban</param>
        /// <returns>a list of banned users identifiers</returns>
        [RequireXPowered]
        [HttpPost("Ban")]
        [Authorize(Policy = LocalApi.PolicyName)]
        [Authorize(Policy = XPolicies.EnabledAdmin)]
        public async Task<ActionResult<IEnumerable<string>>> Ban(
            [FromBody] XUserNameIdRequest model
        )
        {
            //
            // Do Action ...
            try
            {
                //
                // Validate Args ...
                await ValidationProvider
                    .GroupValidationBuilder()
                    .AddNotNull(model)
                    .AddNotZeroChilds(model.Ids)
                    .ValidateGroupAsync();

                //
                var result = await IdentityManager
                    .Ban(
                        User.Identity.Name,
                        model
                    );

                //
                return Ok(result
                    .ToDynamicObject());
            }
            catch (Exception ex)
            {
                //
                var exResult = GetExceptionActionResult(ex);
                return exResult;
            }
        }

        /// <summary>
        /// UnBann Specific Users 
        /// </summary>
        /// <param name="model">an instance of <see>XUserNameIdRequest</see> which represents user identifier list to Ban</param>
        /// <returns>a list of unbanned users identifiers</returns>
        [RequireXPowered]
        [HttpPost("UnBan")]
        [Authorize(Policy = LocalApi.PolicyName)]
        [Authorize(Policy = XPolicies.EnabledAdmin)]
        public async Task<ActionResult<IEnumerable<string>>> UnBan(
            [FromBody] XUserNameIdRequest model
        )
        {
            //
            // Do Action ...
            try
            {
                //
                // Validate Args ...
                await ValidationProvider
                    .GroupValidationBuilder()
                    .AddNotNull(model)
                    .AddNotZeroChilds(model.Ids)
                    .ValidateGroupAsync();

                //
                var result = await IdentityManager
                    .UnBan(
                        User.Identity.Name,
                        model
                    );

                //
                return Ok(result
                    .ToDynamicObject());
            }
            catch (Exception ex)
            {
                //
                var exResult = GetExceptionActionResult(ex);
                return exResult;
            }
        }

        /// <summary>
        /// Check Specific User is Banned or not
        /// </summary>
        /// <param name="userSelectByParam">specified user's identifier</param>
        /// <returns>a boolean value which represent user banned or not</returns>
        [RequireXPowered]
        [Authorize(Policy = LocalApi.PolicyName)]
        [HttpGet("IsBanned/{userSelectByParam?}")]
        [Authorize(Policy = XPolicies.EnabledAdmin)]
        [Authorize(Policy = XPolicies.EnabledAgent)]
        public async Task<ActionResult<bool>> IsBanned(
            [FromRoute] string userSelectByParam = null
        )
        {
            //
            // Do Action ...
            try
            {
                //
                // Validate Args ...
                if (userSelectByParam.IsNullOrEmpty())
                {
                    userSelectByParam = User.Identity.Name;
                }
                ValidationProvider.NotEmpty(userSelectByParam);

                //
                var result = await IdentityManager
                    .IsBanned(
                        User.Identity.Name,
                        userSelectByParam
                    );

                //
                return Ok(result);
            }
            catch (Exception ex)
            {
                //
                var exResult = GetExceptionActionResult(ex);
                return exResult;
            }
        }
        #endregion
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\xIds\Controllers\Account\AccountController+Authentication.cs

using System;
using System.Threading.Tasks;
using IdentityModel.Client;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using xIdentityHelper;
using xCommons.Attributes;
using xCommons.Extensions;
using xExceptions.Constants;
using xIdentityModels.Extensions;
using xIdentityModels.Models;
using static IdentityServer4.IdentityServerConstants;
using static xIdentityHelper.XApiScopeHelper;
using Microsoft.Extensions.Logging;

namespace xIds.Controllers
{
    public partial class AccountController
    {
        //
        #region Authentication Actions ...
        /// <summary>
        /// Retrieve OAuth Discovery Document
        /// </summary>
        /// <returns>an instance of <see>DiscoveryDocumentResponse</see></returns>
        [AllowAnonymous]
        [RequireXPowered]
        [HttpGet("DiscoveryDocument")]
        public async Task<ActionResult<DiscoveryDocumentResponse>> GetDiscoveryDocument()
        {
            //
            // Do Action ...
            try
            {
                //
                var result = await IdentityManager
                    .RequestDiscoveryDocument();

                //
                // Ceck Response Result ...
                if (result.IsError)
                {
                    XException.InvalidConfiguration.Throw();
                }

                //
                return Ok(result
                    .ToDynamicObject());
            }
            catch (Exception ex)
            {
                //
                var result = GetExceptionActionResult(ex);
                return result;
            }
        }

        /// <summary>
        /// Request AccessToken for Specific XApiScope
        /// </summary>
        /// <param name="scope">a member of <see>XApiScope</see></param>
        /// <returns>an instance of <see>XTokenResponse</see></returns>
        [AllowAnonymous]
        [RequireXPowered]
        [HttpPost("RequestScopeAccessToken")]
        public async Task<ActionResult<XTokenResponse>> RequestScopeAccessToken(
            [FromHeader] XApiScope scope
        )
        {
            //
            // Do Action ...
            try
            {
                //
                // Validate Args ...
                var scopeName = string.Empty;
                try
                {
                    scopeName = scope.GetStringValue();
                }
                catch { }
                ValidationProvider.NotEmpty(scopeName);

                //
                var result = await IdentityManager
                    .RequestScopeAccessToken(scopeName);

                //
                // Ceck Response Result ...
                if (result.IsError)
                {
                    XException.InvalidConfiguration.Throw();
                }

                //
                return Ok(result
                    .CreateXTokenResponse()
                    .ToDynamicObject());
            }
            catch (Exception ex)
            {
                //
                var result = GetExceptionActionResult(ex);
                return result;
            }
        }

        /// <summary>
        /// Authenticate User
        /// </summary>
        /// <remarks>
        /// Sample request:
        /// 
        ///     {
        ///         "password": "",
        ///         "userSelectBy": "",
        ///     }
        /// 
        /// </remarks>
        /// <param name="model">an instance of <see>XLoginRequest</see> class which represent Authentication requirements</param>
        /// <returns>an instance of <see>XTokenResponse</see></returns>
        [AllowAnonymous]
        [RequireXPowered]
        [HttpPost("Authenticate")]
        public async Task<ActionResult<XTokenResponse>> Authenticate(
            [FromBody] XLoginRequest model
        )
        {
            //
            // Do Action ...
            try
            {
                //
                // Validate Args ...
                if (!ModelState.IsValid)
                {
                    XException.InvalidArgs.Throw();
                }
                await ValidationProvider
                    .GroupValidationBuilder()
                    .AddNotNull(model)
                    .AddNotEmpty(
                        model.UserSelectBy,
                        model.Password
                    )
                    .ValidateGroupAsync();

                //
                var result = await IdentityManager
                    .Authenticate(model);

                //
                // Check Result ...
                if (result.IsError)
                {
                    throw result.GetException();
                }

                //
                // Return Result ...
                return Ok(result
                    .CreateXTokenResponse()
                    .ToDynamicObject());
            }
            catch (Exception ex)
            {
                //
                var result = GetExceptionActionResult(ex);
                return result;
            }
        }

        /// <summary>
        /// Authenticate User
        /// </summary>
        /// <remarks>
        /// Sample request:
        /// 
        ///     {
        ///         "language": "fa-IR"
        ///         "password": "",
        ///         "userSelectBy": "",
        ///         "device": {
        ///             "os":"Mac",
        ///             "browser":"Chrome",
        ///             "osVersion":"mac-os-x-15",
        ///             "userAgent":"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_3) AppleWebKit/537.36 (KHTML, like Gecko) x-framework-test/0.0.0 Chrome/87.0.4280.141 Electron/11.2.0 Safari/537.36",
        ///             "deviceType":3,
        ///             "identifier":"[Mac]-[mac-os-x-15]-[3]-[Chrome]-[Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_3) AppleWebKit/537.36 (KHTML, like Gecko) x-framework-test/0.0.0 Chrome/87.0.4280.141 Electron/11.2.0 Safari/537.36]",
        ///             "token":"96f400dd9aa5c57a8cec9d6f4775bad3"
        ///         }
        ///     }
        /// 
        /// </remarks>
        /// <param name="model">an instance of <see>XLoginRequest</see> class which represent Authentication requirements</param>
        /// <returns>an instance of <see>XLoginResponse</see></returns>
        [AllowAnonymous]
        [RequireXPowered]
        [HttpPost("Login")]
        public async Task<ActionResult<XLoginResponse>> Login(
            [FromBody] XLoginRequest model
        )
        {
            //
            // Do Action ...
            try
            {
                //
                // Validate Args ...
                if (!ModelState.IsValid)
                {
                    XException.InvalidArgs.Throw();
                }
                await ValidationProvider
                    .GroupValidationBuilder()
                    .AddNotNull(
                        model,
                        model.Device)
                    .AddNotEmpty(
                        model.Language,
                        model.UserSelectBy,
                        model.Password
                    )
                    .ValidateGroupAsync();

                //
                var result = await IdentityManager
                    .Login(model);

                //
                return Ok(result
                    .ToDynamicObject());
            }
            catch (Exception ex)
            {
                //
                var result = GetExceptionActionResult(ex);
                return result;
            }
        }

        /// <summary>
        /// Refresh Expired Tokens
        /// </summary>
        /// <remarks>
        /// in addition to AccessToken, you had to pass RefreshToken due to Headers
        /// </remarks>
        /// <returns>an instance of <see>XTokenResponse</see></returns>
        [AllowAnonymous]
        [RequireXPowered]
        [HttpPost("RefreshTokens")]
        public async Task<ActionResult<XTokenResponse>> RefreshTokens()
        {
            //
            // Do Action ...
            try
            {
                //
                // Retrieve Toke Response ...
                var model = await RetrieveTokensAsXTokenResponse();

                //
                // Validate Args ...
                ValidationProvider
                    .GroupValidationBuilder()
                    .AddNotNull(model)
                    .AddNotEmpty(
                        model.AccessToken,
                        model.RefreshToken)
                    .ValidateGroup();

                //
                var result = await IdentityManager
                    .RefreshTokens(model);

                //
                return Ok(result
                    .ToDynamicObject());
            }
            catch (Exception ex)
            {
                //
                var result = GetExceptionActionResult(ex);
                return result;
            }
        }
        #endregion

        //
        #region Password Actions ...
        /// <summary>
        /// Change a User's Password ...
        /// </summary>
        /// <remarks>
        ///     for this action you have to provide:
        ///         - Lang: client device currently used locale, such as: en-US.
        ///         - Password: user's current active password.
        ///         - NewPassword: user's new password to change.
        ///         - Device: user's client device which is an instance of XDevice.
        ///         - ReturnUrl: client application Login URL.
        /// 
        /// Sample request:
        /// 
        ///     {
        ///         "lang": "fa-IR",
        ///         "password": ""
        ///         "newPassword": "",
        ///         "returnUrl": "http://localhost/login",
        ///         "device": {
        ///             "os":"Mac",
        ///             "browser":"Chrome",
        ///             "osVersion":"mac-os-x-15",
        ///             "userAgent":"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_3) AppleWebKit/537.36 (KHTML, like Gecko) x-framework-test/0.0.0 Chrome/87.0.4280.141 Electron/11.2.0 Safari/537.36",
        ///             "deviceType":3,
        ///             "identifier":"[Mac]-[mac-os-x-15]-[3]-[Chrome]-[Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_3) AppleWebKit/537.36 (KHTML, like Gecko) x-framework-test/0.0.0 Chrome/87.0.4280.141 Electron/11.2.0 Safari/537.36]",
        ///             "token":"96f400dd9aa5c57a8cec9d6f4775bad3"
        ///         }
        ///     }
        /// 
        /// </remarks>
        /// <param name="model">an instance of <see>XActionRequest</see> class which provider requirement for action</param>
        /// <returns></returns>
        [RequireXPowered]
        [HttpPost("ChangePassword")]
        [Authorize(Policy = XPolicies.User)]
        [Authorize(Policy = XPolicies.EnabledUser)]
        [Authorize(Policy = LocalApi.PolicyName)]
        public async Task<ActionResult> ChangePassword(
            [FromBody] XActionRequest model
        )
        {
            //
            // Do Action ...
            try
            {
                //
                // Validate Args ...
                if (!ModelState.IsValid)
                {
                    XException.InvalidArgs.Throw();
                }
                await ValidationProvider
                    .GroupValidationBuilder()
                    .AddNotNull(
                        model,
                        model.Device
                    )
                    .AddNotEmpty(
                        model.Lang,
                        model.Password,
                        model.NewPassword,
                        model.ReturnUrl
                    )
                    .ValidateGroupAsync();

                //
                // Get User Select By ...
                var userSelectByParam = GetUserSelectByParam(
                    model,
                    forceNotNull: false
                );
                if (userSelectByParam.IsNullOrEmpty())
                {
                    userSelectByParam = User.Identity.Name;
                }
                ValidationProvider.NotEmpty(userSelectByParam);

                //
                // Get Request ...
                await IdentityManager
                    .ChangePassword(
                        model.Lang,
                        model.Device,
                        userSelectByParam,
                        model.Password,
                        model.NewPassword,
                        model.ReturnUrl
                    );

                //
                return Ok();
            }
            catch (Exception ex)
            {
                //
                var exResult = GetExceptionActionResult(ex);
                return exResult;
            }
        }
        #endregion
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\xIds\Controllers\Account\AccountController+Friendship.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using xCommons.Attributes;
using xCommons.Extensions;
using xExceptions.Constants;
using xIdentityHelper;
using xIdentityModels.Constants;
using xIdentityModels.Dtos;
using xIdentityModels.Navigations;
using xModels.Dtos;
using static IdentityServer4.IdentityServerConstants;

namespace xIds.Controllers
{
    public partial class AccountController
    {
        //
        #region Friendship Actions ...
        //
        #region Actions ...
        /// <summary>
        /// Follow a User
        /// </summary>
        /// <param name="destUser">a user identifier which represent destination user</param>
        /// <returns>an instance of <see>XFriendshipFollowing</see></returns>
        [RequireXPowered]
        [HttpPost("Friendship/{destUser}/Follow")]
        [Authorize(Policy = LocalApi.PolicyName)]
        [Authorize(Policy = XPolicies.EnabledUser)]
        public async Task<ActionResult<XFriendshipFollowing>> Follow(
            [FromRoute] string destUser
        )
        {
            //
            // Do Action ...
            try
            {
                //
                // Validate Args ...
                ValidationProvider.NotEmpty(destUser);

                //
                var result = await IdentityManager
                    .Follow(
                        User.Identity.Name,
                        destUser
                    );

                //
                return Ok(result
                    .ToDynamicObject());
            }
            catch (Exception ex)
            {
                //
                var exResult = GetExceptionActionResult(ex);
                return exResult;
            }
        }

        /// <summary>
        /// Cancel Following
        /// </summary>
        /// <param name="destUser">a user identifier which represent destination user</param>
        /// <returns>a boolean value</returns>
        [HttpPost("Friendship/{destUser}/Cancel")]
        [Authorize(Policy = LocalApi.PolicyName)]
        [Authorize(Policy = XPolicies.EnabledUser)]
        public async Task<ActionResult<bool>> Cancel(
            [FromRoute] string destUser
        )
        {
            //
            // Do Action ...
            try
            {
                //
                // Validate Args ...
                ValidationProvider.NotEmpty(destUser);

                //
                var result = await IdentityManager
                    .Cancel(
                        User.Identity.Name,
                        destUser
                    );

                //
                return Ok(result);
            }
            catch (Exception ex)
            {
                //
                var exResult = GetExceptionActionResult(ex);
                return exResult;
            }
        }

        /// <summary>
        /// Unfollow a Follower
        /// </summary>
        /// <param name="destUser">a user identifier which represent destination user</param>
        /// <returns></returns>
        [HttpPost("Friendship/{destUser}/UnFollowFollower")]
        [Authorize(Policy = LocalApi.PolicyName)]
        [Authorize(Policy = XPolicies.EnabledUser)]
        public async Task<ActionResult> UnFollowFollower(
            [FromRoute] string destUser
        )
        {
            //
            // Do Action ...
            try
            {
                //
                // Validate Args ...
                ValidationProvider.NotEmpty(destUser);

                //
                await IdentityManager
                    .UnFollowFollower(
                        User.Identity.Name,
                        destUser
                    );

                //
                return Ok();
            }
            catch (Exception ex)
            {
                //
                var exResult = GetExceptionActionResult(ex);
                return exResult;
            }
        }

        /// <summary>
        /// Unfollow Following
        /// </summary>
        /// <param name="destUser">a user identifier which represent destination user</param>
        /// <returns></returns>
        [Authorize(Policy = LocalApi.PolicyName)]
        [Authorize(Policy = XPolicies.EnabledUser)]
        [HttpPost("Friendship/{destUser}/UnFollowFollowing")]
        public async Task<ActionResult> UnFollowFollowing(
            [FromRoute] string destUser
        )
        {
            //
            // Do Action ...
            try
            {
                //
                // Validate Args ...
                ValidationProvider.NotEmpty(destUser);

                //
                await IdentityManager
                    .UnFollowFollowing(
                        User.Identity.Name,
                        destUser
                    );

                //
                return Ok();
            }
            catch (Exception ex)
            {
                //
                var exResult = GetExceptionActionResult(ex);
                return exResult;
            }
        }

        /// <summary>
        /// Block a Follower
        /// </summary>
        /// <param name="destUser">a user identifier which represent destination user</param>
        /// <returns>an instance of <see>XFriendshipFollowing</see></returns>
        [HttpPost("Friendship/{destUser}/Block")]
        [Authorize(Policy = LocalApi.PolicyName)]
        [Authorize(Policy = XPolicies.EnabledUser)]
        public async Task<ActionResult<XFriendshipFollowing>> Block(
            [FromRoute] string destUser
        )
        {
            //
            // Do Action ...
            try
            {
                //
                // Validate Args ...
                ValidationProvider.NotEmpty(destUser);

                //
                var result = await IdentityManager
                    .Block(
                        User.Identity.Name,
                        destUser
                    );

                //
                return Ok(result
                    .ToDynamicObject());
            }
            catch (Exception ex)
            {
                //
                var exResult = GetExceptionActionResult(ex);

                //
                return exResult;
            }
        }

        /// <summary>
        /// Unblock a Blocked User
        /// </summary>
        /// <param name="destUser">an instance of <see>XFriendshipFollowing</see></param>
        /// <returns>an instance of <see>XFriendshipFollowing</see></returns>
        [HttpPost("Friendship/{destUser}/UnBlock")]
        [Authorize(Policy = LocalApi.PolicyName)]
        [Authorize(Policy = XPolicies.EnabledUser)]
        public async Task<ActionResult<XFriendshipFollowing>> UnBlock(
            [FromRoute] string destUser
        )
        {
            //
            // Do Action ...
            try
            {
                //
                // Validate Args ...
                ValidationProvider.NotEmpty(destUser);

                //
                var result = await IdentityManager
                    .UnBlock(
                        User.Identity.Name,
                        destUser
                    );

                //
                return Ok(result
                    .ToDynamicObject());
            }
            catch (Exception ex)
            {
                //
                var exResult = GetExceptionActionResult(ex);
                return exResult;
            }
        }
        #endregion

        //
        #region Request Handlers ...
        /// <summary>
        /// Accept a Following Request 
        /// </summary>
        /// <param name="destUser">a user identifier which represent destination user</param>
        /// <returns>an instance of <see>XFriendshipFollower</see></returns>
        [Authorize(Policy = LocalApi.PolicyName)]
        [Authorize(Policy = XPolicies.EnabledUser)]
        [HttpPost("Friendship/{destUser}/AcceptRequest")]
        public async Task<ActionResult<XFriendshipFollower>> AcceptRequest(
            [FromRoute] string destUser
        )
        {
            //
            // Do Action ...
            try
            {
                //
                // Validate Args ...
                ValidationProvider.NotEmpty(destUser);

                //
                var result = await IdentityManager
                    .AcceptRequest(
                        User.Identity.Name,
                        destUser
                    );

                //
                return Ok(result
                    .ToDynamicObject());
            }
            catch (Exception ex)
            {
                //
                var exResult = GetExceptionActionResult(ex);
                return exResult;
            }
        }

        /// <summary>
        /// Reject a Following Request
        /// </summary>
        /// <param name="destUser">a user identifier which represent destination user</param>
        /// <returns>an instance of <see>XFriendshipFollower</see></returns>
        [Authorize(Policy = LocalApi.PolicyName)]
        [Authorize(Policy = XPolicies.EnabledUser)]
        [HttpPost("Friendship/{destUser}/RejectRequest")]
        public async Task<ActionResult<XFriendshipFollower>> RejectRequest(
            [FromRoute] string destUser
        )
        {
            //
            // Do Action ...
            try
            {
                //
                // Validate Args ...
                ValidationProvider.NotEmpty(destUser);

                //
                var result = await IdentityManager
                    .RejectRequest(
                        User.Identity.Name,
                        destUser
                    );

                //
                return Ok(result
                    .ToDynamicObject());
            }
            catch (Exception ex)
            {
                //
                var exResult = GetExceptionActionResult(ex);
                return exResult;
            }
        }
        #endregion

        //
        #region Getters ...
        /// <summary>
        /// Check a User IsFollower of Requested User 
        /// </summary>
        /// <param name="destUser">a user identifier which represent destination user</param>
        /// <returns>a boolean value</returns>
        [Authorize(Policy = LocalApi.PolicyName)]
        [Authorize(Policy = XPolicies.EnabledUser)]
        [HttpGet("Friendship/{destUser}/IsFollower")]
        public async Task<ActionResult<bool>> IsFollower(
            [FromRoute] string destUser
        )
        {
            //
            // Do Action ...
            try
            {
                //
                // Validate Args ...
                ValidationProvider.NotEmpty(destUser);

                //
                var result = await IdentityManager
                    .IsFollower(
                        User.Identity.Name,
                        destUser
                    );

                //
                return Ok(result);
            }
            catch (Exception ex)
            {
                //
                var exResult = GetExceptionActionResult(ex);
                return exResult;
            }
        }

        /// <summary>
        /// Get Follower State of a User
        /// </summary>
        /// <param name="destUser">a user identifier which represent destination user</param>
        /// <returns>an instance of <see>XFriendshipState</see></returns>
        [Authorize(Policy = LocalApi.PolicyName)]
        [Authorize(Policy = XPolicies.EnabledUser)]
        [HttpGet("Friendship/{destUser}/FollowerState")]
        public async Task<ActionResult<XFriendshipState>> FollowerState(
            [FromRoute] string destUser
        )
        {
            //
            // Do Action ...
            try
            {
                //
                // Validate Args ...
                ValidationProvider.NotEmpty(destUser);

                //
                var result = await IdentityManager
                    .GetFollowerState(
                        User.Identity.Name,
                        destUser
                    );

                //
                return Ok(result);
            }
            catch (Exception ex)
            {
                //
                var exResult = GetExceptionActionResult(ex);
                return exResult;
            }
        }

        /// <summary>
        /// Get Specific Follower 
        /// </summary>
        /// <param name="destUser">a user identifier which represent destination user</param>
        /// <returns>an instance of <see>XFriendshipFollower</see></returns>
        [Authorize(Policy = LocalApi.PolicyName)]
        [Authorize(Policy = XPolicies.EnabledUser)]
        [HttpGet("Friendship/{destUser}/Follower")]
        public async Task<ActionResult<XFriendshipFollower>> Follower(
            [FromRoute] string destUser
        )
        {
            //
            // Do Action ...
            try
            {
                //
                // Validate Args ...
                ValidationProvider.NotEmpty(destUser);

                //
                var result = await IdentityManager
                    .GetFollower(
                        User.Identity.Name,
                        destUser
                    );

                //
                return Ok(result
                    .ToDynamicObject());
            }
            catch (Exception ex)
            {
                //
                var exResult = GetExceptionActionResult(ex);
                return exResult;
            }
        }

        /// <summary>
        /// Get Followers List Of Current User 
        /// </summary>
        /// <returns>a collection of <see>XFriendshipFollower</see></returns>
        [HttpGet("Friendship/Followers")]
        [Authorize(Policy = LocalApi.PolicyName)]
        [Authorize(Policy = XPolicies.EnabledUser)]
        public async Task<ActionResult<IEnumerable<XFriendshipFollower>>> Followers()
        {
            //
            // Do Action ...
            try
            {
                //
                var result = await IdentityManager
                    .GetFollowers(User.Identity.Name);

                //
                return Ok(result
                    .ToDynamicObject());
            }
            catch (Exception ex)
            {
                //
                var exResult = GetExceptionActionResult(ex);

                //
                return exResult;
            }
        }

        /// <summary>
        /// Get All Followers List Includes Blocked, Requested and etc 
        /// of Current User
        /// </summary>
        /// <returns>a collection of <see>XFriendshipFollower</see></returns>
        [HttpGet("Friendship/AllFollowers")]
        [Authorize(Policy = LocalApi.PolicyName)]
        [Authorize(Policy = XPolicies.EnabledUser)]
        public async Task<ActionResult<IEnumerable<XFriendshipFollower>>> AllFollowers()
        {
            //
            // Do Action ...
            try
            {
                //
                var result = await IdentityManager
                    .GetAllFollowers(User.Identity.Name);

                //
                return Ok(result
                    .ToDynamicObject());
            }
            catch (Exception ex)
            {
                //
                var exResult = GetExceptionActionResult(ex);
                return exResult;
            }
        }

        /// <summary>
        /// Get All Followers List Includes Blocked, Requested and etc 
        /// of Current User based On Query Model ...
        /// </summary>
        /// <returns>a Query Result of <see>XFriendDto</see></returns>
        [HttpGet("Friendship/QueryFollowers")]
        [Authorize(Policy = LocalApi.PolicyName)]
        [Authorize(Policy = XPolicies.EnabledUser)]
        public async Task<ActionResult<XQueryResult<XFriendDto>>> QueryFollowers(
            [FromQuery] XQuery query,
            [FromQuery] string destUser
        )
        {
            //
            // Do Action ...
            try
            {
                //
                // Normalizing Dest User ...
                var userInfo = await GetUserInfo();
                bool isAdmin = userInfo.Roles.Contains(XUserRoles.ADMIN);
                if (destUser.IsNullOrEmpty())
                {
                    destUser = userInfo.UserName;
                }
                bool isDestUserValid = isAdmin || destUser == userInfo.UserId || destUser == userInfo.Email || destUser == userInfo.PhoneNumber || destUser == userInfo.UserName;
                if (!isDestUserValid)
                {
                    XException.NotAllowed.Throw();
                }

                //                
                var result = await IdentityManager
                    .QueryFollowers(
                        query: query,
                        userSelectByParam: destUser
                    );

                //
                return Ok(result
                    .ToDynamicObject());
            }
            catch (Exception ex)
            {
                //
                var exResult = GetExceptionActionResult(ex);
                return exResult;
            }
        }

        /// <summary>
        /// Check a User is in Followings of Current User
        /// </summary>
        /// <param name="destUser">a user identifier which represent destination user</param>
        /// <returns>a boolean value</returns>
        [Authorize(Policy = LocalApi.PolicyName)]
        [Authorize(Policy = XPolicies.EnabledUser)]
        [HttpGet("Friendship/{destUser}/IsFollowing")]
        public async Task<ActionResult<bool>> IsFollowing(
            [FromRoute] string destUser
        )
        {
            //
            // Do Action ...
            try
            {
                //
                // Validate Args ...
                ValidationProvider.NotEmpty(destUser);

                //
                var result = await IdentityManager
                    .IsFollowing(
                        User.Identity.Name,
                        destUser
                    );

                //
                return Ok(result);
            }
            catch (Exception ex)
            {
                //
                var exResult = GetExceptionActionResult(ex);
                return exResult;
            }
        }

        /// <summary>
        /// Get Following State Relation between Specific User 
        /// and Current User
        /// </summary>
        /// <param name="destUser">a user identifier which represent destination user</param>
        /// <returns>an instance of <see>XFriendshipState</see></returns>
        [Authorize(Policy = LocalApi.PolicyName)]
        [Authorize(Policy = XPolicies.EnabledUser)]
        [HttpGet("Friendship/{destUser}/FollowingState")]
        public async Task<ActionResult<XFriendshipState>> FollowingState(
            [FromRoute] string destUser
        )
        {
            //
            // Do Action ...
            try
            {
                //
                // Validate Args ...
                ValidationProvider.NotEmpty(destUser);

                //
                var result = await IdentityManager
                    .GetFollowingState(
                        User.Identity.Name,
                        destUser
                    );

                //
                return Ok(result);
            }
            catch (Exception ex)
            {
                //
                var exResult = GetExceptionActionResult(ex);
                return exResult;
            }
        }

        /// <summary>
        /// Get Specific Following Model
        /// </summary>
        /// <param name="destUser">a user identifier which represent destination user</param>
        /// <returns>an instance of <see>XFriendshipFollowing</see></returns>
        [Authorize(Policy = LocalApi.PolicyName)]
        [Authorize(Policy = XPolicies.EnabledUser)]
        [HttpGet("Friendship/{destUser}/Following")]
        public async Task<ActionResult<XFriendshipFollowing>> Following(
            [FromRoute] string destUser
        )
        {
            //
            // Do Action ...
            try
            {
                //
                // Validate Args ...
                ValidationProvider.NotEmpty(destUser);

                //
                var result = await IdentityManager
                    .GetFollowing(
                        User.Identity.Name,
                        destUser
                    );

                //
                return Ok(result
                    .ToDynamicObject());
            }
            catch (Exception ex)
            {
                //
                var exResult = GetExceptionActionResult(ex);
                return exResult;
            }
        }

        /// <summary>
        /// Get Followings of Current User
        /// </summary>
        /// <returns>a collection of <see>XFriendshipFollowing</see></returns>
        [HttpGet("Friendship/Followings")]
        [Authorize(Policy = LocalApi.PolicyName)]
        [Authorize(Policy = XPolicies.EnabledUser)]
        public async Task<ActionResult<IEnumerable<XFriendshipFollowing>>> Followings()
        {
            //
            // Do Action ...
            try
            {
                //
                var result = await IdentityManager
                    .GetFollowings(User.Identity.Name);

                //
                return Ok(result
                    .ToDynamicObject());
            }
            catch (Exception ex)
            {
                //
                var exResult = GetExceptionActionResult(ex);
                return exResult;
            }
        }

        /// <summary>
        /// Get All Following List Includes Blocked, Requested and etc 
        /// of Current User
        /// </summary>
        /// <returns>a collection of <see>XFriendshipFollowing</see></returns>
        [HttpGet("Friendship/AllFollowings")]
        [Authorize(Policy = LocalApi.PolicyName)]
        [Authorize(Policy = XPolicies.EnabledUser)]
        public async Task<ActionResult<IEnumerable<XFriendshipFollowing>>> AllFollowings()
        {
            //
            // Do Action ...
            try
            {
                //
                var result = await IdentityManager
                    .GetAllFollowings(User.Identity.Name);

                //
                return Ok(result
                    .ToDynamicObject());
            }
            catch (Exception ex)
            {
                //
                var exResult = GetExceptionActionResult(ex);
                return exResult;
            }
        }

        /// <summary>
        /// Get All Following List Includes Blocked, Requested and etc 
        /// of Current User based On Query Model ...
        /// </summary>
        /// <returns>a Query Result of <see>XFriendDto</see></returns>
        [HttpGet("Friendship/QueryFollowings")]
        [Authorize(Policy = LocalApi.PolicyName)]
        [Authorize(Policy = XPolicies.EnabledUser)]
        public async Task<ActionResult<XQueryResult<XFriendDto>>> QueryFollowings(
            [FromQuery] XQuery query,
            [FromQuery] string destUser
        )
        {
            //
            // Do Action ...
            try
            {
                //
                // Normalizing Dest User ...
                var userInfo = await GetUserInfo();
                bool isAdmin = userInfo.Roles.Contains(XUserRoles.ADMIN);
                if (destUser.IsNullOrEmpty())
                {
                    destUser = userInfo.UserName;
                }
                bool isDestUserValid = isAdmin || destUser == userInfo.UserId || destUser == userInfo.Email || destUser == userInfo.PhoneNumber || destUser == userInfo.UserName;
                if (!isDestUserValid)
                {
                    XException.NotAllowed.Throw();
                }

                //                
                var result = await IdentityManager
                    .QueryFollowings(
                        query: query,
                        userSelectByParam: destUser
                    );

                //
                return Ok(result
                    .ToDynamicObject());
            }
            catch (Exception ex)
            {
                //
                var exResult = GetExceptionActionResult(ex);
                return exResult;
            }
        }
        #endregion

        //
        #region Others ...
        /// <summary>
        /// Return Following UserName's List of Current User 
        /// </summary>
        /// <returns>a collection of UserNames</returns>
        [HttpGet("Friendship/FollowingsList")]
        [Authorize(Policy = LocalApi.PolicyName)]
        [Authorize(Policy = XPolicies.EnabledUser)]
        public async Task<ActionResult<IEnumerable<string>>> FollowingsList()
        {
            //
            // Do Action ...
            try
            {
                //
                var result = await IdentityManager
                    .GetFollowingList(User.Identity.Name);

                //
                return Ok(result
                    .ToDynamicObject());
            }
            catch (Exception ex)
            {
                //
                var exResult = GetExceptionActionResult(ex);
                return exResult;
            }
        }

        /// <summary>
        /// Return Followers UserName's List of Current User 
        /// </summary>
        /// <returns>a collection of UserNames</returns>
        [HttpGet("Friendship/FollowersList")]
        [Authorize(Policy = LocalApi.PolicyName)]
        [Authorize(Policy = XPolicies.EnabledUser)]
        public async Task<ActionResult<IEnumerable<string>>> FollowersList()
        {
            //
            // Do Action ...
            try
            {
                //
                var result = await IdentityManager
                    .GetFollowersList(User.Identity.Name);

                //
                return Ok(result
                    .ToDynamicObject());
            }
            catch (Exception ex)
            {
                //
                var exResult = GetExceptionActionResult(ex);
                return exResult;
            }
        }

        /// <summary>
        /// Get Friendship Info Model between Specific User and Current User
        /// </summary>
        /// <param name="destUser">a user identifier which represent destination user</param>
        /// <returns>an instance of <see>XFriendshipInfoDto</see></returns>
        [HttpGet("Friendship/{destUser}/FriendshipInfo")]
        [Authorize(Policy = LocalApi.PolicyName)]
        [Authorize(Policy = XPolicies.EnabledUser)]
        public async Task<ActionResult<XFriendshipInfoDto>> FriendshipInfo(
            [FromRoute] string destUser
        )
        {
            //
            // Do Action ...
            try
            {
                //
                var result = await IdentityManager
                    .GetFriendshipInfo(User.Identity.Name, destUser);

                //
                return Ok(result
                    .ToDynamicObject());
            }
            catch (Exception ex)
            {
                //
                var exResult = GetExceptionActionResult(ex);
                return exResult;
            }
        }
        #endregion
        #endregion        
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\xIds\Controllers\Account\AccountController+Open.cs

using System;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using xCommons.Attributes;
using xCommons.Constants;
using xIdentityModels.Dtos;

namespace xIds.Controllers
{
    public partial class AccountController
    {
        //
        // Implememnt all Open Actions here ...

        //
        #region Open Actions ...
        [AllowAnonymous]
        [RequireXPowered]
        [HttpGet("Open")]
        public async Task<ActionResult<string>> Get(
            [FromHeader] string token,
            [FromQuery] string request
        )
        {
            //
            // Do Action ...
            try
            {
                //
                // Validate Args ...
                await ValidationProvider
                    .GroupValidationBuilder()
                    .AddNotEmpty(token)
                    .AddNotEmpty(request)
                    .ValidateGroupAsync();

                //
                // Prepare Inner Dto Model ...
                var dto = new XOpenActionInnerDto
                {
                    Token = token,
                    Payload = request
                };

                //
                // Do Action ...
                var resultDto = await IdentityManager.OpenGet(dto);
                Response.Headers.Add(XAuthentication.TOKEN, resultDto.Token);

                //
                // Return Result
                return Ok(resultDto.Payload);
            }
            catch (Exception ex)
            {
                //
                var result = GetExceptionActionResult(ex);
                return result;
            }
        }
        #endregion

        //
        #region Private ...
        #endregion
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\xIds\Controllers\Account\AccountController+Profile.cs

using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using xIdentityHelper;
using xCommons.Attributes;
using xCommons.Extensions;
using xIdentityModels.Dtos;
using xIdentityModels.Models;
using xModels.Dtos;
using static IdentityServer4.IdentityServerConstants;

namespace xIds.Controllers
{
    public partial class AccountController
    {
        //
        #region Retrieve Actions ...
        /// <summary>
        /// Retrieve User Names based on UserIds
        /// </summary>
        /// <param name="ids">a comma seperated list of UserIds</param>
        /// <returns>a collection of UserNames</returns>
        [HttpGet("Profile/{ids}/GetNames")]
        [Authorize(Policy = XPolicies.User)]
        [Authorize(Policy = LocalApi.PolicyName)]
        [Authorize(Policy = XPolicies.EnabledUser)]
        public async Task<ActionResult<IEnumerable<string>>> GetNames(
            [FromRoute] string ids
        )
        {
            //
            // Do Action ...
            try
            {
                //
                ValidationProvider.NotEmpty(ids);

                //
                var xIdList = ids.ParseListString<string>();
                var result = await IdentityManager.GetUserNamesAsync(
                    xIdList
                );

                //
                // Return Result
                return Ok(result
                    .ToDynamicObject());
            }
            catch (Exception ex)
            {
                //
                var result = GetExceptionActionResult(ex);
                return result;
            }
        }

        /// <summary>
        /// get user ids and retrieve corresponding user names
        /// </summary>
        /// <param name="model">an instance of <see>XUserNameIdRequest</see> which represent required UserIds collection</param>
        /// <returns>a collection of <see>XUserNameIdResponse</see> instance</returns>
        [HttpPost("Profile/GetNameIds")]
        [Authorize(Policy = XPolicies.User)]
        [Authorize(Policy = LocalApi.PolicyName)]
        [Authorize(Policy = XPolicies.EnabledUser)]
        public async Task<ActionResult<IEnumerable<XUserNameIdResponse>>> GetNameIds(
            [FromBody] XUserNameIdRequest model
        )
        {
            //
            // Do Action ...
            try
            {
                //
                ValidationProvider.NotNull(model);

                //
                var result = await IdentityManager.GetUserNameIdsAsync(
                    model
                );

                //
                // Return Result
                return Ok(result
                    .ToDynamicObject());
            }
            catch (Exception ex)
            {
                //
                var result = GetExceptionActionResult(ex);
                return result;
            }
        }

        /// <summary>
        /// Get Profile Object of Specific User 
        /// </summary>
        /// <param name="userSelectByParam">specifies which user profile must be retrieved</param>
        /// <returns>an instance of <see>XUserProfileDto</see></returns>
        [RequireXPowered]
        [Authorize(Policy = XPolicies.User)]
        [Authorize(Policy = LocalApi.PolicyName)]
        [HttpGet("Profile/{userSelectByParam?}")]
        [Authorize(Policy = XPolicies.EnabledUser)]
        public async Task<ActionResult<XUserProfileDto>> GetProfile(
            [FromRoute] string userSelectByParam = ""
        )
        {
            //
            // Do Action ...
            try
            {
                //
                if (userSelectByParam.IsNullOrEmpty())
                {
                    userSelectByParam = User.Identity.Name;
                }

                //
                var result = await IdentityManager
                    .GetUserProfileAsync(
                        userSelectByParam,
                        User.Identity.Name
                    );

                //
                // Return Result
                return Ok(result
                    .ToDynamicObject());
            }
            catch (Exception ex)
            {
                //
                var result = GetExceptionActionResult(ex);
                return result;
            }
        }

        /// <summary>
        /// Query Users 
        /// for specifiy users role for query user 'role: string' and 'forceRole: boolean' in header
        /// </summary>
        /// <param name="query">how to filter results based on <see>XQuery</see> structure</param>
        /// <param name="role">an string which represent user role</param>
        /// <param name="forceRole">if it's true the user must has exact role, otherwise top level users also listed</param>
        /// <returns>an instance of <see>XQueryResult</see> of <see>XUserProfileDto</see></returns>
        [RequireXPowered]
        [HttpGet("Profile/Query")]
        [Authorize(Policy = LocalApi.PolicyName)]
        [Authorize(Policy = XPolicies.EnabledAdmin)]
        [Authorize(Policy = XPolicies.EnabledAgent)]
        public async Task<ActionResult<XQueryResult<XUserProfileDto>>> QueryProfiles(
            [FromQuery] XQuery query, [FromHeader] string role, [FromHeader] bool forceRole = false
        )
        {
            //
            // Do Action ...
            try
            {
                //
                var userId = User.Identity.Name;

                //
                var result = new XQueryResult<XUserProfileDto>();
                if (role.IsNullOrEmpty())
                {
                    //
                    result = await IdentityManager.QueryUsers(
                        userId,
                        query
                    );
                }
                else
                {
                    //
                    result = await IdentityManager.QueryInRoleUsers(
                        userId,
                        role,
                        query,
                        forceRole
                    );
                }

                //
                return Ok(result
                    .ToDynamicObject());
            }
            catch (Exception ex)
            {
                //
                var exception = GetExceptionActionResult(ex);
                return exception;
            }
        }

        /// <summary>
        /// Query Specified User's Profile Images
        /// </summary>
        /// <param name="userSelectByParam">determine's which user profile must be retrieved</param>
        /// <param name="query">how to filter results based on <see>XQuery</see> structure</param>
        /// <returns>an instance of <see>XQueryResult</see> of <see>XProfileImage</see></returns>
        [RequireXPowered]
        [Authorize(Policy = XPolicies.User)]
        [Authorize(Policy = LocalApi.PolicyName)]
        [Authorize(Policy = XPolicies.EnabledUser)]
        [Authorize(Policy = XPolicies.EnabledAdmin)]
        [HttpGet("Profile/Avatars/Query/{userSelectByParam?}")]
        public async Task<ActionResult<XQueryResult<XProfileImageDto>>> QueryAvatars(
            [FromQuery] XQuery query, [FromRoute] string userSelectByParam = null
        )
        {
            //
            // Do Action ...
            try
            {
                //
                if (userSelectByParam.IsNullOrEmpty())
                {
                    userSelectByParam = User.Identity.Name;
                }

                //
                var result = await IdentityManager.QueryAvatars(
                    userSelectByParam,
                    query
                );

                //
                return Ok(result
                    .ToDynamicObject());
            }
            catch (Exception ex)
            {
                //
                var exception = GetExceptionActionResult(ex);
                return exception;
            }
        }
        #endregion

        //
        #region Update Actions ...
        /// <summary>
        /// Update User Profile based on XProfileUpdateRequest (FirstName/LastName/DateOfBirth)
        /// </summary>
        /// <param name="model">user update info, an instance of <see>XProfileUpdateRequest</see></param>
        /// <param name="userSelectByParam">determine's which user profile must be retrieved</param>
        /// <returns>an instance of <see>XUserProfileDto</see></returns>
        [RequireXPowered]
        [Authorize(Policy = LocalApi.PolicyName)]
        [Authorize(Policy = XPolicies.EnabledUser)]
        [HttpPost("Profile/Update/{userSelectByParam?}")]
        public async Task<ActionResult<XUserProfileDto>> UpdateProfile(
            [FromBody] XProfileUpdateRequest model, [FromRoute] string userSelectByParam = null
        )
        {
            //
            // Do Action ...
            try
            {
                //
                if (userSelectByParam.IsNullOrEmpty())
                {
                    userSelectByParam = User.Identity.Name;
                }

                //
                var result = await IdentityManager.ProfileUpdateAsync(
                    userSelectByParam,
                    User.Identity.Name,
                    model
                );

                //
                // Return Result
                return Ok(result
                    .ToDynamicObject());
            }
            catch (Exception ex)
            {
                //
                var result = GetExceptionActionResult(ex);
                return result;
            }
        }

        /// <summary>
        /// Update a User Profile based on XProfileUpdateRequest Full
        /// </summary>
        /// <param name="model">user update info, an instance of <see>XProfileUpdateRequest</see></param>
        /// <param name="userSelectByParam">determine's which user profile must be retrieved</param>
        /// <returns>an instance of <see>XUserProfileDto</see></returns>
        [RequireXPowered]
        [Authorize(Policy = LocalApi.PolicyName)]
        [HttpPost("Profile/{userSelectByParam?}")]
        [Authorize(Policy = XPolicies.EnabledAdminOrAgent)]
        public async Task<ActionResult<XUserProfileDto>> FullUpdateProfile(
            [FromBody] XProfileUpdateRequest model, [FromRoute] string userSelectByParam = null
        )
        {
            //
            // Do Action ...
            try
            {
                //
                if (userSelectByParam.IsNullOrEmpty())
                {
                    userSelectByParam = User.Identity.Name;
                }

                //
                var result = await IdentityManager.FullProfileUpdateAsync(
                    userSelectByParam,
                    User.Identity.Name,
                    model
                );

                //
                // Return Result
                return Ok(result
                    .ToDynamicObject());
            }
            catch (Exception ex)
            {
                //
                var result = GetExceptionActionResult(ex);
                return result;
            }
        }
        #endregion

        //
        #region Avatar Actions ...
        /// <summary>
        /// Add a New Profile Image
        /// </summary>
        /// <param name="file">an specific File to upload, <see>IFormFile</see></param>
        /// <returns>an instance of <see>XUserProfileDto</see></returns>
        [RequireXPowered]
        [HttpPost("Profile/Avatar")]
        [RequestSizeLimit(966_367_641)]
        [Authorize(Policy = XPolicies.User)]
        [Authorize(Policy = LocalApi.PolicyName)]
        [Authorize(Policy = XPolicies.EnabledUser)]
        public async Task<ActionResult<XUserProfileDto>> AddAvatar(
            [FromForm] IFormFile file
        )
        {
            //
            // Do Action ...
            try
            {
                //
                // Validate Args ...
                ValidationProvider.NotNull(file);

                //
                // Get Request ...
                var result = await IdentityManager
                    .AddAvatar(
                        User.Identity.Name,
                        file
                    );

                //
                return Ok(result
                    .ToDynamicObject());
            }
            catch (Exception ex)
            {
                //
                var exResult = GetExceptionActionResult(ex);
                return exResult;
            }
        }

        /// <summary>
        /// Add a New Collection of Profile Images
        /// </summary>
        /// <param name="files">a collection of Files to upload, <see>IFormFileCollection</see></param>
        /// <returns>an instance of <see>XUserProfileDto</see></returns>
        [RequireXPowered]
        [HttpPost("Profile/Avatars")]
        [RequestSizeLimit(966_367_641)]
        [Authorize(Policy = XPolicies.User)]
        [Authorize(Policy = LocalApi.PolicyName)]
        [Authorize(Policy = XPolicies.EnabledUser)]
        public async Task<ActionResult<XUserProfileDto>> AddAvatars(
            [FromForm] IFormFileCollection files
        )
        {
            //
            // Do Action ...
            try
            {
                //
                // Validate Args ...
                ValidationProvider.NotZeroChilds(files);

                //
                // Get Request ...
                var result = await IdentityManager.AddAvatars(
                    User.Identity.Name,
                    files
                );

                //
                return Ok(result
                    .ToDynamicObject());
            }
            catch (Exception ex)
            {
                //
                var exResult = GetExceptionActionResult(ex);
                return exResult;
            }
        }

        /// <summary>
        /// Remove Profile Images
        /// </summary>
        /// <param name="ids">a comma seperated list of avatarIds to remove</param>
        /// <returns>an instance of <see>XUserProfileDto</see></returns>
        [RequireXPowered]
        [Authorize(Policy = XPolicies.User)]
        [HttpDelete("Profile/Avatars/{ids}")]
        [Authorize(Policy = LocalApi.PolicyName)]
        [Authorize(Policy = XPolicies.EnabledUser)]
        public async Task<ActionResult<XUserProfileDto>> RemoveAvatars(
            [FromRoute] string ids
        )
        {
            //
            // Do Action ...
            try
            {
                //
                ValidationProvider.NotEmpty(ids);
                var idList = ids.Split(",");
                var idCollection = new Collection<int>();

                //
                foreach (var s in idList)
                {
                    idCollection.Add(int.Parse(s));
                }

                //
                // Get Request ...
                var result = await IdentityManager
                    .RemoveAvatar(
                        User.Identity.Name,
                        idCollection.ToArray()
                    );

                //
                return Ok(result
                    .ToDynamicObject());
            }
            catch (Exception ex)
            {
                //
                var result = GetExceptionActionResult(ex);
                return result;
            }
        }

        /// <summary>
        /// set Specified Profile Image as Avatar
        /// </summary>
        /// <param name="id">an integer which reperesent AvatarId to set as current Avatar</param>
        /// <returns>an instance of <see>XUserProfileDto</see></returns>
        [RequireXPowered]
        [HttpPost("Profile/Avatars/{id:int}/Set")]
        [Authorize(Policy = XPolicies.User)]
        [Authorize(Policy = LocalApi.PolicyName)]
        [Authorize(Policy = XPolicies.EnabledUser)]
        public async Task<ActionResult<XUserProfileDto>> SetAvatar(
            [FromRoute] int id
        )
        {
            //
            // Do Action ...
            try
            {
                //
                var result = await IdentityManager
                    .SetAvatar(
                        User.Identity.Name,
                        id
                    );

                //
                return Ok(result
                    .ToDynamicObject());
            }
            catch (Exception ex)
            {
                //
                var exception = GetExceptionActionResult(ex);
                return exception;
            }
        }
        #endregion
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\xIds\Controllers\Account\AccountController+Query.cs

using System;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using xCommons.Attributes;
using xCommons.Extensions;
using xIdentityHelper;
using xModels.Dtos;
using static IdentityServer4.IdentityServerConstants;

namespace xIds.Controllers
{
    public partial class AccountController
    {
        /// <summary>
        /// Query Users 
        /// for specifiy users role for query user 'role: string' and 'forceRole: boolean' in header
        /// </summary>
        /// <param name="query">how to filter results based on <see>XQuery</see> structure</param>
        /// <param name="role">an string which represent user role</param>
        /// <param name="forceRole">if it's true the user must has exact role, otherwise top level users also listed</param>
        /// <returns>an instance of <see>XQueryResult</see> of <see>XUserProfileDto</see></returns>
        [RequireXPowered]
        [HttpGet("Users/Query")]
        [Authorize(Policy = LocalApi.PolicyName)]
        [Authorize(Policy = XPolicies.EnabledUser)]
        public async Task<ActionResult<XQueryResult<string>>> QueryUsers(
            [FromQuery] XQuery query,
            [FromHeader] string role,
            [FromHeader] bool forceRole = false
        )
        {
            //
            // Do Actions ...
            try
            {
                //
                // Retrieve User Info ...
                var userInfo = await GetUserInfo();

                //
                // Retrieve Result Based on Provided Query ...
                var result = await IdentityManager.QueryUsers(
                    role: role,
                    query: query,
                    forceRole: forceRole,
                    requestedUserSelectByParam: userInfo.UserId
                );

                //
                // Return result ...
                return Ok(result
                    .ToDynamicObject());
            }
            catch (Exception ex)
            {
                //
                var exception = GetExceptionActionResult(ex);
                return exception;
            }
        }
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\xIds\Controllers\Account\AccountController+Registration.cs

using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using xIdentityHelper;
using xCommons.Attributes;
using xCommons.Extensions;
using xExceptions.Constants;
using xIdentityModels.Constants;
using xIdentityModels.Models;
using static IdentityServer4.IdentityServerConstants;

namespace xIds.Controllers
{
    public partial class AccountController
    {
        //
        #region CanRegister ...
        /// <summary>
        /// Check a UserName is Available For Registration or not
        /// </summary>
        /// <param name="userName">an string value which represent desired username</param>
        /// <returns>a boolean value</returns>
        [AllowAnonymous]
        [RequireXPowered]
        [HttpGet("CanRegisterUserName/{userName?}")]
        public async Task<ActionResult<bool>> CanRegisterUserName(
            [FromRoute] string userName
        )
        {
            //
            // Validate Args ...
            if (userName.IsNullOrEmpty())
            {
                return BadRequest(
                    XException.InvalidArgs
                    .ToXError()
                );
            }

            //
            // Do Action ...
            try
            {
                //
                var result = await IdentityManager
                    .CanRegister(userName);

                //
                // Return Result
                return Ok(result);
            }
            catch (Exception ex)
            {
                //
                var result = GetExceptionActionResult(ex);

                //
                return result;
            }
        }

        /// <summary>
        /// Check a Mobile Number is Available For Registration or not
        /// </summary>
        /// <param name="mobileNumber">an string value which represent desired mobile number</param>
        /// <returns>a boolean value</returns>
        [AllowAnonymous]
        [RequireXPowered]
        [HttpGet("CanRegisterMobileNumber/{mobileNumber?}")]
        public async Task<ActionResult<bool>> CanRegisterMobileNumber(
            [FromRoute] string mobileNumber
        )
        {
            //
            // Validate Args ...
            if (mobileNumber.IsNullOrEmpty())
            {
                return BadRequest(
                    XException.InvalidArgs
                    .ToXError()
                );
            }
            if (!mobileNumber.IsValidMobileNumber())
            {
                return BadRequest(
                    XException.InvalidMobileNumber
                    .ToXError()
                );
            }

            //
            // Do Action ...
            try
            {
                //
                var result = await IdentityManager
                    .CanRegister(mobileNumber);

                //
                // Return Result
                return Ok(result);
            }
            catch (Exception ex)
            {
                //
                var result = GetExceptionActionResult(ex);

                //
                return result;
            }
        }

        /// <summary>
        /// Check a Email Address is Available For Registration or not
        /// </summary>
        /// <param name="email">an string value which represent desired email address</param>
        /// <returns>a boolean value</returns>
        [AllowAnonymous]
        [RequireXPowered]
        [HttpGet("CanRegisterEmail/{email?}")]
        public async Task<ActionResult<bool>> CanRegisterEmail(
            [FromRoute] string email
        )
        {
            //
            // Validate Args ...
            if (email.IsNullOrEmpty())
            {
                return BadRequest(
                    XException.InvalidArgs
                    .ToXError()
                );
            }
            if (!email.IsValidEmail())
            {
                return BadRequest(
                    XException.InvalidEmailAddress
                    .ToXError()
                );
            }

            //
            // Do Action ...
            try
            {
                //
                var result = await IdentityManager
                    .CanRegister(email);

                //
                // Return Result
                return Ok(result);
            }
            catch (Exception ex)
            {
                //
                var result = GetExceptionActionResult(ex);

                //
                return result;
            }
        }
        #endregion

        //
        #region Confirmations ...
        /// <summary>
        /// Check User is Confirmed Email or not
        /// </summary>
        /// <returns>a boolean value</returns>
        [RequireXPowered]
        [HttpGet("IsConfirmedEmail")]
        [Authorize(Policy = XPolicies.User)]
        [Authorize(Policy = LocalApi.PolicyName)]
        public async Task<ActionResult<bool>> IsConfirmedEmail()
        {
            //
            // Do Action ...
            try
            {
                //
                var result = await IdentityManager
                    .IsConfirmedEmail(User.Identity.Name);

                //
                // Return Result
                return Ok(result);
            }
            catch (Exception ex)
            {
                //
                var result = GetExceptionActionResult(ex);

                //
                return result;
            }
        }

        /// <summary>
        /// Check User is Confirmed Mobile or not
        /// </summary>
        /// <returns>a boolean value</returns>
        [RequireXPowered]
        [HttpGet("IsConfirmedMobile")]
        [Authorize(Policy = XPolicies.User)]
        [Authorize(Policy = LocalApi.PolicyName)]
        public async Task<ActionResult<bool>> IsConfirmedMobile()
        {
            //
            // Do Action ...
            try
            {
                //
                var result = await IdentityManager
                    .IsConfirmedMobile(User.Identity.Name);

                //
                // Return Result
                return Ok(result);
            }
            catch (Exception ex)
            {
                //
                var result = GetExceptionActionResult(ex);

                //
                return result;
            }
        }

        /// <summary>
        /// Confirm Registration
        /// </summary>
        /// <remarks>
        ///     for this action you have to provide:
        ///         - Lang: client device currently used locale, such as: en-US.
        ///         - ActionToken: user's requested action token for this action.
        ///         - Device: user's client device which is an instance of XDevice.
        ///         - ReturnUrl: client application Login URL.
        /// 
        /// Sample request:
        /// 
        ///     {
        ///         "lang": "fa-IR",
        ///         "actionToken": ""
        ///         "returnUrl": "http://localhost/login",
        ///         "device": {
        ///             "os":"Mac",
        ///             "browser":"Chrome",
        ///             "osVersion":"mac-os-x-15",
        ///             "userAgent":"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_3) AppleWebKit/537.36 (KHTML, like Gecko) x-framework-test/0.0.0 Chrome/87.0.4280.141 Electron/11.2.0 Safari/537.36",
        ///             "deviceType":3,
        ///             "identifier":"[Mac]-[mac-os-x-15]-[3]-[Chrome]-[Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_3) AppleWebKit/537.36 (KHTML, like Gecko) x-framework-test/0.0.0 Chrome/87.0.4280.141 Electron/11.2.0 Safari/537.36]",
        ///             "token":"96f400dd9aa5c57a8cec9d6f4775bad3"
        ///         }
        ///     }
        /// 
        /// </remarks>
        /// <param name="model">an instance of <see>XActionRequest</see> class which provider requirement for action</param>
        /// <returns></returns>
        [AllowAnonymous]
        [RequireXPowered]
        [HttpPost("ConfirmRegistration")]
        public async Task<ActionResult> ConfirmRegistration(
            [FromBody] XActionRequest model
        )
        {
            //
            // Do Action ...
            try
            {
                //
                // Validate Args ...
                if (!ModelState.IsValid)
                {
                    XException.InvalidArgs.Throw();
                }
                await ValidationProvider
                    .GroupValidationBuilder()
                    .AddNotEmpty(
                        model.Lang,
                        model.ActionToken,
                        model.ReturnUrl
                    )
                    .AddNotNull(model.Device)
                    .ValidateGroupAsync();

                //
                // Get Request ...
                await IdentityManager
                    .ConfirmRegistration(
                        model.Lang,
                        model.Device,
                        model.ActionToken,
                        model.ReturnUrl
                    );

                //
                return Ok();
            }
            catch (Exception ex)
            {
                //
                var exResult = GetExceptionActionResult(ex);
                return exResult;
            }
        }

        /// <summary>
        /// Confirm Requested Mobile Number
        /// </summary>
        /// <remarks>
        ///     for this action you have to provide:
        ///         - Lang: client device currently used locale, such as: en-US. 
        ///         - ActionToken: user's requested action token for this action. 
        ///         - Device: user's client device which is an instance of XDevice. 
        ///         - MobileVerificationCode: a verification code which produced due Request Action.
        /// 
        /// Sample request:
        /// 
        ///     {
        ///         "lang": "fa-IR",
        ///         "actionToken": ""
        ///         "mobileVerificationCode": "",
        ///         "device": {
        ///             "os":"Mac",
        ///             "browser":"Chrome",
        ///             "osVersion":"mac-os-x-15",
        ///             "userAgent":"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_3) AppleWebKit/537.36 (KHTML, like Gecko) x-framework-test/0.0.0 Chrome/87.0.4280.141 Electron/11.2.0 Safari/537.36",
        ///             "deviceType":3,
        ///             "identifier":"[Mac]-[mac-os-x-15]-[3]-[Chrome]-[Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_3) AppleWebKit/537.36 (KHTML, like Gecko) x-framework-test/0.0.0 Chrome/87.0.4280.141 Electron/11.2.0 Safari/537.36]",
        ///             "token":"96f400dd9aa5c57a8cec9d6f4775bad3"
        ///         }
        ///     }
        /// 
        /// </remarks>
        /// <param name="model">an instance of <see>XActionRequest</see> class which provider requirement for action</param>
        /// <returns>an instance of <see>XActionResponse</see></returns>
        [AllowAnonymous]
        [RequireXPowered]
        [HttpPost("ConfirmMobileNumber")]
        public async Task<ActionResult<XActionResponse>> ConfirmMobileNumber(
            [FromBody] XActionRequest model
        )
        {
            //
            // Do Action ...
            try
            {
                //
                // Validate Args ...
                if (!ModelState.IsValid)
                {
                    XException.InvalidArgs.Throw();
                }
                await ValidationProvider
                    .GroupValidationBuilder()
                    .AddNotEmpty(
                        model.Lang,
                        model.ActionToken,
                        model.MobileVerificationCode
                    )
                    .AddNotNull(model.Device)
                    .ValidateGroupAsync();

                //
                // Get Request ...
                var result = await IdentityManager
                    .ConfirmMobileNumber(
                        model.Lang,
                        model.Device,
                        model.ActionToken,
                        model.MobileVerificationCode
                    );

                //
                return Ok(result
                    .ToDynamicObject());
            }
            catch (Exception ex)
            {
                //
                var exResult = GetExceptionActionResult(ex);
                return exResult;
            }
        }

        /// <summary>
        /// Confirm Requested Email Address
        /// </summary>
        /// <remarks>
        ///     for this action you have to provide: 
        ///         - Lang: client device currently used locale, such as: en-US. 
        ///         - ActionToken: user's requested action token for this action. 
        ///         - Device: user's client device which is an instance of XDevice. 
        ///         - EmailVerificationCode: a verification code which produced due Request Action.
        /// 
        /// Sample request:
        /// 
        ///     {
        ///         "lang": "fa-IR",
        ///         "actionToken": ""
        ///         "emailVerificationCode": "",
        ///         "device": {
        ///             "os":"Mac",
        ///             "browser":"Chrome",
        ///             "osVersion":"mac-os-x-15",
        ///             "userAgent":"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_3) AppleWebKit/537.36 (KHTML, like Gecko) x-framework-test/0.0.0 Chrome/87.0.4280.141 Electron/11.2.0 Safari/537.36",
        ///             "deviceType":3,
        ///             "identifier":"[Mac]-[mac-os-x-15]-[3]-[Chrome]-[Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_3) AppleWebKit/537.36 (KHTML, like Gecko) x-framework-test/0.0.0 Chrome/87.0.4280.141 Electron/11.2.0 Safari/537.36]",
        ///             "token":"96f400dd9aa5c57a8cec9d6f4775bad3"
        ///         }
        ///     }
        /// 
        /// </remarks>
        /// <param name="model">an instance of <see>XActionRequest</see> class which provider requirement for action</param>
        /// <returns>an instance of <see>XActionResponse</see></returns>
        [AllowAnonymous]
        [RequireXPowered]
        [HttpPost("ConfirmEmailAddress")]
        public async Task<ActionResult<XActionResponse>> ConfirmEmailAddress(
            [FromBody] XActionRequest model
        )
        {
            //
            // Do Action ...
            try
            {
                //
                // Validate Args ...
                if (!ModelState.IsValid)
                {
                    XException.InvalidArgs.Throw();
                }
                await ValidationProvider
                    .GroupValidationBuilder()
                    .AddNotEmpty(
                        model.Lang,
                        model.ActionToken,
                        model.EmailVerificationCode
                    )
                    .AddNotNull(model.Device)
                    .ValidateGroupAsync();

                //
                // Get Request ...
                var result = await IdentityManager
                    .ConfirmEmailAddress(
                        model.Lang,
                        model.Device,
                        model.ActionToken,
                        model.EmailVerificationCode
                    );

                //
                return Ok(result
                    .ToDynamicObject());
            }
            catch (Exception ex)
            {
                //
                var exResult = GetExceptionActionResult(ex);
                return exResult;
            }
        }
        #endregion

        //
        #region Request for Actions ...
        /// <summary>
        /// Request For Mobile Number Change/Confirm 
        /// </summary>
        /// <remarks>
        ///     for this action you have to provide: 
        ///         - Lang: client device currently used locale, such as: en-US.
        ///         - Password: user's current active password.
        ///         - MobileNumber: which phone number is going to confirm.
        ///         - Device: user's client device which is an instance of XDevice.
        /// 
        /// Sample request:
        /// 
        ///     {
        ///         "lang": "fa-IR",
        ///         "password": "",
        ///         "mobileNumber": "",
        ///         "device": {
        ///             "os":"Mac",
        ///             "browser":"Chrome",
        ///             "osVersion":"mac-os-x-15",
        ///             "userAgent":"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_3) AppleWebKit/537.36 (KHTML, like Gecko) x-framework-test/0.0.0 Chrome/87.0.4280.141 Electron/11.2.0 Safari/537.36",
        ///             "deviceType":3,
        ///             "identifier":"[Mac]-[mac-os-x-15]-[3]-[Chrome]-[Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_3) AppleWebKit/537.36 (KHTML, like Gecko) x-framework-test/0.0.0 Chrome/87.0.4280.141 Electron/11.2.0 Safari/537.36]",
        ///             "token":"96f400dd9aa5c57a8cec9d6f4775bad3"
        ///         }
        ///     }
        /// 
        /// </remarks>
        /// <param name="model">an instance of <see>XActionRequest</see> class which provider requirement for action</param>
        /// <returns>an instance of <see>XActionResponse</see></returns>
        [AllowAnonymous]
        [RequireXPowered]
        [HttpPost("RequestConfirmMobile")]
        public async Task<ActionResult<XActionResponse>> RequestConfirmMobile(
            [FromBody] XActionRequest model
        )
        {
            //
            // Do Action ...
            try
            {
                //
                // Validate Args ...
                if (!ModelState.IsValid)
                {
                    XException.InvalidArgs.Throw();
                }
                await ValidationProvider
                    .GroupValidationBuilder()
                    .AddNotEmpty(
                        model.Lang,
                        model.Password,
                        model.MobileNumber
                    )
                    .AddNotNull(model.Device)
                    .AddMobileNumber(model.MobileNumber)
                    .ValidateGroupAsync();

                //
                // Get UserSelect By Param ...
                var userSelectByParam = GetUserSelectByParam(
                    model,
                    excludes: new List<XUserSelectBy> {
                        XUserSelectBy.Email,
                        XUserSelectBy.MobileNumber
                    });

                //
                // Get Request ...
                var result = await IdentityManager
                    .RequestConfirmMobile(
                        model.Lang,
                        model.Device,
                        userSelectByParam,
                        model.Password,
                        model.MobileNumber
                    );

                //
                return Ok(result
                    .ToDynamicObject());
            }
            catch (Exception ex)
            {
                //
                var exResult = GetExceptionActionResult(ex);
                return exResult;
            }
        }

        /// <summary>
        /// Request For Email Address Change/Confirm
        /// </summary>
        /// <remarks>
        ///     for this action you have to provide:
        ///         - Lang: client device currently used locale, such as: en-US.
        ///         - Password: user's current active password.
        ///         - Email: which email address is going to confirm.
        ///         - Device: user's client device which is an instance of XDevice.
        /// 
        /// Sample request:
        /// 
        ///     {
        ///         "lang": "fa-IR",
        ///         "password": "",
        ///         "email": "",
        ///         "device": {
        ///             "os":"Mac",
        ///             "browser":"Chrome",
        ///             "osVersion":"mac-os-x-15",
        ///             "userAgent":"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_3) AppleWebKit/537.36 (KHTML, like Gecko) x-framework-test/0.0.0 Chrome/87.0.4280.141 Electron/11.2.0 Safari/537.36",
        ///             "deviceType":3,
        ///             "identifier":"[Mac]-[mac-os-x-15]-[3]-[Chrome]-[Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_3) AppleWebKit/537.36 (KHTML, like Gecko) x-framework-test/0.0.0 Chrome/87.0.4280.141 Electron/11.2.0 Safari/537.36]",
        ///             "token":"96f400dd9aa5c57a8cec9d6f4775bad3"
        ///         }
        ///     }
        /// 
        /// </remarks>
        /// <param name="model">an instance of <see>XActionRequest</see> class which provider requirement for action</param>
        /// <returns>an instance of <see>XActionResponse</see></returns>
        [AllowAnonymous]
        [RequireXPowered]
        [HttpPost("RequestConfirmEmail")]
        public async Task<ActionResult<XActionResponse>> RequestConfirmEmail(
            [FromBody] XActionRequest model
        )
        {
            //
            // Do Action ...
            try
            {
                //
                // Validate Args ...
                if (!ModelState.IsValid)
                {
                    XException.InvalidArgs.Throw();
                }
                await ValidationProvider
                    .GroupValidationBuilder()
                    .AddNotEmpty(
                        model.Lang,
                        model.Email,
                        model.Password)
                    .AddNotNull(model.Device)
                    .AddEmailAddress(model.Email)
                    .ValidateGroupAsync();

                //
                // Get UserSelect By Param ...
                var userSelectByParam = GetUserSelectByParam(
                    model,
                    excludes: new List<XUserSelectBy> {
                        XUserSelectBy.Email,
                        XUserSelectBy.MobileNumber
                    });

                //
                // Get Request ...
                var result = await IdentityManager
                    .RequestConfirmEmail(
                        model.Lang,
                        model.Device,
                        userSelectByParam,
                        model.Password,
                        model.Email
                    );

                //
                return Ok(result
                    .ToDynamicObject());
            }
            catch (Exception ex)
            {
                //
                var exResult = GetExceptionActionResult(ex);
                return exResult;
            }
        }

        /// <summary>
        /// Request Reset Password Action
        /// </summary>
        /// <remarks>
        ///     for this action you have to provide:
        ///         - Lang: client device currently used locale, such as: en-US.
        ///         - Device: user's client device which is an instance of XDevice.
        ///         - ReturnUrl: client application ResetPassword URL.
        /// 
        /// Sample request:
        /// 
        ///     {
        ///         "lang": "fa-IR",
        ///         "returnUrl": "http://localhost/reset-password",
        ///         "device": {
        ///             "os":"Mac",
        ///             "browser":"Chrome",
        ///             "osVersion":"mac-os-x-15",
        ///             "userAgent":"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_3) AppleWebKit/537.36 (KHTML, like Gecko) x-framework-test/0.0.0 Chrome/87.0.4280.141 Electron/11.2.0 Safari/537.36",
        ///             "deviceType":3,
        ///             "identifier":"[Mac]-[mac-os-x-15]-[3]-[Chrome]-[Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_3) AppleWebKit/537.36 (KHTML, like Gecko) x-framework-test/0.0.0 Chrome/87.0.4280.141 Electron/11.2.0 Safari/537.36]",
        ///             "token":"96f400dd9aa5c57a8cec9d6f4775bad3"
        ///         }
        ///     }
        /// 
        /// </remarks>
        /// <param name="model">an instance of <see>XActionRequest</see> class which provider requirement for action</param>
        /// <returns>an instance of <see>XActionResponse</see></returns>
        [AllowAnonymous]
        [RequireXPowered]
        [HttpPost("RequestResetPassword")]
        public async Task<ActionResult<XActionResponse>> RequestResetPassword(
            [FromBody] XActionRequest model
        )
        {
            //
            // Do Action ...
            try
            {
                //
                // Validate Args ...
                if (!ModelState.IsValid)
                {
                    XException.InvalidArgs.Throw();
                }
                await ValidationProvider
                    .GroupValidationBuilder()
                    .AddNotEmpty(
                        model.Lang,
                        model.ReturnUrl)
                    .AddNotNull(model.Device)
                    .AddUrl(model.ReturnUrl)
                    .ValidateGroupAsync();

                //
                // Get UserSelect By Param ...
                var userSelectByParam = GetUserSelectByParam(model);

                //
                // Get Request ...
                var result = await IdentityManager
                    .RequestResetPassword(
                        model.Lang,
                        model.Device,
                        userSelectByParam,
                        model.ReturnUrl
                    );

                //
                return Ok(result
                    .ToDynamicObject());
            }
            catch (Exception ex)
            {
                //
                var exResult = GetExceptionActionResult(ex);
                return exResult;
            }
        }

        /// <summary>
        /// Reset a User's Password
        /// </summary>
        /// <remarks>
        ///     for this action you have to provide:
        ///         - Lang: client device currently used locale, such as: en-US.
        ///         - ActionToken: user's requested action token for this action.
        ///         - NewPassword: user's new password to change.
        ///         - Device: user's client device which is an instance of XDevice.
        ///         - ReturnUrl: client application Login URL.
        /// 
        /// Sample request:
        /// 
        ///     {
        ///         "lang": "fa-IR",
        ///         "actionToken": "",
        ///         "newPassword": "",
        ///         "returnUrl": "http://localhost/login",
        ///         "device": {
        ///             "os":"Mac",
        ///             "browser":"Chrome",
        ///             "osVersion":"mac-os-x-15",
        ///             "userAgent":"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_3) AppleWebKit/537.36 (KHTML, like Gecko) x-framework-test/0.0.0 Chrome/87.0.4280.141 Electron/11.2.0 Safari/537.36",
        ///             "deviceType":3,
        ///             "identifier":"[Mac]-[mac-os-x-15]-[3]-[Chrome]-[Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_3) AppleWebKit/537.36 (KHTML, like Gecko) x-framework-test/0.0.0 Chrome/87.0.4280.141 Electron/11.2.0 Safari/537.36]",
        ///             "token":"96f400dd9aa5c57a8cec9d6f4775bad3"
        ///         }
        ///     }
        /// 
        /// </remarks>
        /// <param name="model">an instance of <see>XActionRequest</see> class which provider requirement for action</param>
        /// <returns></returns>
        [AllowAnonymous]
        [RequireXPowered]
        [HttpPost("ResetPassword")]
        public async Task<ActionResult> ResetPassword(
            [FromBody] XActionRequest model
        )
        {
            //
            // Do Action ...
            try
            {
                //
                // Validate Args ...
                if (!ModelState.IsValid)
                {
                    XException.InvalidArgs.Throw();
                }
                await ValidationProvider
                    .GroupValidationBuilder()
                    .AddNotEmpty(
                        model.Lang,
                        model.ActionToken,
                        model.NewPassword,
                        model.ReturnUrl)
                    .AddNotNull(model.Device)
                    .ValidateGroupAsync();

                //
                // Get Request ...
                await IdentityManager
                    .ResetPassword(
                        model.Lang,
                        model.Device,
                        model.ActionToken,
                        model.NewPassword,
                        model.ReturnUrl
                    );

                //
                return Ok();
            }
            catch (Exception ex)
            {
                //
                var exResult = GetExceptionActionResult(ex);
                return exResult;
            }
        }

        /// <summary>
        /// Request Registration Confirm
        /// </summary>
        /// <remarks>
        ///     for this action you have to provide:
        ///         - a UserSelectedBy identifier which represet User.
        ///         - Lang: client device currently used locale, such as: en-US.
        ///         - Password: user's current active password.
        ///         - Device: user's client device which is an instance of XDevice.
        ///         - ReturnUrl: client application Confirm Registration URL.
        /// 
        /// Sample request:
        /// 
        ///     {
        ///         "lang": "fa-IR",
        ///         "userId": ""
        ///         "password": "",
        ///         "returnUrl": "http://localhost/confirm",
        ///         "device": {
        ///             "os":"Mac",
        ///             "browser":"Chrome",
        ///             "osVersion":"mac-os-x-15",
        ///             "userAgent":"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_3) AppleWebKit/537.36 (KHTML, like Gecko) x-framework-test/0.0.0 Chrome/87.0.4280.141 Electron/11.2.0 Safari/537.36",
        ///             "deviceType":3,
        ///             "identifier":"[Mac]-[mac-os-x-15]-[3]-[Chrome]-[Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_3) AppleWebKit/537.36 (KHTML, like Gecko) x-framework-test/0.0.0 Chrome/87.0.4280.141 Electron/11.2.0 Safari/537.36]",
        ///             "token":"96f400dd9aa5c57a8cec9d6f4775bad3"
        ///         }
        ///     }
        /// 
        /// </remarks>
        /// <param name="model">an instance of <see>XActionRequest</see> class which provider requirement for action</param>
        /// <returns></returns>
        [AllowAnonymous]
        [RequireXPowered]
        [HttpPost("RequestConfirmRegistration")]
        public async Task<ActionResult> RequestConfirmRegistration(
            [FromBody] XActionRequest model
        )
        {
            //
            // Do Action ...
            try
            {
                //
                // Validate Args ...
                if (!ModelState.IsValid)
                {
                    XException.InvalidArgs.Throw();
                }
                await ValidationProvider
                    .GroupValidationBuilder()
                    .AddNotEmpty(
                        model.Lang,
                        model.Password,
                        model.ReturnUrl)
                    .AddNotNull(model.Device)
                    .AddUrl(model.ReturnUrl)
                    .ValidateGroupAsync();

                //
                // Get UserSelect By Param ...
                var userSelectByParam = GetUserSelectByParam(model);

                //
                // Get Request ...
                await IdentityManager
                    .RequestConfirmRegistration(
                        model.Lang,
                        model.Device,
                        userSelectByParam,
                        model.Password,
                        model.ReturnUrl
                    );

                //
                return Ok();
            }
            catch (Exception ex)
            {
                //
                var exResult = GetExceptionActionResult(ex);
                return exResult;
            }
        }
        #endregion

        //
        #region Registration ...
        /// <summary>
        /// Invite a User to Register on Dashboard
        /// </summary>
        /// <remarks>
        ///     for this action you have to provide: 
        ///         - Lang: client device currently used locale, such as: en-US.
        ///         - Email: which email address is going to invite.
        ///         - Device: user's client device which is an instance of XDevice.
        ///         - ReturnUrl: client application Registration URL.
        ///     notice in this step you had to provide all this informations as FormData
        /// 
        /// Sample request:
        /// 
        ///     {
        ///         "lang": "fa-IR",
        ///         "email": "",
        ///         "returnUrl": "",
        ///         "device": {
        ///             "os":"Mac",
        ///             "browser":"Chrome",
        ///             "osVersion":"mac-os-x-15",
        ///             "userAgent":"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_3) AppleWebKit/537.36 (KHTML, like Gecko) x-framework-test/0.0.0 Chrome/87.0.4280.141 Electron/11.2.0 Safari/537.36",
        ///             "deviceType":3,
        ///             "identifier":"[Mac]-[mac-os-x-15]-[3]-[Chrome]-[Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_3) AppleWebKit/537.36 (KHTML, like Gecko) x-framework-test/0.0.0 Chrome/87.0.4280.141 Electron/11.2.0 Safari/537.36]",
        ///             "token":"96f400dd9aa5c57a8cec9d6f4775bad3"
        ///         }
        ///     }
        /// 
        /// </remarks>
        /// <param name="model">an instance of <see>XActionRequest</see> class which provider requirement for action</param>
        /// <returns>an instance of <see>XActionResponse</see></returns>
        [RequireXPowered]
        [HttpPost("InviteUser")]
        [Authorize(Policy = LocalApi.PolicyName)]
        [Authorize(Policy = XPolicies.EnabledAdmin)]
        [Authorize(Policy = XPolicies.EnabledAgent)]
        public async Task<ActionResult<XActionResponse>> InviteUser(
            [FromBody] XActionRequest model
        )
        {
            //
            // Do Action ...
            try
            {
                //
                // Validate Args ...
                if (!ModelState.IsValid)
                {
                    XException.InvalidArgs.Throw();
                }

                //
                await ValidationProvider
                    .GroupValidationBuilder()
                    .AddNotEmpty(
                        model.Lang,
                        model.Email,
                        model.ReturnUrl)
                    .AddEmailAddress(model.Email)
                    .AddNotNull(model.Device)
                    .ValidateGroupAsync();

                //
                var result = await IdentityManager
                    .InviteUser(
                        model.Lang,
                        model.Device,
                        model.Email,
                        model.ReturnUrl);

                //
                return Ok(result
                    .ToDynamicObject());
            }
            catch (Exception ex)
            {
                //
                var result = GetExceptionActionResult(ex);
                return result;
            }
        }

        /// <summary>
        /// Recieve some Basic Informations and Start Registration Proccess
        /// if they Valid 
        /// 
        /// Registration Proccess Starts with Invoking this Action
        /// </summary>
        /// <remarks>
        ///     for this action you have to provide: 
        ///         - Lang: client device currently used locale, such as: en-US.
        ///         - FirstName: user's FirstName.
        ///         - LastName: user's LastName.
        ///         - DateOfBirth: user's dob date.
        ///         - MobileNumber: user's MobileNumber optional.
        ///         - Email: user's Email optional.
        ///         - ActionToken: user's requested action token for this action (if user invited). 
        ///         - Device: user's client device which is an instance of XDevice.
        /// 
        /// Sample request:
        /// 
        ///     {
        ///         "lang": "fa-IR",
        ///         "firstName": "",
        ///         "lastName": "",
        ///         "dateOfBirth": "",
        ///         "email": "",
        ///         "mobileNumber": "",
        ///         "actionToken": "",
        ///         "device": {
        ///             "os":"Mac",
        ///             "browser":"Chrome",
        ///             "osVersion":"mac-os-x-15",
        ///             "userAgent":"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_3) AppleWebKit/537.36 (KHTML, like Gecko) x-framework-test/0.0.0 Chrome/87.0.4280.141 Electron/11.2.0 Safari/537.36",
        ///             "deviceType":3,
        ///             "identifier":"[Mac]-[mac-os-x-15]-[3]-[Chrome]-[Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_3) AppleWebKit/537.36 (KHTML, like Gecko) x-framework-test/0.0.0 Chrome/87.0.4280.141 Electron/11.2.0 Safari/537.36]",
        ///             "token":"96f400dd9aa5c57a8cec9d6f4775bad3"
        ///         }
        ///     }
        /// 
        /// </remarks>
        /// <param name="model">an instance of <see>XActionRequest</see> class which provider requirement for action</param>
        /// <returns>an instance of <see>XActionResponse</see></returns>
        [AllowAnonymous]
        [RequireXPowered]
        [HttpPost("RequestRegistration")]
        public async Task<ActionResult<XActionResponse>> RequestRegistration(
            [FromBody] XActionRequest model
        )
        {
            //
            // Do Action ...
            try
            {
                //
                // Validate Args ...
                if (!ModelState.IsValid)
                {
                    XException.InvalidArgs.Throw();
                }
                await ValidationProvider
                    .GroupValidationBuilder()
                    .AddNotEmpty(
                        model.Lang,
                        model.FirstName,
                        model.LastName)
                    .AddNotNull(
                        model.Device,
                        model.DateOfBirth)
                    .ValidateGroupAsync();

                //
                // Check Date Of Birth ...
                if (!model.DateOfBirth.HasValue)
                {
                    XException.InvalidArgs.Throw(); ;
                }

                //
                // Validate Mobile Number if Exists ...
                if (!model.MobileNumber.IsNullOrEmpty())
                {
                    ValidationProvider.MobileNumber(model.MobileNumber);
                }

                //
                // Validate Email Address if Exists ...
                if (!model.Email.IsNullOrEmpty())
                {
                    ValidationProvider.EmailAddress(model.Email);
                }

                //
                // Get Request ...
                var result = await IdentityManager
                    .RequestRegistration(
                        model.Lang,
                        model.Device,
                        model.ActionToken,
                        model.FirstName,
                        model.LastName,
                        model.DateOfBirth.GetValueOrDefault(),
                        model.MobileNumber,
                        model.Email
                    );

                //
                return Ok(result
                    .ToDynamicObject());
            }
            catch (Exception ex)
            {
                //
                var exResult = GetExceptionActionResult(ex);

                //
                return exResult;
            }
        }

        /// <summary>
        /// Add User Account Informations
        /// </summary>
        /// <remarks>
        ///     for this action you have to provide: 
        ///         - Lang: client device currently used locale, such as: en-US.
        ///         - ActionToken: user's requested action token for this action.
        ///         - UserName: user name.
        ///         - Password: assigne password.
        ///         - Device: user's client device which is an instance of XDevice.
        /// 
        /// Sample request:
        /// 
        ///     {
        ///         "lang": "fa-IR",
        ///         "userName": "",
        ///         "password": "",
        ///         "actionToken": "",
        ///         "device": {
        ///             "os":"Mac",
        ///             "browser":"Chrome",
        ///             "osVersion":"mac-os-x-15",
        ///             "userAgent":"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_3) AppleWebKit/537.36 (KHTML, like Gecko) x-framework-test/0.0.0 Chrome/87.0.4280.141 Electron/11.2.0 Safari/537.36",
        ///             "deviceType":3,
        ///             "identifier":"[Mac]-[mac-os-x-15]-[3]-[Chrome]-[Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_3) AppleWebKit/537.36 (KHTML, like Gecko) x-framework-test/0.0.0 Chrome/87.0.4280.141 Electron/11.2.0 Safari/537.36]",
        ///             "token":"96f400dd9aa5c57a8cec9d6f4775bad3"
        ///         }
        ///     }
        /// 
        /// </remarks>
        /// <param name="model">an instance of <see>XActionRequest</see> class which provider requirement for action</param>
        /// <returns>an instance of <see>XActionResponse</see></returns>
        [AllowAnonymous]
        [RequireXPowered]
        [HttpPost("AddAccountInfo")]
        public async Task<ActionResult<XActionResponse>> AddAccountInfo(
            [FromBody] XActionRequest model
        )
        {
            //
            // Do Action ...
            try
            {
                //
                // Validate Args ...
                if (!ModelState.IsValid)
                {
                    XException.InvalidArgs.Throw();
                }
                await ValidationProvider
                    .GroupValidationBuilder()
                    .AddNotEmpty(
                        model.Lang,
                        model.ActionToken,
                        model.UserName,
                        model.Password)
                    .AddNotNull(model.Device)
                    .ValidateGroupAsync();

                //
                // Get Request ...
                var result = await IdentityManager
                    .AddAcountInfo(
                        model.Lang,
                        model.Device,
                        model.ActionToken,
                        model.UserName,
                        model.Password);

                //
                return Ok(result
                    .ToDynamicObject());
            }
            catch (Exception ex)
            {
                //
                var exResult = GetExceptionActionResult(ex);
                return exResult;
            }
        }

        /// <summary>
        /// Upload and Attach a Profile Image for User. this is an Optional Step
        /// </summary>
        /// <param name="actionToken">user's requested action token</param>
        /// <param name="file">an instance of <see>IFormFile</see> for user's Avatar</param>
        /// <returns>an instance of <see>XActionResponse</see></returns>
        [AllowAnonymous]
        [RequireXPowered]
        [HttpPost("AttachProfileImage")]
        public async Task<ActionResult<XActionResponse>> AttachProfileImage(
            [FromForm] string actionToken, [FromForm] IFormFile file
        )
        {
            //
            // Do Action ...
            try
            {
                // 
                // Validate Args ...
                await ValidationProvider
                    .GroupValidationBuilder()
                    .AddNotEmpty(actionToken)
                    .AddNotNull(file)
                    .ValidateGroupAsync();

                //
                var result = await IdentityManager
                    .AttachProfileImage(actionToken, file);

                //
                return Ok(result
                    .ToDynamicObject());
            }
            catch (Exception ex)
            {
                //
                var exResult = GetExceptionActionResult(ex);
                return exResult;
            }
        }

        /// <summary>
        /// Finish Registrationn Proccess 
        /// </summary>
        /// <remarks>
        ///     for this action you have to provide: 
        ///         - a proper User Identifier such as: (UserId, UserName, Email or MobileNumber).
        ///         - Lang: client device currently used locale, such as: en-US.
        ///         - ActionToken: user's requested action token for this action.
        ///         - Password: assigne password.
        ///         - Device: user's client device which is an instance of XDevice.
        ///         - ReturnUrl: client application Login URL.
        /// 
        /// Sample request:
        /// 
        ///     {
        ///         "lang": "fa-IR",
        ///         "userName": "",
        ///         "password": "",
        ///         "returnUrl": "",
        ///         "device": {
        ///             "os":"Mac",
        ///             "browser":"Chrome",
        ///             "osVersion":"mac-os-x-15",
        ///             "userAgent":"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_3) AppleWebKit/537.36 (KHTML, like Gecko) x-framework-test/0.0.0 Chrome/87.0.4280.141 Electron/11.2.0 Safari/537.36",
        ///             "deviceType":3,
        ///             "identifier":"[Mac]-[mac-os-x-15]-[3]-[Chrome]-[Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_3) AppleWebKit/537.36 (KHTML, like Gecko) x-framework-test/0.0.0 Chrome/87.0.4280.141 Electron/11.2.0 Safari/537.36]",
        ///             "token":"96f400dd9aa5c57a8cec9d6f4775bad3"
        ///         }
        ///     }
        /// 
        /// </remarks>
        /// <param name="model">an instance of <see>XActionRequest</see> class which provider requirement for action</param>
        /// <returns></returns>
        [AllowAnonymous]
        [RequireXPowered]
        [HttpPost("FinishRegistration")]
        public async Task<ActionResult> FinishRegistration(
            [FromBody] XActionRequest model
        )
        {
            //
            // Do Action ...
            try
            {
                //
                // Validate Args ...
                if (!ModelState.IsValid)
                {
                    XException.InvalidArgs.Throw();
                }
                await ValidationProvider
                    .GroupValidationBuilder()
                    .AddNotEmpty(
                        model.Lang,
                        model.Password,
                        model.ReturnUrl)
                    .AddNotNull(model.Device)
                    .AddUrl(model.ReturnUrl)
                    .ValidateGroupAsync();

                //
                var userSelectByParam = IdentityManager
                    .GetUserSelectByParam(model);
                ValidationProvider
                    .NotEmpty(userSelectByParam);

                //
                // Get Request ...
                await IdentityManager
                    .FinishRegistration(
                        model.Lang,
                        model.Device,
                        userSelectByParam,
                        model.Password,
                        model.ReturnUrl
                    );

                //
                return Ok();
            }
            catch (Exception ex)
            {
                //
                var exResult = GetExceptionActionResult(ex);

                //
                return exResult;
            }
        }
        #endregion
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\xIds\Controllers\Account\AccountController+Search.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using xCommons.Attributes;
using xCommons.Extensions;
using xIdentityHelper;
using xIdentityModels.Dtos;
using xModels.Dtos;
using static IdentityServer4.IdentityServerConstants;

namespace xIds.Controllers
{
    /// <summary>
    /// Actions which related to Search and Suggest Users for 
    /// Friendship or Detecting ...
    /// </summary>
    public partial class AccountController
    {
        //
        #region Actions of Search ...
        /// <summary>
        /// Query Open To Search Users Profiles ... 
        /// Query all Users Which their Profiles is Open To Search ...
        /// </summary>
        /// <param name="query">how to filter results based on <see>XQuery</see> structure</param>
        /// <returns>an instance of <see>XQueryResult</see> of <see>XUserProfileDto</see></returns>
        [RequireXPowered]
        [HttpGet("OpenToSearch/Query")]
        [Authorize(Policy = LocalApi.PolicyName)]
        [Authorize(Policy = XPolicies.EnabledUser)]
        public async Task<ActionResult<XQueryResult<XUserProfileDto>>> QueryOpenToSearchProfiles(
            [FromQuery] XQuery query)
        {
            //
            // Do Action ...
            try
            {
                //
                var userId = User.Identity.Name;

                //
                var result = await IdentityManager.QueryOpenToSearchUsers(
                    userId,
                    query
                );

                return Ok(result
                    .ToDynamicObject());
            }
            catch (Exception ex)
            {
                //
                var exception = GetExceptionActionResult(ex);
                return exception;
            }
        }
        #endregion
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\xIds\Controllers\Account\AccountController+Test.cs

using System.Linq;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using xIdentityHelper;
using xCommons.Attributes;
using static IdentityServer4.IdentityServerConstants;

namespace xIds.Controllers
{
    public partial class AccountController
    {

        //
        #region Test Actions ...
        /// <summary>
        /// API Read Scope
        /// </summary>
        /// <returns>string message</returns>
        [RequireXPowered]
        [Authorize(LocalApi.PolicyName)]
        [HttpGet("Test/PassReadAccess")]
        [Authorize(Policy = XPolicies.ReadAccess)]
        public ActionResult<string> PassReadAccess()
        {
            return Ok("Read Access Passed ...");
        }

        /// <summary>
        /// API Write Scope
        /// </summary>
        /// <returns>string message</returns>
        [RequireXPowered]
        [Authorize(LocalApi.PolicyName)]
        [HttpGet("Test/PassWriteAccess")]
        [Authorize(Policy = XPolicies.WriteAccess)]
        public ActionResult<string> PassWriteAccess()
        {
            return Ok("Write Access Passed ...");
        }

        /// <summary>
        /// API Admin Scope
        /// </summary>
        /// <returns>string message</returns>
        [RequireXPowered]
        [Authorize(LocalApi.PolicyName)]
        [HttpGet("Test/PassAdminAccess")]
        [Authorize(Policy = XPolicies.AdminAccess)]
        public ActionResult<string> PassAdminAccess()
        {
            return Ok("Admin Access Passed ...");
        }

        /// <summary>
        /// API Manage Scop
        /// </summary>
        /// <returns>string message</returns>
        [RequireXPowered]
        [Authorize(LocalApi.PolicyName)]
        [HttpGet("Test/PassManageAccess")]
        [Authorize(Policy = XPolicies.ManageAccess)]
        public ActionResult<string> PassManageAccess()
        {
            return Ok("Manage Access Passed ...");
        }

        /// <summary>
        /// a simple Action which returns a List of Authenticated User Claims
        /// </summary>
        /// <returns>string message which represent current user's claims</returns>
        [RequireXPowered]
        [HttpGet("Test/HiClaims")]
        [Authorize(LocalApi.PolicyName)]
        [Authorize(Policy = XPolicies.User)]
        public ActionResult<string> HiClaims()
        {
            //
            var result = new
            {
                name = User.Identity.Name,
                claims = User.Claims.Select(c => new
                {
                    c.Type,
                    c.Value
                })
            };

            //
            return Ok(result);
        }

        /// <summary>
        /// a simple Hello User for Checking Authentication and Policy 
        /// </summary>
        /// <returns>string message which contains authenticated user name</returns>
        [RequireXPowered]
        [HttpGet("Test/HiUser")]
        [Authorize(LocalApi.PolicyName)]
        [Authorize(Policy = XPolicies.User)]
        public ActionResult<string> HiUser()
        {
            //
            var result = $"Hi User: {User.Identity.Name} ...";

            //
            return Ok(result);
        }

        /// <summary>
        /// a simple Hello User for Checking Authentication and Policy 
        /// </summary>
        /// <returns>string message which contains authenticated user name</returns>
        [RequireXPowered]
        [HttpGet("Test/HiEnabledUser")]
        [Authorize(LocalApi.PolicyName)]
        [Authorize(Policy = XPolicies.EnabledUser)]
        public ActionResult<string> HiEnabledUser()
        {
            //
            var result = $"Hi User: {User.Identity.Name} is Enabled ...";

            //
            return Ok(result);
        }

        /// <summary>
        /// a simple Hello User for Checking Authentication and Policy 
        /// </summary>
        /// <returns>string message which contains authenticated user name</returns>
        [RequireXPowered]
        [HttpGet("Test/HiAdmin")]
        [Authorize(LocalApi.PolicyName)]
        [Authorize(Policy = XPolicies.Admin)]
        public ActionResult<string> HiAdmin()
        {
            //
            var result = $"Hi Admin: {User.Identity.Name} ...";

            //
            return Ok(result);
        }

        /// <summary>
        /// a simple Hello User for Checking Authentication and Policy 
        /// </summary>
        /// <returns>string message which contains authenticated user name</returns>
        [RequireXPowered]
        [HttpGet("Test/HiEnabledAdmin")]
        [Authorize(LocalApi.PolicyName)]
        [Authorize(Policy = XPolicies.EnabledAdmin)]
        public ActionResult<string> HiEnabledAdmin()
        {
            //
            var result = $"Hi Admin: {User.Identity.Name} is Enabled ...";

            //
            return Ok(result);
        }
        #endregion        
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\xIds\Controllers\Base\XIBaseController.cs

using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Authentication;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Logging;
using xCommons.Configurations;
using xCommons.Constants;
using xCommons.Controllers;
using xCommons.Extensions;
using xCommons.Providers;
using xExceptions.Constants;
using xIdentityModels.Constants;
using xIdentityModels.Models;
using xIds.Interfaces;

namespace xIds.Controllers.Base
{
    public abstract class XIBaseController : XBaseController
    {
        public IXIdentityManager IdentityManager { get; }

        protected XIBaseController(
            ILogger logger,
            XAppConfiguration appConfiguration,
            IXIdentityManager identityManager,
            XValidationProvider validationProvider
        ) : base(
            logger,
            appConfiguration,
            validationProvider
        )
        {
            IdentityManager = identityManager;
        }

        //
        #region User Handlers NonActions ...
        /// <summary>
        /// Retrieve User Identifier Base on XActionRequest
        /// </summary>
        /// <param name="model"></param>
        /// <param name="forceNotNull"></param>
        /// <param name="excludes"></param>
        /// <returns></returns>
        [NonAction]
        public string GetUserSelectByParam(
            XActionRequest model,
            bool forceNotNull = true,
            ICollection<XUserSelectBy> excludes = null)
        {
            //
            // Validate Args ...
            ValidationProvider.NotNull(model);

            //
            var result = IdentityManager.GetUserSelectByParam(
                model,
                forceNotNull,
                excludes);

            //
            return result;
        }

        /// <summary>
        /// Retrieve Access Token
        /// </summary>
        /// <returns></returns>
        [NonAction]
        public async Task<string> GetAccessToken()
        {
            //
            var accessToken = Request.Headers[XAuthorization.Header].ToString();
            if (accessToken.IsNullOrEmpty())
            {
                accessToken = await HttpContext.GetTokenAsync(XAuthorization.AccessToken);
            }

            //
            if (accessToken
                .ToNormalString()
                .Contains(XAuthorization.TokenIdentifier.ToNormalString()))
            {
                accessToken = accessToken.Remove(0, XAuthorization.TokenIdentifier.Length);
            }

            //
            Logger.LogInformation($"Token: {accessToken}");
            return accessToken;
        }

        /// <summary>
        /// Retrieve Refresh Token
        /// </summary>
        /// <returns></returns>
        [NonAction]
        public async Task<string> GetRefreshToken()
        {
            //
            var refreshToken = Request.Headers[XAuthorization.RefreshToken].ToString();
            if (refreshToken.IsNullOrEmpty())
            {
                refreshToken = await HttpContext.GetTokenAsync(XAuthorization.RefreshToken);
            }

            //
            Logger.LogInformation($"Refresh Token: {refreshToken}");
            return refreshToken;
        }

        /// <summary>
        /// Retrieve Access Token Expiration Date
        /// </summary>
        /// <returns></returns>
        [NonAction]
        public async Task<long> GetTokenExpiresAt()
        {
            //
            var expiresAtStr = Request.Headers[XAuthorization.ExpiresAt].ToString();
            if (expiresAtStr.IsNullOrEmpty())
            {
                expiresAtStr = await HttpContext.GetTokenAsync(XAuthorization.ExpiresAt);
            }

            //
            var expiresAt = expiresAtStr.ConvertTo<long>();

            //
            Logger.LogInformation($"Token ExpiresAt: {expiresAtStr}");
            return expiresAt;
        }

        /// <summary>
        /// Retrieve All Required Tokens
        /// </summary>
        /// <returns></returns>
        [NonAction]
        public async Task<XLoginResponse> RetrieveTokensAsXLoginResponse()
        {
            //
            var accessToken = await GetAccessToken();
            var refreshToken = await GetRefreshToken();
            var expiresAt = await GetTokenExpiresAt();

            //
            return new XLoginResponse
            {
                AccessToken = accessToken,
                RefreshToken = refreshToken,
                ExpiresAt = expiresAt
            };
        }

        /// <summary>
        /// Retrieve All Required Tokens
        /// </summary>
        /// <returns></returns>
        [NonAction]
        public async Task<XTokenResponse> RetrieveTokensAsXTokenResponse()
        {
            //
            var accessToken = await GetAccessToken();
            var refreshToken = await GetRefreshToken();
            var expiresAt = await GetTokenExpiresAt();

            //
            return new XTokenResponse
            {
                AccessToken = accessToken,
                RefreshToken = refreshToken,
                ExpiresAt = expiresAt
            };
        }

        /// <summary>
        /// Retrive UserInfo
        /// </summary>
        /// <returns></returns>
        [NonAction]
        public async Task<XUserClaimsInfoDto> GetUserInfo()
        {
            //
            var claims = User.Claims ?? null;
            if (!claims.HasChild())
            {
                return null;
            }

            var xTokens = await RetrieveTokensAsXTokenResponse();
            var result = new XUserClaimsInfoDto(
                xTokens.AccessToken,
                xTokens.RefreshToken,
                xTokens.ExpiresAt,
                User.Claims
            );

            //
            return result;
        }

        /// <summary>
        /// Validate User Authenticated and Retrieve User Info
        /// </summary>
        /// <returns></returns>
        [NonAction]
        public async Task<XUserClaimsInfoDto> ValidateAndGetUserInfo()
        {
            //
            if (!User.Identity.IsAuthenticated)
            {
                XException.NotAuthorized.Throw();
            }

            //
            var result = await GetUserInfo();
            if (result.IsNull())
            {
                XException.NotAuthorized.Throw();
            }

            //
            return result;
        }
        #endregion

        //
        #region NonActions ...
        /// <summary>
        /// Convert an Exception to Propper Error Result
        /// </summary>
        /// <param name="ex"></param>
        /// <returns></returns>
        [NonAction]
        public new 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(error);
                }
            }
            catch { }

            //
            return BadRequest(error);
        }
        #endregion
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\xIds\Controllers\AccountController.cs

using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Logging;
using xCommons.Configurations;
using xCommons.Providers;
using xIds.Controllers.Base;
using xIds.Interfaces;

namespace xIds.Controllers
{
    /// <summary>
    /// Provide all available tools for manipulating users and accounts
    /// </summary>
    [ApiController]
    public partial class AccountController : XIBaseController
    {

        public AccountController(
            IXIdentityManager identityManager,
            ILogger<AccountController> logger,
            XAppConfiguration appConfiguration,
            XValidationProvider validationProvider
        ) : base(
            logger,
            appConfiguration,
            identityManager,
            validationProvider
        )
        { }
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\xIds\Controllers\StartupController.cs

using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Logging;
using xCommons.Configurations;
using xCommons.Controllers;
using xCommons.Providers;

namespace xIds.Controllers
{
    /// <summary>
    /// Startup and Running Controller 
    /// </summary>
    [Route("")]
    [AllowAnonymous]
    public class StartupController : XBaseController
    {
        public StartupController(
            ILogger<StartupController> logger,
            XAppConfiguration appConfiguration,
            XValidationProvider validationProvider
        ) : base(
            logger,
            appConfiguration,
            validationProvider
        )
        { }

        /// <summary>
        /// Show Configured Welcome Message 
        /// </summary>
        /// <returns>an string message</returns>
        [HttpGet("")]
        [AllowAnonymous]
        public virtual ActionResult<string> Index()
        {
            //
            var controllerName = GetControllerName();
            var message = $"{AppConfiguration.WelcomeMessage}";

            //
            return Ok(message);
        }
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\xIds\DbContext\XIdentityDbContext.cs

using Microsoft.AspNetCore.Identity;
using Microsoft.AspNetCore.Identity.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore;
using xIdentityModels;
using xIdentityModels.Models;
using xIdentityModels.Navigations;

namespace xIds.DbContext
{
    public class XIdentityDbContext : IdentityDbContext
    {
        //
        #region Props/DbSets ...
        public DbSet<XToken> Tokens { get; set; }
        public DbSet<XDevice> Devices { get; set; }
        public DbSet<XProfileImage> Avatars { get; set; }
        public DbSet<XBannedDevice> BannedDevices { get; set; }
        public DbSet<XFriendshipFollower> Followers { get; set; }
        public DbSet<XFriendshipFollowing> Followings { get; set; }
        public DbSet<XVerificationRequest> VerificationRequests { get; set; }
        #endregion

        public XIdentityDbContext(DbContextOptions<XIdentityDbContext> options) : base(options)
        {
            //
            try
            {
                Database.EnsureCreated();
                Database.Migrate();
            }
            catch { }
        }

        protected override void OnModelCreating(ModelBuilder modelBuilder)
        {
            //
            base.OnModelCreating(modelBuilder);

            //
            // Fix XUser GUID Generator on Add ...
            modelBuilder
                .Entity<IdentityUser>()
                .Property(e => e.Id)
                .ValueGeneratedOnAdd();

            //
            // Handle Role List ...
            modelBuilder.Entity<XUser>(u =>
            {
                u.HasMany(x => x.Roles)
                    .WithOne()
                    .HasForeignKey(ur => ur.UserId)
                    .IsRequired();
            });
        }
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\xIds\DI\XDIHelperExtension.cs

using System.Collections.Generic;
using IdentityServer4;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.HttpOverrides;
using Microsoft.AspNetCore.Identity;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using xCommons.Authorization;
using xCommons.Constants;
using xCommons.Extensions;
using xExceptions.Constants;
using xIdentityHelper;
using xIdentityModels;
using xIdentityModels.Configurations;
using xIds.Configurations;
using xIds.Constants;
using xIds.DbContext;
using xIds.Extensions;
using xIds.Helpers;
using xIds.Interfaces;
using xIds.Providers;
using xIds.Validators;
using xMessageService.DI;
using xMessageService.Interfaces;
using xStorageService.DI;
using xStorageService.Interfaces;

namespace xIds.DI
{
    public static class XDIHelperExtension
    {
        /// <summary>
        /// Register Application DataProvider 
        /// </summary>
        /// <param name="services"></param>
        /// <param name="configuration"></param>
        public static void AddXDataProvider(
            this IServiceCollection services,
            IConfiguration configuration
        )
        {
            //
            // Retrieve DbInfo ...
            var dbInfo = configuration.GetXDbInfo();
            var identityDbConnectionString = configuration.GetConnectionString(ConnectionStringNames.IDENTITY_CONNECTION_NAME);

            //
            // Register Db Context for EF ...
            services.AddDbContext<XIdentityDbContext>(builder =>
            {
                //
                builder.PrepareXDbContextOptionsBuilder(
                    dbInfo,
                    identityDbConnectionString
                );
            });
        }

        /// <summary>
        /// Extract Connection String From IConfiguration
        /// </summary>
        /// <param name="config"></param>
        /// <param name="connectionName"></param>
        /// <returns></returns>
        public static string GetXConnectionString(
            this IConfiguration config,
            string connectionName = null
        )
        {
            //
            if (connectionName.IsNullOrEmpty())
            {
                connectionName = XDbProviderConfigurations.DEFAULT_CONNECTION_NAME;
            }

            //
            return config.GetConnectionString(connectionName);
        }

        /// <summary>
        /// Retrive XDataService Configurations
        /// </summary>
        /// <param name="source"></param>
        /// <param name="connectionName"></param>
        /// <returns></returns>
        public static XDataServiceConfiguration GetXDataServiceConfiguration(
            this IConfiguration source,
            string connectionName = null
        )
        {
            //
            var xDataServiceConfigSection = source
                .GetSection(Constants.ConfigurationNodeNames.DATA_SERVICE_NODE_NAME);
            var result = xDataServiceConfigSection.Get<XDataServiceConfiguration>();
            if (result.IsNull())
            {
                result = new XDataServiceConfiguration();
            }

            //
            result.Provider = source.GetXDbProviderType();
            result.ConnectionString = source.GetXConnectionString(connectionName);

            //
            return result;
        }

        /// <summary>
        /// Register XDataService Configuration
        /// </summary>
        /// <param name="services"></param>
        /// <param name="configuration"></param>
        /// <param name="connectionName"></param>
        public static void AddXDataServiceConfiguration(
            this IServiceCollection services,
            IConfiguration configuration,
            string connectionName = null
        )
        {
            //
            var dataServiceConfiguration = configuration
                .GetXDataServiceConfiguration(connectionName);

            //
            services.AddSingleton<XDataServiceConfiguration>(dataServiceConfiguration);
        }

        /// <summary>
        /// Register All Requirements For XIdentityServer Usage
        /// </summary>
        /// <param name="services"></param>
        /// <param name="configuration"></param>
        public static void AddXIdentityServerRequirements(
            this IServiceCollection services,
            IConfiguration configuration
        )
        {
            //
            services.AddXDataProvider(configuration);

            //
            // Register XIdentityMessageProvider ...
            services.AddXIdentityMessageProvider();

            //
            // Register IdentityManager Service ...
            var xIdentityManager = services.GetRegisteredService<IXIdentityManager>();
            if (xIdentityManager.IsNull())
            {
                services.AddXIdentityManager();
            }

            //
            // Check XMessage Service Registered or not and Register it if not ...
            var xMessageProvider = services.GetRegisteredService<IXMessageProvider>();
            if (xMessageProvider.IsNull())
            {
                services.AddXMessageService(configuration);
            }

            //
            // Check Storage Service Registered or not and Register it if not ...
            var xStorageProvider = services.GetRegisteredService<IXStorageProvider>();
            if (xStorageProvider.IsNull())
            {
                services.AddXStorageService(configuration);
            }

            //
            // Register XIdentityConfiguration ...
            var xIdentityConfiguration = configuration.GetXIdentityConfiguration();
            services.AddSingleton<XIdentityConfiguration>(xIdentityConfiguration);

            //
            // Register XIdentityHelper ...
            services.AddSingleton<IXIdentityHelper, XIdentityHelper>();
            var xIdentityHelper = services.GetRegisteredService<IXIdentityHelper>();

            //
            // Register Asp.net Identity ...
            services.AddXIdentity();
        }

        /// <summary>
        /// Add IdentityServer with Support of Ef
        /// </summary>
        /// <param name="services"></param>
        /// <param name="configuration"></param>
        public static void AddEfSupportXIdentityServer(
            this IServiceCollection services,
            IConfiguration configuration
        )
        {
            //
            // Register All Requirements ...
            services.AddXIdentityServerRequirements(configuration);

            //
            // add DbSeeder Config ...
            services.AddXDebSeederDescriptor(configuration);

            //
            // Retrieve Certificate ...
            var identityServerSigningCertificate = configuration.GetCertificate(CertificatesConfigurations.CertificateNames.IdentityServerSigning);

            //
            // Retrieve DbInfo ...
            var dbInfo = configuration.GetXDbInfo();

            //
            // Retrieve Connection String Names ...
            var configDbConnectionString = configuration.GetConnectionString(ConnectionStringNames.CONFIGURATION_CONNECTION_NAME);
            var persistedGrantDbConnectionString = configuration.GetConnectionString(ConnectionStringNames.PRESISTED_GRANTS_CONNECTION_NAME);

            //
            // Register IdentityServer ...
            services.AddIdentityServer(options =>
            {
                //
                options.Discovery.CustomEntries.Add("account_api", "~/account");

                //
                // options.Events.RaiseErrorEvents = true;
                // options.Events.RaiseFailureEvents = true;
                // options.Events.RaiseSuccessEvents = true;
                // options.Events.RaiseInformationEvents = true;
            })
                .LoadSigningCredentialFrom(identityServerSigningCertificate)
                .AddXDbProvider(configuration)
                .AddAspNetIdentity<XUser>()
                .AddProfileService<XIdentityProfileService>()
                .AddResourceOwnerValidator<XResourceOwnerPasswordValidator>();
        }

        /// <summary>
        /// force app to use IdentityServer 
        /// </summary>
        /// <param name="app"></param>
        /// <param name="logger"></param>
        public static void UseXIdentityServer(
            this IApplicationBuilder app,
            ILogger logger
        )
        {
            //
            // Update XIdentityServer Configurations before Use Identity Server ...
            app.SeedData(logger)
                .GetAwaiter()
                .GetResult();

            //
            // Use Identity Server ...
            app.UseIdentityServer();
        }

        /// <summary>
        /// Register Asp.net Identity as User Store 
        /// </summary>
        /// <param name="services"></param>
        public static void AddXIdentity(this IServiceCollection services)
        {
            //
            var xIdentityConfiguration = services.GetRegisteredService<XIdentityConfiguration>();
            if (xIdentityConfiguration.IsNull())
            {
                XException.InvalidConfiguration.Throw();
            }

            //
            var xIdentityHelper = services.GetRegisteredService<IXIdentityHelper>();
            if (xIdentityHelper.IsNull())
            {
                XException.InvalidConfiguration.Throw();
            }

            //
            // Add Identity for User Persists ...
            services.AddIdentity<XUser, IdentityRole>(options =>
            {
                //
                var mLockoutSpan = xIdentityHelper.GetLockoutTimeSpan();

                //
                // Lockout Setting ...
                options.Lockout.DefaultLockoutTimeSpan = mLockoutSpan;
                options.Lockout.MaxFailedAccessAttempts = xIdentityConfiguration.Policy.Lockout.MaxFailedAccessAttempts;
                options.Lockout.AllowedForNewUsers = xIdentityConfiguration.Policy.Lockout.AllowedForNewUsers;

                //
                // Password settings ...
                options.Password.RequireDigit = xIdentityConfiguration.Policy.Password.RequireDigit;
                options.Password.RequireLowercase = xIdentityConfiguration.Policy.Password.RequireLowercase;
                options.Password.RequireNonAlphanumeric = xIdentityConfiguration.Policy.Password.RequireNonAlphanumeric;
                options.Password.RequireUppercase = xIdentityConfiguration.Policy.Password.RequireUppercase;
                options.Password.RequiredLength = xIdentityConfiguration.Policy.Password.RequiredLength;
                options.Password.RequiredUniqueChars = xIdentityConfiguration.Policy.Password.RequiredUniqueChars;

                //
                // SignIn settings ...
                options.SignIn.RequireConfirmedEmail = xIdentityConfiguration.Policy.SignIn.RequireConfirmedEmail;
                options.SignIn.RequireConfirmedPhoneNumber = xIdentityConfiguration.Policy.SignIn.RequireConfirmedPhoneNumber;

                //
                // User settings ...
                options.User.AllowedUserNameCharacters = xIdentityConfiguration.Policy.User.AllowedUserNameCharacters;
                options.User.RequireUniqueEmail = xIdentityConfiguration.Policy.User.RequireUniqueEmail;
            })
                .AddEntityFrameworkStores<XIdentityDbContext>()
                .AddDefaultTokenProviders();
        }

        /// <summary>
        /// Register IdentityServer Based Authentication
        /// </summary>
        /// <param name="services"></param>
        /// <param name="configuration"></param>
        public static void AddXIdentityServerAuthentication(
            this IServiceCollection services,
            IConfiguration configuration
        )
        {
            //
            services.AddXIdentityResourceConfiguration(configuration);
            services.AddAuthentication()
                .AddJwtBearer(options =>
                {
                    //
                    options.SaveToken = true;
                    options.RequireHttpsMetadata = false;

                    //
                    options.ForwardDefault = XAuthentication.IDENTITY_SERVER_LOCAL_API;
                })
                .AddLocalApi();
        }

        /// <summary>
        /// Register Authorization Policies
        /// </summary>
        /// <param name="services"></param>
        /// <param name="policies"></param>
        public static void AddXAuthorization(
            this IServiceCollection services,
            IDictionary<string, AuthorizationPolicy> policies = null
        )
        {
            //
            services.AddAuthorization(options =>
            {
                //
                if (!policies.IsNull())
                {
                    //
                    // Fill Policies ...
                    using (var policiesEnumerator = policies.GetEnumerator())
                    {
                        while (policiesEnumerator.MoveNext())
                        {
                            var policyDescriptor = policiesEnumerator.Current;
                            options.AddPolicy(policyDescriptor.Key, policyDescriptor.Value);
                        }
                    }
                }

                //
                var xPolicies = XAuthorizationHelper.GetXAuthorizationPolicies();
                if (!xPolicies.IsNull())
                {
                    //
                    // Fill Policies ...
                    using (var policiesEnumerator = xPolicies.GetEnumerator())
                    {
                        while (policiesEnumerator.MoveNext())
                        {
                            var policyDescriptor = policiesEnumerator.Current;
                            options.AddPolicy(policyDescriptor.Key, policyDescriptor.Value);
                        }
                    }
                }

                //
                // Add Local APi Policy ...
                options.AddPolicy(IdentityServerConstants.LocalApi.PolicyName, policy =>
                {
                    //
                    policy.AddAuthenticationSchemes(IdentityServerConstants.LocalApi.AuthenticationScheme);
                    policy.RequireAuthenticatedUser();
                });
            });

            //
            services.AddSingleton<IAuthorizationHandler, RequiredRolesHandler>();
        }

        /// <summary>
        /// Use Forward Headers Options for resolving behind a proxy issues ...
        /// </summary>
        /// <param name="source"></param>
        /// <returns></returns>
        public static void UseXForwardOptions(this IApplicationBuilder source)
        {
            //
            var forwardOptions = new ForwardedHeadersOptions
            {
                ForwardedHeaders = ForwardedHeaders.XForwardedFor | ForwardedHeaders.XForwardedProto,
                RequireHeaderSymmetry = false
            };

            //
            forwardOptions.KnownNetworks.Clear();
            forwardOptions.KnownProxies.Clear();

            //
            // ref: https://github.com/aspnet/Docs/issues/2384
            source.UseForwardedHeaders(forwardOptions);
        }
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\xIds\Extensions\DbExtensions.cs

using System;
using System.Reflection;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Infrastructure;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using MySql.EntityFrameworkCore.Infrastructure;
using xCommons.Extensions;
using xIdentityModels.Configurations;
using xIds.Configurations;
using xIds.Constants;
using xIds.Models;

namespace xIds.Extensions
{
    public static class DbExtensions
    {
        /// <summary>
        /// Retrieve Data Provider Type from Configurations
        /// </summary>
        /// <param name="source"></param>
        /// <returns></returns>
        public static XDbProviders GetXDbProviderType(this IConfiguration source)
        {
            //
            var dbProvider = (source[$"{ConfigurationNodeNames.PROVIDER_NODE_NAME}"])
                .ToNormalString();

            //
            return dbProvider == ProviderType.SQLServer.ToNormalString() ?
                XDbProviders.SQLServer :
                dbProvider == ProviderType.SQLite.ToNormalString() ?
                XDbProviders.SQLite :
                dbProvider == ProviderType.MySQL.ToNormalString() ?
                XDbProviders.MySQL :
                XDbProviders.None;
        }

        /// <summary>
        /// Retrieve AspNet Identity Configurations 
        /// </summary>
        /// <param name="source"></param>
        /// <returns></returns>
        public static XIdentityConfiguration GetXIdentityConfiguration(this IConfiguration source)
        {
            //
            var xIdentityConfigSection = source
                .GetSection(ConfigurationNodeNames.IDENTITY_NODE_NAME);
            return xIdentityConfigSection.Get<XIdentityConfiguration>();
        }

        /// <summary>
        /// Retrieve XIdentityResource Configuration from AppSettings
        /// </summary>
        /// <param name="configuration"></param>
        /// <returns></returns>
        public static XIdentityResourceConfiguration GetXIdentityResourceConfiguration(this IConfiguration configuration)
        {
            //
            var xIdentityResourceSection = configuration.GetSection(ConfigurationNodeNames.IDENTITY_RESOURCE_NODE_NAME);
            return xIdentityResourceSection.Get<XIdentityResourceConfiguration>();
        }

        /// <summary>
        /// Register XIdentityResourceConfiguration
        /// </summary>
        /// <param name="services"></param>
        /// <param name="configuration"></param>
        public static void AddXIdentityResourceConfiguration(
            this IServiceCollection services,
            IConfiguration configuration
        )
        {
            //
            var xIdentityResourceConfiguration = configuration.GetXIdentityResourceConfiguration();
            if (!xIdentityResourceConfiguration.IsNull())
            {
                services.AddSingleton<XIdentityResourceConfiguration>(xIdentityResourceConfiguration);
            }
        }

        /// <summary>
        /// Converts DbInfo Options Builder for MySql Usage
        /// </summary>
        /// <param name="source"></param>
        /// <returns></returns>
        public static Action<MySQLDbContextOptionsBuilder> GetMySqlOptionsBuilder(this XDbInfo source)
        {
            return ((Action<MySQLDbContextOptionsBuilder>)source.OptionsBuilder);
        }

        /// <summary>
        /// Converts DbInfo Options Builder for SQLite Usage
        /// </summary>
        /// <param name="source"></param>
        /// <returns></returns>
        public static Action<SqliteDbContextOptionsBuilder> GetSQLiteOptionsBuilder(this XDbInfo source)
        {
            return ((Action<SqliteDbContextOptionsBuilder>)source.OptionsBuilder);
        }

        /// <summary>
        /// Converts DbInfo Options Builder for SQLServer Usage
        /// </summary>
        /// <param name="source"></param>
        /// <returns></returns>
        public static Action<SqlServerDbContextOptionsBuilder> GetSQLServerOptionsBuilder(this XDbInfo source)
        {
            return ((Action<SqlServerDbContextOptionsBuilder>)source.OptionsBuilder);
        }

        /// <summary>
        /// Retrieve Required Informations to Register DbContexts into Di as XDbInfo instance
        /// </summary>
        /// <param name="configuration"></param>
        /// <returns></returns>
        public static XDbInfo GetXDbInfo(this IConfiguration configuration)
        {
            return new XDbInfo
            {
                ProviderType = configuration.GetXDbProviderType(),
                MigrationsAssembly = typeof(Startup).GetTypeInfo().Assembly.GetName().Name
            };
        }

        /// <summary>
        /// Prepare DbContextOptionsBuilder with Propper data to Support Configured DbProvider
        /// </summary>
        /// <param name="source"></param>
        /// <param name="dbInfo"></param>
        /// <param name="connectionString"></param>
        public static void PrepareXDbContextOptionsBuilder(
            this DbContextOptionsBuilder source,
            XDbInfo dbInfo,
            string connectionString
        )
        {
            //
            if (dbInfo.ProviderType == XDbProviders.MySQL)
            {
                //
                // Add Support for MySql ...
                source.UseMySQL(
                    connectionString,
                    dbInfo.GetMySqlOptionsBuilder()
                );
            }
            else if (dbInfo.ProviderType == XDbProviders.SQLite)
            {
                //
                // Add Support for SQLite ...
                source.UseSqlite(
                    connectionString,
                    dbInfo.GetSQLiteOptionsBuilder()
                );
            }
            else if (dbInfo.ProviderType == XDbProviders.SQLServer)
            {
                //
                // Add Support for SQLServer ...
                source.UseSqlServer(
                    connectionString,
                    dbInfo.GetSQLServerOptionsBuilder()
                );
            }
        }
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\xIds\Extensions\IdentityExtensions.cs

using Microsoft.Extensions.DependencyInjection;
using xIds.Interfaces;
using xIds.Providers;

namespace xIds.Extensions
{
    public static class IdentityExtensions
    {
        /// <summary>
        /// Register IdentityManager 
        /// </summary>
        /// <param name="source"></param>
        public static void AddXIdentityManager(this IServiceCollection source)
        {
            source.AddScoped<IXIdentityManager, XIdentityManager>();
        }

        /// <summary>
        /// Register IdentityMessage Provider 
        /// </summary>
        /// <param name="source"></param>
        public static void AddXIdentityMessageProvider(
            this IServiceCollection source
        )
        {
            source.AddScoped<IXIdentityMessageProvider, XIdentityMessageProvider>();
        }
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\xIds\Extensions\IIdentityServerBuilderExtensions.cs

using System.Reflection;
using System.Security.Cryptography.X509Certificates;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using xCommons.Extensions;
using xCommons.Models;
using xIds.Constants;

namespace xIds.Extensions
{
    public static class IIdentityServerBuilderExtensions
    {
        /// <summary>
        /// Add Support for Configured XDbProvider to IdentityServer
        /// </summary>
        /// <param name="source"></param>
        /// <param name="configuration"></param>
        /// <returns></returns>
        public static IIdentityServerBuilder AddXDbProvider(
            this IIdentityServerBuilder source,
            IConfiguration configuration
        )
        {
            //
            // Retrieve DB Info ...
            var dbInfo = configuration.GetXDbInfo();
            dbInfo.OptionsBuilder = (optionsBuilder) =>
            {
                optionsBuilder.MigrationsAssembly(typeof(Startup).GetTypeInfo().Assembly.GetName().Name);
                optionsBuilder.UseQuerySplittingBehavior(QuerySplittingBehavior.SplitQuery);
            };

            //
            // Retrieve Connection String Names ...
            var identityDbConnectionString = configuration.GetConnectionString(ConnectionStringNames.IDENTITY_CONNECTION_NAME);
            var configDbConnectionString = configuration.GetConnectionString(ConnectionStringNames.CONFIGURATION_CONNECTION_NAME);
            var persistedGrantDbConnectionString = configuration.GetConnectionString(ConnectionStringNames.PRESISTED_GRANTS_CONNECTION_NAME);

            //
            // Add Operational Store ...
            source.AddOperationalStore(opt =>
            {
                opt.ConfigureDbContext =
                    builder =>
                    {
                        //
                        builder.PrepareXDbContextOptionsBuilder(
                            dbInfo,
                            persistedGrantDbConnectionString
                        );

                        //
                        builder.UseQueryTrackingBehavior(QueryTrackingBehavior.NoTracking);
                    };

                //
                // this enables automatic token cleanup. this is optional.
                opt.EnableTokenCleanup = true;
                opt.TokenCleanupInterval = 3600;
            });

            //
            // Add Configuration Store ...
            source.AddConfigurationStore(opt =>
            {
                opt.ConfigureDbContext =
                    builder =>
                    {
                        //
                        builder.PrepareXDbContextOptionsBuilder(
                            dbInfo,
                            configDbConnectionString
                        );
                    };
            });

            //
            return source;
        }

        /// <summary>
        /// Set Configured Certificate File to IdentityServer 
        /// </summary>
        /// <param name="builder"></param>
        /// <param name="certificate"></param>
        /// <returns></returns>
        public static IIdentityServerBuilder LoadSigningCredentialFrom(
            this IIdentityServerBuilder builder,
            XCertificate certificate
        )
        {
            //
            if (!certificate.IsNull() &&
                !certificate.Path.IsNullOrEmpty() &&
                !certificate.Secret.IsNullOrEmpty()
            )
            {
                try
                {
                    builder.AddSigningCredential(new X509Certificate2(certificate.Path, certificate.Secret));
                }
                catch
                {
                    builder.AddDeveloperSigningCredential();
                }
            }
            else
            {
                builder.AddDeveloperSigningCredential();
            }

            //
            return builder;
        }
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\xIds\Extensions\IQueryableExtensions.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Reflection;
using System.Threading.Tasks;
using Microsoft.EntityFrameworkCore;
using xCommons.Extensions;
using xExceptions.Constants;
using xModels.Base;
using xIds.Constants;

namespace xIds.Extensions
{
    public static class IQueryableExtensions
    {
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\xIds\Extensions\XDbSeederExtensions.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using IdentityServer4.EntityFramework.DbContexts;
using IdentityServer4.EntityFramework.Mappers;
using Microsoft.AspNetCore.Builder;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using xCommons.Extensions;
using xIdentityModels.Descriptors;
using xIdentityModels.Extensions;
using xIds.Constants;
using xIds.Interfaces;
using xIds.Models;

namespace xIds.Extensions
{
    public static class XDbSeeder
    {
        /// <summary>
        /// Retrieve DbSeedDescriptor from appSetting Configuration
        /// </summary>
        /// <param name="configuration"></param>
        /// <returns></returns>
        public static XDbSeedDescriptor GetXDbSeedDescriptor(this IConfiguration configuration)
        {
            //
            var dbSeedSection = configuration.GetSection(ConfigurationNodeNames.DB_SEED_NODE_NAME);
            return dbSeedSection.Get<XDbSeedDescriptor>();
        }

        /// <summary>
        /// Register XDbSeedDescriptor as Singleton Service
        /// </summary>
        /// <param name="services"></param>
        /// <param name="configuration"></param>
        public static void AddXDebSeederDescriptor(
            this IServiceCollection services,
            IConfiguration configuration
        )
        {
            //
            var dbSeedDescriptor = configuration.GetXDbSeedDescriptor();
            if (!dbSeedDescriptor.IsNull())
            {
                services.AddSingleton<XDbSeedDescriptor>(dbSeedDescriptor);
            }
            else
            {
                Console.WriteLine("Error: DbSeeder Configuration not found in AppSetting ...");
            }
        }

        /// <summary>
        /// Add Base Required Data to XIdentitySer DbContexts
        /// </summary>
        /// <param name="app"></param>
        /// <param name="logger"></param>
        /// <returns></returns>
        public static async Task SeedData(
            this IApplicationBuilder app,
            ILogger logger
        )
        {
            //
            logger.LogInformation($"Start Add/Update XIdentityServer Descriptors ...");

            //
            // Create Scope ...
            using (var scope = app.ApplicationServices.CreateScope())
            {
                //
                // Retrieve Required Configurations ...
                var dbSeedDescriptor = scope.ServiceProvider.GetService<XDbSeedDescriptor>();
                if (dbSeedDescriptor.IsNull())
                {
                    //
                    Console.WriteLine("DbSeeder is Null ...");
                    return;
                }
                logger.LogInformation($"Update Exists Descriptors: {dbSeedDescriptor.UpdateExists.ToString()}");

                //
                // Retrieve Required Services ...
                var identityProvider = scope.ServiceProvider.GetService<IXIdentityManager>();

                //
                // Retrieve DbContexts ...
                var grantDbContext = scope.ServiceProvider.GetService<PersistedGrantDbContext>();
                var configDbContext = scope.ServiceProvider.GetService<ConfigurationDbContext>();

                //
                #region Clients ...
                //
                logger.LogInformation($"Start Seeding Clients ...");

                //
                var dClients = dbSeedDescriptor.Clients;
                var hasClient = configDbContext.Clients.Any();
                if ((!hasClient ||
                        (hasClient && dbSeedDescriptor.UpdateExists)) &&
                    dClients.HasChild())
                {
                    //
                    var clientEntities = dClients.Select(dc => dc.ToEntity());

                    //
                    foreach (var client in clientEntities)
                    {
                        //
                        logger.LogInformation($"Add/Update: {client.ClientId}");

                        //
                        // Retrieve Exists Client ...
                        var existsClient = configDbContext.Clients
                            .Include(c => c.AllowedCorsOrigins)
                            .Include(c => c.AllowedGrantTypes)
                            .Include(c => c.AllowedScopes)
                            .Include(c => c.Claims)
                            .Include(c => c.ClientSecrets)
                            .FirstOrDefault(cl => cl.ClientId == client.ClientId);

                        //
                        var isExistsClient = !existsClient.IsNull();
                        var isSameContent = isExistsClient &&
                            existsClient.IsSameContent(client, propertyBlackList: new[] { nameof(existsClient.Id) });

                        //
                        if (isExistsClient)
                        {
                            //
                            if (!isSameContent)
                            {
                                //
                                logger.LogInformation($"Update Client: {existsClient.ClientId}");

                                //
                                existsClient = existsClient.UpdateData(client, propertyBlackList: new[] { nameof(existsClient.Id) });
                                configDbContext.Clients.Update(existsClient);
                            }
                        }
                        else
                        {
                            //
                            logger.LogInformation($"Add Client: {client.ClientId}");

                            //
                            await configDbContext.Clients.AddAsync(client);
                        }
                    }

                    //
                    // Save Changes on Config Db Context ...
                    await configDbContext.SaveChangesAsync();
                }

                //
                logger.LogInformation($"Finish Seeding Clients ...");
                #endregion

                //
                #region IdentityResources ...
                //
                logger.LogInformation($"Start Seeding Identity Resources ...");

                //
                var dIdentityResources = dbSeedDescriptor.IdentityResources;
                var hasIdentityResources = configDbContext.IdentityResources.Any();
                if ((!hasIdentityResources ||
                        (hasIdentityResources && dbSeedDescriptor.UpdateExists)) &&
                    dIdentityResources.HasChild())
                {
                    //
                    var identityResourceEntities = dIdentityResources.Select(di => di.ToEntity());

                    //
                    foreach (var identityResource in identityResourceEntities)
                    {
                        //
                        logger.LogInformation($"Add/Update: {identityResource.DisplayName}");

                        //
                        // Retrieve Exists IdentityResource ...
                        var existsIdentityResource = configDbContext.IdentityResources
                            .AsNoTracking()
                            .FirstOrDefault(ir => ir.Name == identityResource.Name);

                        //
                        var isExistsResource = !existsIdentityResource.IsNull();
                        var isSameContent = isExistsResource &&
                            existsIdentityResource.IsSameContent(identityResource, propertyBlackList: new[] { nameof(existsIdentityResource.Id) });

                        //
                        if (isExistsResource &&
                            dbSeedDescriptor.UpdateExists)
                        {
                            //
                            if (!isSameContent)
                            {
                                //
                                logger.LogInformation($"Update IdentityResource: {identityResource.DisplayName}");

                                //
                                existsIdentityResource = existsIdentityResource.UpdateData(identityResource, propertyBlackList: new[] { nameof(existsIdentityResource.Id) });
                                configDbContext.IdentityResources.Update(existsIdentityResource);
                            }
                        }
                        else
                        {
                            //
                            logger.LogInformation($"Add IdentityResource: {identityResource.DisplayName}");

                            //
                            await configDbContext.IdentityResources.AddAsync(identityResource);
                        }
                    }

                    //
                    // Save Changes on Config Db Context ...
                    // await configDbContext.SaveChangesAsync();
                }

                //
                logger.LogInformation($"Finish Seeding Identity Resources ...");
                #endregion

                //
                #region Api Resources ...
                //
                logger.LogInformation($"Start Seeding Api Resources ...");

                //
                var dApiResources = dbSeedDescriptor.ApiResources;
                var hasApiResources = configDbContext.ApiResources.Any();
                if ((!hasApiResources ||
                        (hasApiResources && dbSeedDescriptor.UpdateExists)) &&
                    dApiResources.HasChild())
                {
                    //
                    var apiResourceEntities = dApiResources.Select(da => da.ToEntity());

                    //
                    foreach (var apiResource in apiResourceEntities)
                    {
                        //
                        logger.LogInformation($"Add/Update: {apiResource.DisplayName}");

                        //
                        // Retrieve Exists ApiResource ...
                        var existsApiResource = configDbContext.ApiResources
                            .Include(r => r.Secrets)
                            .Include(r => r.Scopes)
                            .FirstOrDefault(ar => ar.Name == apiResource.Name);

                        //
                        var isExistsResource = !existsApiResource.IsNull();
                        var isSameContent = isExistsResource &&
                            existsApiResource.IsSameContent(apiResource, propertyBlackList: new[] { nameof(existsApiResource.Id) });

                        //
                        if (isExistsResource &&
                            dbSeedDescriptor.UpdateExists)
                        {
                            //
                            if (!isSameContent)
                            {
                                //
                                logger.LogInformation($"Update ApiResource: {existsApiResource.DisplayName}");

                                //
                                existsApiResource = existsApiResource.UpdateData(apiResource, propertyBlackList: new[] { nameof(existsApiResource.Id) });
                                configDbContext.ApiResources.Update(existsApiResource);
                            }
                        }
                        else
                        {
                            //
                            logger.LogInformation($"Add ApiResource: {apiResource.DisplayName}");

                            //
                            await configDbContext.ApiResources.AddAsync(apiResource);
                        }
                    }

                    //
                    // Save Changes on Config Db Context ...
                    // await configDbContext.SaveChangesAsync();
                }

                //
                logger.LogInformation($"Finish Seeding Api Resources ...");
                #endregion

                //
                #region Api Scopes ...
                //
                logger.LogInformation($"Start Seeding Scopes ...");

                //
                var dScopes = dbSeedDescriptor.ApiScopes;
                var hasScope = configDbContext.ApiScopes.Any();
                if ((!hasScope ||
                        (hasScope && dbSeedDescriptor.UpdateExists)) &&
                    dScopes.HasChild())
                {
                    //
                    var apiScopeEntities = dScopes.Select(dc => dc.ToEntity());

                    //
                    foreach (var apiScope in apiScopeEntities)
                    {
                        //
                        logger.LogInformation($"Add/Update: {apiScope.DisplayName}");

                        //
                        // Retrieve Exists Client ...
                        var existsScope = configDbContext.ApiScopes
                            .FirstOrDefault(sc => sc.Name == apiScope.Name);

                        //
                        var isExistsScope = !existsScope.IsNull();
                        var isSameContent = isExistsScope &&
                            existsScope.IsSameContent(apiScope, propertyBlackList: new[] { nameof(existsScope.Id) });

                        //
                        if (isExistsScope &&
                            dbSeedDescriptor.UpdateExists)
                        {
                            //
                            if (!isSameContent)
                            {
                                //
                                logger.LogInformation($"Update ApiScope: {existsScope.Name}");

                                //
                                existsScope = existsScope.UpdateData(apiScope, propertyBlackList: new[] { nameof(existsScope.Id) });
                                configDbContext.ApiScopes.Update(existsScope);
                            }
                        }
                        else
                        {
                            //
                            logger.LogInformation($"Add ApiScope: {apiScope.Name}");

                            //
                            await configDbContext.ApiScopes.AddAsync(apiScope);
                        }
                    }

                    //
                    // Save Changes on Config Db Context ...
                    await configDbContext.SaveChangesAsync();
                }

                //
                logger.LogInformation($"Finish Seeding Scopes ...");
                #endregion

                //
                #region Users ...
                //
                logger.LogInformation($"Start Seeding Users ...");

                //
                var configUsers = dbSeedDescriptor.Users;
                var hasUser = identityProvider.GetUsersDbSet().Any();
                if ((!hasUser ||
                        (hasUser && dbSeedDescriptor.UpdateExists)) &&
                    configUsers.HasChild())
                {
                    foreach (var user in configUsers)
                    {
                        //
                        logger.LogInformation($"Add/Update User: {user.UserName}");

                        //
                        var isUserExists = await identityProvider.IsUserExistsAsync(user.UserName);
                        if (isUserExists &&
                            dbSeedDescriptor.UpdateExists)
                        {
                            //
                            var existsUser = await identityProvider.GetUserAsync(user.UserName);
                            var isSame = existsUser.IsSameAs(user);
                            if (!isSame)
                            {
                                //
                                // Update Entity ...
                                existsUser = existsUser.UpdateData(user, propertyWhiteList: new[] {
                                    nameof (XIdentityUserDescriptor.FirstName),
                                    nameof (XIdentityUserDescriptor.LastName),
                                    nameof (XIdentityUserDescriptor.UserName),
                                    nameof (XIdentityUserDescriptor.Email),
                                    nameof (XIdentityUserDescriptor.EmailConfirmed),
                                    nameof (XIdentityUserDescriptor.PhoneNumber),
                                    nameof (XIdentityUserDescriptor.PhoneNumberConfirmed),
                                    nameof (XIdentityUserDescriptor.IsEnable),
                                    nameof (XIdentityUserDescriptor.IsBanned),
                                    nameof (XIdentityUserDescriptor.DateOfBirth)
                                }, propertyValueProviders: new[] {
                                    new KeyValuePair<string, Func<XIdentityUserDescriptor, object>> (
                                        nameof (XIdentityUserDescriptor.DateOfBirth),
                                        (user) => DateTime.Parse (user.DateOfBirth))
                                });

                                //
                                await identityProvider.UpdateUserAsync(existsUser, false, false);
                            }
                        }
                        else
                        {
                            await identityProvider.CreateUserAsync(user);
                        }
                    }
                }

                //
                logger.LogInformation($"Finish Seeding Users ...");
                #endregion
            }

            //
            logger.LogInformation($"Finish Add/Update XIdentityServer Descriptors ...");
        }
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\xIds\Extensions\XModelExtensions.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.EntityFrameworkCore;
using xCommons.Extensions;
using xDataService.Configuration;
using xIdentityModels.Models;

namespace xIds.Extensions
{
    public static class XModelExtensions
    {
        /// <summary>
        /// Determine a banned time is passed or not
        /// </summary>
        /// <param name="source"></param>
        /// <param name="delaySeconds"></param>
        /// <returns></returns>
        public static bool IsDelayTimePassed(
            this XBannedDevice source,
            int delaySeconds
        )
        {
            //
            var passedTime = source.BannedOn.AddSeconds(delaySeconds);

            //
            var result = DateTime.UtcNow >= passedTime;

            //
            return result;
        }

        /// <summary>
        /// Applying Filter to IQueryable
        /// /// </summary>
        /// <typeparam name="T"></typeparam>
        public static async Task<IQueryable<T>> ApplyFilterAsync<T>(
            this IQueryable<T> source,
            string filter
        ) where T : class
        {
            //
            // Apply Filter ...
            if (!filter.IsNullOrEmpty())
            {
                //
                var items = source.AsAsyncEnumerable();
                var filteredItems = new List<T>();
                await
                foreach (var item in items)
                {
                    //
                    if (item.GetPropValues()
                        .ToNormalString()
                        .Contains(filter
                            .ToNormalString()))
                    {
                        //
                        filteredItems.Add(item);
                    }
                }

                //
                return filteredItems.AsQueryable();
            }

            //
            return source;
        }

        public static XDataServiceConfiguration ToXDataServiceConfig(this Configurations.XDataServiceConfiguration config)
        {
            //
            var result = new XDataServiceConfiguration();

            //
            if (!config.IsNullOrDefault())
            {
                //
                result.PagingConfiguration.DefaultPageSize = config.PagingConfiguration.DefaultPageSize;
                result.PagingConfiguration.MaxAvailablePageSize = config.PagingConfiguration.MaxAvailablePageSize;
                result.PagingConfiguration.MinAvailablePageSize = config.PagingConfiguration.MinAvailablePageSize;
            }

            //
            return result;
        }
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\xIds\Helpers\XIdentityHelper.cs

using System;
using System.IdentityModel.Tokens.Jwt;
using Microsoft.IdentityModel.Tokens;
using xCommons.Extensions;
using xCommons.Providers;
using xExceptions.Constants;
using xIdentityModels.Configurations;
using xIdentityModels.Extensions;
using xIdentityModels.Models;
using xIds.Interfaces;

namespace xIds.Helpers
{
    public class XIdentityHelper : IXIdentityHelper
    {
        private readonly XIdentityConfiguration configurations;
        private readonly JwtSecurityTokenHandler tokenHandler;
        private readonly XValidationProvider dataValidationHelper;

        public XIdentityHelper(
            XIdentityConfiguration configurations,
            XValidationProvider dataValidationHelper
        )
        {
            //
            this.configurations = configurations;
            this.tokenHandler = new JwtSecurityTokenHandler();
            this.dataValidationHelper = dataValidationHelper;
        }

        //
        #region Configuration Parser ...
        /// <summary>
        /// Generate a Key for Signing JWT Tokens
        /// </summary>
        /// <returns></returns>
        public SymmetricSecurityKey GetTokenSecretKey()
        {
            //
            dataValidationHelper
                .NotEmpty(configurations.IdentitySecretKey);

            //
            var result = new SymmetricSecurityKey(configurations
                .IdentitySecretKey.ToBytes());

            //
            return result;
        }

        /// <summary>
        /// Generate Security Token Signing Key
        /// </summary>
        /// <returns></returns>
        public SigningCredentials GetTokenSigningCredentials()
        {
            //
            var key = GetTokenSecretKey();
            dataValidationHelper
                .NotNull(key);

            //
            var result = new SigningCredentials(key, SecurityAlgorithms.HmacSha256);

            //
            return result;
        }

        /// <summary>
        /// Get Token Validation Parameters
        /// </summary>
        /// <returns></returns>
        public TokenValidationParameters GetTokenValidationParams()
        {
            //
            var key = GetTokenSecretKey();
            var issuer = configurations.IdentityIssuer;
            var audience = configurations.IdentityAudience;

            //
            dataValidationHelper
                .NotNull(key);
            dataValidationHelper
                .NotEmpty(issuer, audience);

            //
            var result = new TokenValidationParameters
            {
                ValidIssuer = issuer,
                ValidAudience = audience,
                ValidateLifetime = true,
                IssuerSigningKey = key
            };

            //
            return result;
        }

        /// <summary>
        /// Get Account Lockout Time Span after Max Fail Reached
        /// </summary>
        /// <returns></returns>
        public TimeSpan GetLockoutTimeSpan()
        {
            //
            dataValidationHelper
                .NotNull(configurations.Policy, configurations.Policy.Lockout);

            //
            var timeSpanString = configurations.Policy.Lockout.LockoutTimeSpanProvider;
            dataValidationHelper
                .NotEmpty(timeSpanString);

            //
            var mExpireValue = 0;
            var mExpireValueStr = timeSpanString.GetDigits();
            var mExpireUnit = timeSpanString.Replace(mExpireValueStr, "");
            dataValidationHelper
                .NotEmpty(mExpireUnit);
            dataValidationHelper
                .NotEmpty(mExpireValueStr);

            //
            var isParsed = int.TryParse(mExpireValueStr, out mExpireValue);

            //
            switch (mExpireUnit)
            {
                case "d":
                    return TimeSpan.FromDays(mExpireValue);

                case "h":
                    return TimeSpan.FromHours(mExpireValue);

                case "m":
                    return TimeSpan.FromMinutes(mExpireValue);

                case "s":
                    return TimeSpan.FromSeconds(mExpireValue);

                case "ms":
                default:
                    return TimeSpan.FromMilliseconds(mExpireValue);
            }
        }

        /// <summary>
        /// Generate Security Token Descriptor for Tokenize another
        /// </summary>
        /// <returns></returns>
        public SecurityTokenDescriptor GetActionTokenDescriptor()
        {
            //
            dataValidationHelper
                .NotNull(configurations);

            //
            var issuer = configurations.IdentityIssuer;
            var audience = configurations.IdentityAudience;
            dataValidationHelper
                .NotEmpty(issuer, audience);

            //
            var expDate = GetActionTokenExpirationDate();
            var signingCreds = GetTokenSigningCredentials();
            dataValidationHelper
                .NotNull(expDate, signingCreds);

            //
            var descriptor = new SecurityTokenDescriptor
            {
                Issuer = issuer,
                Audience = audience,
                Expires = expDate,
                SigningCredentials = signingCreds
            };

            //
            return descriptor;
        }

        /// <summary>
        /// Get Action Token Expiration Date
        /// </summary>
        /// <returns></returns>
        public DateTime GetActionTokenExpirationDate()
        {
            //
            dataValidationHelper
                .NotNull(configurations);

            //
            var expDateProvider = configurations
                .ActionTokenExpirationDateProvider;
            dataValidationHelper
                .NotEmpty(expDateProvider);

            //
            var result = GetExpirationTime(expDateProvider);
            dataValidationHelper
                .NotNull(result);

            //
            return result;
        }
        #endregion

        //
        #region Action Token Handlers ...
        public bool ValidateToken(string token)
        {
            //
            // Validate Args ...
            dataValidationHelper
                .NotEmpty(token);
            dataValidationHelper
                .NotNull(tokenHandler);

            //
            // Prepare Requirements ...
            var tokenValidationParams = GetTokenValidationParams();
            dataValidationHelper
                .NotNull(tokenValidationParams);

            //
            var result = token
                .ValidateToken(tokenHandler, tokenValidationParams);

            //
            return result;
        }

        /// <summary>
        /// Converts a Token string to SecurityToken instance
        /// </summary>
        /// <param name="token"></param>
        /// <returns></returns>
        public SecurityToken ToSecurityToken(string token)
        {
            //
            dataValidationHelper
                .NotEmpty(token);

            //
            // Validate token ...
            var isTokenValid = ValidateToken(token);
            if (!isTokenValid)
            {
                XException.InvalidToken.Throw();
            }

            //
            // Prepare and Validate Requirements ...
            var tokenValidationParams = GetTokenValidationParams();
            dataValidationHelper
                .NotNull(tokenHandler, tokenValidationParams);

            //
            var result = token
                .ToSecurityToken(tokenHandler, tokenValidationParams);
            dataValidationHelper
                .NotNull(result);

            //
            return result;
        }

        /// <summary>
        /// Convert an ActionRequest to Token Object 
        /// </summary>
        /// <param name="request"></param>
        /// <returns></returns>
        public SecurityToken ToSecurityToken(XActionRequestToken request)
        {
            //
            var tokenDescriptor = GetActionTokenDescriptor();

            //
            dataValidationHelper.NotNull(request, tokenHandler, tokenDescriptor);

            //
            var result = request.ToJwtToken(tokenHandler, tokenDescriptor);

            //
            return result;
        }

        /// <summary>
        /// Retrieve a Token Exiration Date 
        /// </summary>
        /// <param name="token"></param>
        /// <returns></returns>
        public DateTime GetTokenExpirationDate(string token)
        {
            //
            var tokenObj = ToSecurityToken(token);
            dataValidationHelper.NotNull(tokenObj);

            //
            var result = tokenObj.ValidTo;

            //
            return result;
        }

        public XActionRequestToken ParseActionRequestToken(string token)
        {
            //
            dataValidationHelper
                .NotEmpty(token);

            //
            // Validate token ...
            var isTokenValid = ValidateToken(token);
            if (!isTokenValid)
            {
                XException.InvalidToken.Throw();
            }

            //
            // Prepare and Validate Requirements ...
            var tokenValidationParams = GetTokenValidationParams();
            dataValidationHelper
                .NotNull(tokenHandler, tokenValidationParams);

            //
            var result = token
                .ParseActionRequestToken(tokenHandler, tokenValidationParams);
            dataValidationHelper
                .NotNull(result);

            //
            return result;
        }

        /// <summary>
        /// Convert a JWT Security Token Object to 
        /// it's String Representation 
        /// </summary>
        /// <param name="token"></param>
        /// <returns></returns>
        public string ToTokenString(JwtSecurityToken token)
        {
            //
            dataValidationHelper.NotNull(token);

            //
            var result = tokenHandler
                .WriteToken(token);

            //
            return result;
        }

        /// <summary>
        /// Convert an Action Token Object to it's String Representation
        /// </summary>
        /// <param name="token"></param>
        /// <returns></returns>
        public string ToTokenString(SecurityToken token)
        {
            //
            // Validate Args ...
            dataValidationHelper
                .NotNull(token, tokenHandler);

            //
            // Generate and return Result ...
            var result = token.ToTokenString(tokenHandler);
            dataValidationHelper
                .NotEmpty(result);

            //
            return result;
        }
        #endregion

        //
        #region Private Actions ...
        /// <summary>
        /// Calculating Date Difference Provider String
        /// and Generate Date based on UTC Time
        /// </summary>
        /// <param name="expirationProvider"></param>
        /// <returns></returns>
        private DateTime GetExpirationTime(string expirationProvider)
        {
            //
            dataValidationHelper
                .NotEmpty(expirationProvider);

            //
            var mExpireValue = 0;
            var mExpireValueStr = expirationProvider.GetDigits();
            var mExpireUnit = expirationProvider.Replace(mExpireValueStr, "");
            dataValidationHelper
                .NotEmpty(mExpireUnit);
            dataValidationHelper
                .NotEmpty(mExpireValueStr);

            //
            var isParsed = int.TryParse(mExpireValueStr, out mExpireValue);

            //
            switch (mExpireUnit)
            {
                case "d":
                    return DateTime.UtcNow.AddDays(mExpireValue);

                case "h":
                    return DateTime.UtcNow.AddHours(mExpireValue);

                case "m":
                    return DateTime.UtcNow.AddMinutes(mExpireValue);

                case "s":
                    return DateTime.UtcNow.AddSeconds(mExpireValue);

                case "ms":
                default:
                    return DateTime.UtcNow.AddMilliseconds(mExpireValue);
            }
        }
        #endregion                
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\xIds\Interfaces\IXIdentityHelper.cs

using System;
using System.IdentityModel.Tokens.Jwt;
using Microsoft.IdentityModel.Tokens;
using xIdentityModels.Models;

namespace xIds.Interfaces
{
    public interface IXIdentityHelper
    {
        //
        #region Configuration Parser ...
        SymmetricSecurityKey GetTokenSecretKey();
        SigningCredentials GetTokenSigningCredentials();
        TokenValidationParameters GetTokenValidationParams();
        TimeSpan GetLockoutTimeSpan();
        #endregion

        //
        #region Action Token Handlers ...
        bool ValidateToken(string token);
        SecurityToken ToSecurityToken(string token);
        SecurityToken ToSecurityToken(XActionRequestToken request);
        string ToTokenString(SecurityToken token);
        string ToTokenString(JwtSecurityToken token);
        DateTime GetTokenExpirationDate(string token);
        XActionRequestToken ParseActionRequestToken(string token);
        #endregion
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\xIds\Interfaces\IXIdentityManager.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Net.Http;
using System.Security.Claims;
using System.Threading.Tasks;
using IdentityModel.Client;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Identity;
using Microsoft.Extensions.Logging;
using xCommons.Providers;
using xIdentityModels;
using xIdentityModels.Constants;
using xIdentityModels.Descriptors;
using xIdentityModels.Dtos;
using xIdentityModels.Models;
using xIdentityModels.Navigations;
using xIds.DbContext;
using xModels.Dtos;

namespace xIds.Interfaces
{
    public interface IXIdentityManager
    {
        XIdentityDbContext DbContext { get; }
        UserManager<XUser> UserManager { get; }
        ILogger<IXIdentityManager> Logger { get; }
        SignInManager<XUser> SignInManager { get; }
        IXSecurityProvider SecurityProvider { get; }
        RoleManager<IdentityRole> RoleManager { get; }
        XValidationProvider ValidationProvider { get; }

        //
        #region Class Getter (s) Methods ...
        IQueryable<XUser> GetUsersDbSet(
            bool containsDetail = false
        );
        IQueryable<XUser> GetUsersFullDbSet(bool enableTracking = false);
        #endregion

        //
        #region Tools ...
        string GetUserSelectByParam(
            XActionRequest model,
            bool forceNotNull = true,
            ICollection<XUserSelectBy> excludes = null
        );

        Task<XUser> ValidateUserExistsAndRetrieve(
            string userSelectByParam,
            bool containsDetail = false,
            bool checkCanLoginPolicies = false,
            bool checkIsBanned = true,
            bool ignoreDisabledUser = false,
            bool forceAdmin = false,
            Exception exception = null
        );
        #endregion

        //
        #region Default Identity Preparation Actions ...
        Task CreateIdentityRoles();
        Task CreateUserAsync(XIdentityUserDescriptor user);
        #endregion

        //
        #region Identity Actions ...
        HttpClient GetHttpClient();
        Task<IdentityModel.Client.TokenResponse> RequestScopeAccessToken(string scope);
        Task<DiscoveryDocumentResponse> RequestDiscoveryDocument();
        Task<IdentityModel.Client.TokenResponse> Authenticate(XLoginRequest model);
        Task<XLoginResponse> Login(XLoginRequest model);
        Task<XTokenResponse> RefreshTokens(XTokenResponse model);
        #endregion

        //
        #region Role Handlers ...
        Task<bool> IsRoleExistsAsync(string roleName);
        Task<IdentityResult> CreateRoleAsync(string roleName);
        Task<IdentityRole> GetRoleAsync(string roleName);
        Task<IdentityResult> AddUserToRoleAsync(XUser user, string roleName);
        Task<string> GetRoleNameAsync(string roleId);
        Task<IEnumerable<string>> GetRoleNamesAsync(
            string userSelectByParam,
            bool checkCanLoginPolicies = true,
            bool checkIsBanned = true
        );
        Task<IdentityResult> RemoveFromRoleAsync(XUser user, string roleName);
        Task<IdentityResult> RemoveFromRolesAsync(XUser user, IEnumerable<string> roleNames);
        #endregion

        //
        #region User Handlers ...
        Task<bool> CanRegister(string userSelectByParam);
        Task<bool> IsUserExistsAsync(string userSelectByParam);
        Task<XUser> GetUserAsync(
            string userSelectByParam,
            bool containsDetail = false);

        Task<IdentityResult> CreateUserAsync(
            XUser user,
            string password,
            bool checkCanLoginPolicies = true,
            bool checkIsBanned = true
        );

        Task<IdentityResult> UpdateUserAsync(
            XUser user,
            bool checkCanLoginPolicies = true,
            bool checkIsBanned = true
        );

        Task<IEnumerable<string>> GetUserNamesAsync(
            IEnumerable<string> userIds
        );

        Task<IEnumerable<XUserNameIdResponse>> GetUserNameIdsAsync(
            XUserNameIdRequest model
        );

        Task<Claim[]> ToJwtClaims(
            XUser user,
            bool checkCanLoginPolicies = true,
            bool checkIsBanned = true
        );

        Task<SignInResult> CheckPasswordSignInAsync(
            XUser user,
            string password,
            XDevice device,
            string language,
            bool lockoutOnFailure,
            bool isForced = true
        );
        #endregion

        //
        #region User Profile Handlers ...
        Task<XUserProfileDto> GetUserProfileAsync(
            string userSelectByParam,
            string requestedUserSelectByParam,
            bool forceCheckRequestedUser = true,
            bool checkCanLoginPolicies = true,
            bool checkIsBanned = true
        );

        Task<XQueryResult<XUserProfileDto>> QueryUsers(
            string requestedUserSelectByParam,
            XQuery query
        );

        Task<XQueryResult<XUserProfileDto>> QueryInRoleUsers(
            string requestedUserSelectByParam,
            string role,
            XQuery query,
            bool forceRole = false
        );

        Task<IEnumerable<XUserProfileDto>> GetUserProfilesAsync(
            ICollection<string> ids,
            string requestedUserSelectByParam,
            bool forceCheckRequestedUser = true,
            bool checkCanLoginPolicies = true,
            bool checkIsBanned = true
        );

        Task<XQueryResult<XProfileImage>> QueryAvatars(
            string userSelectByParam,
            XQuery query
        );

        Task<XUserProfileDto> ProfileUpdateAsync(
            string userSelectByParam,
            string requestedUserSelectByParam,
            XProfileUpdateRequest request
        );

        Task<XUserProfileDto> FullProfileUpdateAsync(
            string userSelectByParam,
            string requestedUserSelectByParam,
            XProfileUpdateRequest request
        );

        Task<XActionResponse> RequestConfirmMobile(
            string lang,
            XDevice device,
            string userSelectByParam,
            string password,
            string mobileNumber = null
        );

        Task<XActionResponse> RequestConfirmEmail(
            string lang,
            XDevice device,
            string userSelectByParam,
            string password,
            string emailAddress = null
        );

        Task<XActionResponse> RequestResetPassword(
            string lang,
            XDevice device,
            string userSelectByParam,
            string returnUrl
        );

        Task RequestConfirmRegistration(
            string lang,
            XDevice device,
            string userSelectByParam,
            string password,
            string returnUrl
        );

        Task ChangePassword(
            string lang,
            XDevice device,
            string userSelectByParam,
            string password,
            string newPassword,
            string returnUrl
        );

        Task ResetPassword(
            string lang,
            XDevice device,
            string actionHash,
            string newPassword,
            string returnUrl
        );

        Task<XUserProfileDto> AddAvatar(
            string userSelectByParam,
            IFormFile file
        );

        Task<XUserProfileDto> AddAvatars(
            string userSelectByParam,
            IFormFileCollection files
        );

        Task<XUserProfileDto> SetAvatar(
            string userSelectByParam,
            int profileImageId
        );

        Task<XUserProfileDto> RemoveAvatar(
            string userSelectByParam,
            ICollection<int> profileImageIds
        );

        Task ConfirmRegistration(
            string lang,
            XDevice device,
            string actionHash,
            string returnUrl
        );

        Task<XActionResponse> ConfirmMobileNumber(
            string lang,
            XDevice device,
            string registrationHash,
            string verificationCode
        );

        Task<XActionResponse> ConfirmEmailAddress(
            string lang,
            XDevice device,
            string registrationHash,
            string verificationCode
        );

        Task<bool> IsConfirmedEmail(string userSelectByParam);

        Task<bool> IsConfirmedMobile(string userSelectByParam);
        #endregion

        //
        #region Registration Handlers ...
        Task<XActionResponse> InviteUser(
            string lang,
            XDevice device,
            string email,
            string handlerUrl
        );

        Task<XActionResponse> RequestRegistration(
            string lang,
            XDevice device,
            string invitationHash,
            string firstName,
            string lastName,
            DateTime dateOfBirth,
            string mobileNumber = null,
            string emailAddress = null
        );

        Task<XActionResponse> AddAcountInfo(
            string lang,
            XDevice device,
            string registrationHash,
            string userName,
            string password
        );

        Task<XActionResponse> AttachProfileImage(
            string tokenHash,
            IFormFile file
        );

        Task FinishRegistration(
            string lang,
            XDevice device,
            string userSelectByParam,
            string password,
            string returnUrl
        );
        #endregion

        //
        #region Friendship Handlers ...
        //
        #region Actions ...
        Task<XFriendshipFollowing> Follow(
            string userSelectByParam,
            string destUserSelectByParam
        );

        Task<bool> Cancel(
            string userSelectByParam,
            string destUserSelectByParam
        );

        Task UnFollowFollower(
            string userSelectByParam,
            string destUserSelectByParam
        );

        Task UnFollowFollowing(
            string userSelectByParam,
            string destUserSelectByParam
        );

        Task<XFriendshipFollowing> Block(
            string userSelectByParam,
            string destUserSelectByParam
        );

        Task<XFriendshipFollowing> UnBlock(
            string userSelectByParam,
            string destUserSelectByParam
        );
        #endregion

        //
        #region Request Handlers ...
        Task<XFriendshipFollower> AcceptRequest(
            string userSelectByParam,
            string destUserSelectByParam
        );

        Task<XFriendshipFollower> RejectRequest(
            string userSelectByParam,
            string destUserSelectByParam
        );
        #endregion

        //
        #region Getters ...
        Task<bool> IsFollower(
            string userSelectByParam,
            string destUserSelectByParam,
            bool checkIsBanned = true,
            bool checkCanLoginPolicies = true
        );

        Task<XFriendshipState> GetFollowerState(
            string userSelectByParam,
            string destUserSelectByParam,
            bool checkIsBanned = true,
            bool checkCanLoginPolicies = true
        );

        Task<XFriendshipFollower> GetFollower(
            string userSelectByParam,
            string destUserSelectByParam
        );

        Task<IEnumerable<XFriendshipFollower>> GetFollowers(string userSelectByParam);
        Task<IEnumerable<XFriendshipFollower>> GetAllFollowers(string userSelectByParam);
        Task<ICollection<string>> GetFollowersList(string userSelectByParam);
        Task<XQueryResult<XFriendDto>> QueryFollowers(
            XQuery query,
            string userSelectByParam
        );

        Task<bool> IsFollowing(
            string userSelectByParam,
            string destUserSelectByParam,
            bool checkIsBanned = true,
            bool checkCanLoginPolicies = true
        );

        Task<XFriendshipState> GetFollowingState(
            string userSelectByParam,
            string destUserSelectByParam,
            bool checkIsBanned = true,
            bool checkCanLoginPolicies = true
        );

        Task<XFriendshipFollowing> GetFollowing(
            string userSelectByParam,
            string destUserSelectByParam
        );

        Task<IEnumerable<XFriendshipFollowing>> GetFollowings(string userSelectByParam);
        Task<IEnumerable<XFriendshipFollowing>> GetAllFollowings(string userSelectByParam);
        Task<ICollection<string>> GetFollowingList(string userSelectByParam);
        Task<XQueryResult<XFriendDto>> QueryFollowings(
            XQuery query,
            string userSelectByParam
        );
        #endregion

        //
        Task<XFriendshipInfoDto> GetFriendshipInfo(
            string userSelectByParam,
            string destUserSelectByParam,
            bool checkCanLoginPolicies = true,
            bool checkIsBanned = true
        );
        #endregion

        //
        #region Admin Actions ...
        Task<ICollection<string>> Ban(
            string userSelectByParam,
            XUserNameIdRequest model
        );

        Task<ICollection<string>> UnBan(
            string userSelectByParam,
            XUserNameIdRequest model
        );

        Task<bool> IsBanned(
            string userSelectByParam,
            string destUserSelectByParam
        );
        #endregion

        //
        #region Open Actions ...
        //
        #region OpenGet ...
        Task<XOpenActionInnerDto> OpenGet(
            XOpenActionInnerDto model
        );
        Task<XOpenActionInnerDto> OpenGet(
            string token,
            string actionRequest
        );
        #endregion

        Task<XOpenActionUserInfoDto> GetUserInfo(
            XOpenActionRequestDto dto
        );

        Task<IEnumerable<XOpenActionUserInfoDto>> GetUserInfos(
            XOpenActionRequestDto dto
        );
        #endregion

        //
        #region Search ...
        /// <summary>
        /// Query Open To Search User Profiles ...
        /// </summary>
        /// <param name="requestedUserSelectByParam">requested user's identifier</param>
        /// <param name="query">how to filter results based on <see>XQuery</see> structure</param>
        /// <returns>an instance of <see>XQueryResult</see> of <see>XUserProfileDto</see></returns>
        Task<XQueryResult<XUserProfileDto>> QueryOpenToSearchUsers(
            string requestedUserSelectByParam,
            XQuery query
        );
        #endregion

        //
        #region Query Service ...
        /// <summary>
        /// Retrieve Users as Query Model for Query Service ...
        /// </summary>
        /// <param name="requestedUserSelectByParam"></param>
        /// <param name="query"></param>
        /// <param name="role"></param>
        /// <param name="forceRole"></param>
        /// <returns></returns>
        public Task<XQueryResult<string>> QueryUsers(
            string requestedUserSelectByParam,
            XQuery query,
            string role = null,
            bool forceRole = false
        );
        #endregion
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\xIds\Interfaces\IXIdentityMessageProvider.cs

namespace xIds.Interfaces
{
    public interface IXIdentityMessageProvider
    {
        string InviteMsg { get; }
        string RegistrationApproveMsg { get; }
        string RegisteredMsg { get; }
        string VerificationCodeMsg { get; }
        string ChangePasswordMsg { get; }
        string PasswordChangedMsg { get; }
        string NewDeviceLoggedInMsg { get; }

        bool IsReady();
        void PrepareMessages(string lang);
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\xIds\Interfaces\IXSecurityProvider.cs

namespace xIds.Interfaces
{
    public interface IXSecurityProvider
    {
        string Encrypt(string plainText);
        string Decrypt(string cipherText);
        string EncryptFromBytes(byte[] textBytes);
        string DecryptFromBytes(byte[] cipherBytes);
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\xIds\Models\XDbInfo.cs

using System;
using xIds.Constants;

namespace xIds.Models
{
    public class XDbInfo
    {
        private string _migrationAssembly;
        public XDbProviders ProviderType { get; set; }
        public string MigrationsAssembly
        {
            get
            {
                return _migrationAssembly;
            }

            set
            {
                //
                _migrationAssembly = value;

                //
                OptionsBuilder = b =>
                {
                    b.MigrationsAssembly(value);
                };
            }
        }
        public Action<dynamic> OptionsBuilder { get; set; }
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\xIds\Models\XDbSeedDescriptor.cs

using System.Collections.Generic;
using IdentityServer4.Models;
using xIdentityModels.Descriptors;

namespace xIds.Models
{
    /// <summary>
    /// the resource Descriptors for Using on DbSeed
    /// </summary>
    public class XDbSeedDescriptor
    {
        public bool UpdateExists { get; set; }
        public ICollection<ApiScope> ApiScopes { get; set; }
        public ICollection<ApiResource> ApiResources { get; set; }
        public ICollection<IdentityResource> IdentityResources { get; set; }
        public ICollection<Client> Clients { get; set; }
        public ICollection<XIdentityUserDescriptor> Users { get; set; }
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\xIds\Providers\XIdentityManager\XIdentityManager+Admin.cs

using System.Collections.Generic;
using System.Threading.Tasks;
using xCommons.Extensions;
using xIdentityModels.Dtos;

namespace xIds.Providers
{
    public partial class XIdentityManager
    {
        #region Admin Actions ...
        /// <summary>
        /// Retrieve All UnBanned Users Identifiers
        /// </summary>
        /// <param name="userSelectByParam">caller user identifier</param>
        /// <returns>a collection of user identifiers</returns>
        public async Task<ICollection<string>> GetAllUnbanned(
            ICollection<string> userSelectByParam
        )
        {
            //
            var result = new List<string>();
            if (!userSelectByParam.HasChild())
            {
                return result;
            }

            //
            foreach (var uParam in userSelectByParam)
            {
                //
                var destUser = await ValidateUserExistsAndRetrieve(uParam, checkIsBanned: false);
                if (!destUser.IsBanned)
                {
                    result.Add(uParam);
                }
            }

            //
            return result;
        }

        /// <summary>
        /// Get All Banned Users Identifiers
        /// </summary>
        /// <param name="userSelectByParam">caller user identifier</param>
        /// <returns>a collection of user identifiers</returns>
        public async Task<ICollection<string>> GetAllBanned(
            ICollection<string> userSelectByParam
        )
        {
            //
            var result = new List<string>();
            if (!userSelectByParam.HasChild())
            {
                return result;
            }

            //
            foreach (var uParam in userSelectByParam)
            {
                //
                var destUser = await ValidateUserExistsAndRetrieve(uParam, checkIsBanned: false);
                if (destUser.IsBanned)
                {
                    result.Add(uParam);
                }
            }

            //
            return result;
        }

        /// <summary>
        /// Ban a Collection of Users
        /// </summary>
        /// <param name="userSelectByParam">caller user identifier</param>
        /// <param name="model">an instance of <see>XUserNameIdRequest</see> which represents user identifier list to Ban</param>
        /// <returns>a collection of user identifiers</returns>
        public async Task<ICollection<string>> Ban(
            string userSelectByParam,
            XUserNameIdRequest model
        )
        {
            //
            // Validate Args ...
            ValidationProvider.NotEmpty(userSelectByParam);
            ValidationProvider.NotNull(model);
            ValidationProvider.NotZeroChilds(model.Ids);

            //
            var user = await ValidateUserExistsAndRetrieve(
                userSelectByParam,
                forceAdmin: true,
                checkIsBanned: true,
                containDetails: false,
                ignoreDisabledUser: false,
                checkCanLoginPolicies: true
            );

            //
            var result = new List<string>();
            foreach (var uParam in model.Ids)
            {
                //
                var destUser = await ValidateUserExistsAndRetrieve(uParam, checkIsBanned: false);

                //
                var isBanned = destUser.IsBanned;
                if (!isBanned)
                {
                    //
                    destUser.IsBanned = true;

                    //
                    await UpdateUserAsync(
                        user,
                        checkCanLoginPolicies: false,
                        checkIsBanned: false
                    );

                    //
                    result.Add(destUser.Id);
                }
            }

            //
            return result;
        }

        /// <summary>
        /// UnBan a Collection of Users
        /// </summary>
        /// <param name="userSelectByParam">caller user identifier</param>
        /// <param name="model">an instance of <see>XUserNameIdRequest</see> which represents user identifier list to Ban</param>
        /// <returns>a collection of user identifiers</returns>
        public async Task<ICollection<string>> UnBan(
            string userSelectByParam,
            XUserNameIdRequest model
        )
        {
            //
            // Validate Args ...
            ValidationProvider.NotEmpty(userSelectByParam);
            ValidationProvider.NotNull(model);
            ValidationProvider.NotZeroChilds(model.Ids);

            //
            var user = await ValidateUserExistsAndRetrieve(
                userSelectByParam,
                forceAdmin: true,
                checkIsBanned: true,
                containDetails: false,
                ignoreDisabledUser: false,
                checkCanLoginPolicies: true
            );

            //
            var result = new List<string>();
            foreach (var uParam in model.Ids)
            {
                //
                var destUser = await ValidateUserExistsAndRetrieve(uParam, checkIsBanned: false);

                //
                var isBanned = destUser.IsBanned;
                if (isBanned)
                {
                    //
                    destUser.IsBanned = false;

                    //
                    await UpdateUserAsync(
                        user,
                        checkCanLoginPolicies: false,
                        checkIsBanned: false
                    );

                    //
                    result.Add(destUser.Id);
                }
            }

            //
            return result;
        }

        /// <summary>
        /// Detrmines a User is Banned or not
        /// </summary>
        /// <param name="userSelectByParam">caller user identifier</param>
        /// <param name="destUserSelectByParam">destination user identifier which checked is banned or not</param>
        /// <returns>a boolean value which represent user banned or not</returns>
        public async Task<bool> IsBanned(
            string userSelectByParam,
            string destUserSelectByParam
        )
        {
            //
            // Validate Args ...
            ValidationProvider.NotEmpty(
                userSelectByParam,
                destUserSelectByParam
            );

            //
            var user = await ValidateUserExistsAndRetrieve(
                userSelectByParam,
                forceAdmin: false,
                checkIsBanned: true,
                containDetails: false,
                ignoreDisabledUser: false,
                checkCanLoginPolicies: true
            );
            var destUser = await ValidateUserExistsAndRetrieve(destUserSelectByParam, checkIsBanned: false);

            //
            var result = destUser.IsBanned;

            //
            return result;
        }
        #endregion                
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\xIds\Providers\XIdentityManager\XIdentityManager+Device.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.EntityFrameworkCore;
using xCommons.Extensions;
using xExceptions.Constants;
using xIdentityModels;
using xIdentityModels.Extensions;
using xIdentityModels.Models;
using xIdentityModels.Navigations;
using xIds.Extensions;

namespace xIds.Providers
{
    public partial class XIdentityManager
    {
        //
        #region Device Actions ...
        /// <summary>
        /// Check a Device Exists or Not
        /// </summary>
        /// <param name="device">an instance of <see>XDevice</see></param>
        /// <returns>a boolean value</returns>
        public async Task<bool> IsDeviceExistsAsync(
            XDevice device
        )
        {
            return await DbContext.Devices
                .AnyAsync(d => d.IsSameAs(device));
        }

        /// <summary>
        /// Add new Device
        /// </summary>
        /// <param name="device">an instance of <see>XDevice</see></param>
        /// <returns>an instance of <see>XDevice</see></returns>
        public async Task<XDevice> AddDeviceAsync(
            XDevice device
        )
        {
            //
            var isDeviceExists = await IsDeviceExistsAsync(device);
            if (isDeviceExists)
            {
                return null;
            }

            //
            await DbContext.Devices
                .AddAsync(device);

            await DbContext.SaveChangesAsync();

            return device;
        }

        /// <summary>
        /// Get a Device 
        /// </summary>
        /// <param name="device">an instance of <see>XDevice</see></param>
        /// <returns>an instance of <see>XDevice</see></returns>
        public Task<XDevice> GetDeviceAsync(
            XDevice device
        )
        {
            //            
            return DbContext.Devices
                .FirstOrDefaultAsync(d =>
                    d.IsSameAs(device));
        }

        /// <summary>
        /// Retrieve a List of User Related Devices
        /// </summary>
        /// <param name="userSelectByParam">user identifier</param>
        /// <param name="checkCanLoginPolicies">check a user can log in in system or not</param>
        /// <param name="checkIsBanned">check user is banned or not</param>
        /// <returns>a collection of <see>XDevice</see> instances which related to user</returns>
        public async Task<ICollection<XDevice>> GetUserDevices(
            string userSelectByParam,
            bool checkCanLoginPolicies = true,
            bool checkIsBanned = true
        )
        {
            //
            // Validate ARgs ...
            ValidationProvider.NotEmpty(userSelectByParam);

            //
            // Validate And Retrieve User ...
            var user = await ValidateUserExistsAndRetrieve(
                userSelectByParam,
                containDetails: true,
                checkCanLoginPolicies: checkCanLoginPolicies,
                checkIsBanned: checkIsBanned
            );

            //
            // Check User Devices ...
            if (!user.Devices.HasChild())
            {
                return new List<XDevice>();
            }

            //
            return user.Devices;
        }

        /// <summary>
        /// Determines a Device is Exists in User's Devices or not 
        /// </summary>
        /// <param name="user">an instance of <see>XUser</see></param>
        /// <param name="device">an instance of <see>XDevice</see></param>
        /// <returns>a boolean value</returns>
        public bool IsDeviceRelateDToUser(
            XUser user,
            XDevice device
        )
        {
            if (!user.Devices.HasChild())
            {
                return false;
            }

            //
            var result = user.Devices.Any(d => d.IsSameAs(device));

            //
            return result;
        }

        /// <summary>
        /// Determines a Device is Exists in User's Devices or not 
        /// </summary>
        /// <param name="userSelectByParam">user identifier</param>
        /// <param name="device">an instance of <see>XDevice</see></param>
        /// <param name="checkCanLoginPolicies">check a user can log in in system or not</param>
        /// <param name="checkIsBanned">check user is banned or not</param>
        /// <returns>a boolean value</returns>
        public async Task<bool> IsDeviceRelateDToUser(
            string userSelectByParam,
            XDevice device,
            bool checkCanLoginPolicies = true,
            bool checkIsBanned = true
        )
        {
            //
            // Validate Args ...
            ValidationProvider.NotEmpty(userSelectByParam);
            ValidationProvider.NotNull(device);

            //
            var userDevices = await GetUserDevices(
                userSelectByParam,
                checkCanLoginPolicies: checkCanLoginPolicies,
                checkIsBanned: checkIsBanned
            );
            if (!userDevices.HasChild())
            {
                return false;
            }

            //
            var result = userDevices.Any(d => d.IsSameAs(device));

            //
            return result;
        }

        /// <summary>
        /// Add a Device to a User Related Devices
        /// </summary>
        /// <param name="user">an instance of <see>XUser</see></param>
        /// <param name="device">an instance of <see>XDevice</see></param>
        /// <returns>a boolean value</returns>
        public async Task<bool> AddUserRelatedDevice(
            XUser user,
            XDevice device
        )
        {
            //
            var isExists = user.Devices.Any(d =>
                d.IsSameAs(device));
            if (isExists)
            {
                return true;
            }

            //
            user.Devices.Add(device);
            try
            {
                var result = await UpdateUserAsync(user);
                return result.Succeeded;
            }
            catch
            {
                throw XException.ActionFailed.ToException();
            }
        }

        /// <summary>
        /// Add a Device to a User
        /// </summary>
        /// <param name="userSelectByParam">user identifier</param>
        /// <param name="device">an instance of <see>XDevice</see></param>
        /// <param name="checkCanLoginPolicies">check a user can log in in system or not</param>
        /// <param name="checkIsBanned">check user is banned or not</param>
        /// <returns>a boolean value</returns>
        public async Task<bool> AddUserRelatedDevice(
            string userSelectByParam,
            XDevice device,
            bool checkCanLoginPolicies = true,
            bool checkIsBanned = true
        )
        {
            //
            // Validate Args ...
            ValidationProvider.NotEmpty(userSelectByParam);
            ValidationProvider.NotNull(device);

            //
            // Check Device Related ...
            var isDeviceRelatedToUser = await IsDeviceRelateDToUser(
                userSelectByParam,
                device,
                checkCanLoginPolicies: checkCanLoginPolicies,
                checkIsBanned: checkIsBanned);
            if (isDeviceRelatedToUser)
            {
                return true;
            }

            //
            // Retrieve User ...
            var user = await ValidateUserExistsAndRetrieve(
                userSelectByParam,
                containDetails: true,
                checkCanLoginPolicies: checkCanLoginPolicies,
                checkIsBanned: checkIsBanned
            );

            //
            // Add User Device ...
            user.Devices.Add(device);

            //
            var result = await UpdateUserAsync(
                user,
                checkCanLoginPolicies: false,
                checkIsBanned: false
            );

            //
            return result.Succeeded;
        }

        /// <summary>
        /// Remove a Device from a User Related Devices List
        /// </summary>
        /// <param name="user">an instance of <see>XUser</see></param>
        /// <param name="device">an instance of <see>XDevice</see></param>
        /// <returns>a boolean value</returns>
        public async Task<bool> RemoveUserRelatedDevice(
            XUser user,
            XDevice device
        )
        {
            //
            var isRelated = IsDeviceRelateDToUser(user, device);
            if (!isRelated)
            {
                return false;
            }

            //
            var instanse = user.Devices
                .FirstOrDefault(d =>
                    d.IsSameAs(device));

            //
            user.Devices.Remove(instanse);

            //
            var result = await UpdateUserAsync(
                user,
                checkCanLoginPolicies: false,
                checkIsBanned: false
            );

            //
            return result.Succeeded;
        }

        /// <summary>
        /// Remove a Device from a User Devices 
        /// </summary>
        /// <param name="userSelectByParam">user identifier</param>
        /// <param name="device">an instance of <see>XDevice</see></param>
        /// <param name="checkCanLoginPolicies">check a user can log in in system or not</param>
        /// <param name="checkIsBanned">check user is banned or not</param>
        /// <returns>a boolean value</returns>
        public async Task<bool> RemoveUserRelatedDevice(
            string userSelectByParam,
            XDevice device,
            bool checkCanLoginPolicies = true,
            bool checkIsBanned = true
        )
        {
            //
            // Validate Args ...
            ValidationProvider.NotEmpty(userSelectByParam);
            ValidationProvider.NotNull(device);

            //
            // Validate user exists and Retrieve it based on userselectbyparam ...
            var user = await ValidateUserExistsAndRetrieve(
                userSelectByParam,
                containDetails: true,
                checkCanLoginPolicies: checkCanLoginPolicies,
                checkIsBanned: checkIsBanned
            );

            //
            return await RemoveUserRelatedDevice(
                user,
                device
            );
        }
        #endregion

        //
        #region Banned Device Actions ...
        /// <summary>
        /// Check a Device is exists in Banned Devices or not
        /// </summary>
        /// <param name="device">an instance of <see>XDevice</see></param>
        /// <returns>a boolean value</returns>
        public async Task<bool> IsBannedDeviceExists(
            XDevice device
        )
        {
            //
            var result = false;
            var bannedDeviceEnumerable = DbContext.BannedDevices.AsAsyncEnumerable();
            await
            foreach (var bannedDevice in bannedDeviceEnumerable)
            {
                //
                if (bannedDevice.Device.IsSameAs(device))
                {
                    //
                    result = true;
                    break;
                }
            }

            //
            return result;
        }

        /// <summary>
        /// Find First Banned Device
        /// </summary>
        /// <param name="device">an instance of <see>XDevice</see></param>
        /// <returns>an instance of <see>XDevice</see></returns>
        public async Task<XBannedDevice> BannedDeviceFindOne(
            XDevice device
        )
        {
            //
            var result = await DbContext.BannedDevices
                .FirstOrDefaultAsync(bd =>
                    bd.Device.IsSameAs(device)
                );

            //
            return result;
        }

        /// <summary>
        /// Remove Banned Device 
        /// </summary>
        /// <param name="model">an instance of <see>XBannedDevice</see></param>
        /// <returns></returns>
        public async Task BannedDeviceRemove(
            XBannedDevice model
        )
        {
            //
            var isExists = await IsBannedDeviceExists(model.Device);
            if (!isExists)
            {
                return;
            }

            //
            var item = await BannedDeviceFindOne(model.Device);
            if (item == null)
            {
                return;
            }

            //
            DbContext.BannedDevices.Remove(item);
            await DbContext.SaveChangesAsync();
        }

        /// <summary>
        /// Check a Device is Banned or not
        /// </summary>
        /// <param name="device">an instance of <see>XDevice</see></param>
        /// <returns>a boolean value</returns>
        private async Task<bool> IsDeviceBanned(
            XDevice device
        )
        {
            //
            var result = await IsBannedDeviceExists(device);
            return result;
        }

        /// <summary>
        /// Retrieve Specific Banned Device 
        /// </summary>
        /// <param name="device">an instance of <see>XDevice</see></param>
        /// <returns>an instance of <see>XBannedDevice</see></returns>
        private async Task<XBannedDevice> GetBannedDevice(
            XDevice device
        )
        {
            //
            var result = await BannedDeviceFindOne(device);
            return result;
        }

        /// <summary>
        /// Is a Banned Device passed Banning Time 
        /// </summary>
        /// <param name="bannedDevice">an instance of <see>XBannedDevice</see></param>
        /// <returns>a boolean value</returns>
        private bool IsDelayTimePassed(
            XBannedDevice bannedDevice
        )
        {
            //
            // Validate Args ...
            if (bannedDevice == null ||
                Configuration == null)
            {
                XException.InvalidArgs.Throw();
            }

            //
            var isPassed = bannedDevice
                .IsDelayTimePassed(Configuration.BannedDeviceTimeout);

            //
            return isPassed;
        }

        /// <summary>
        /// Retrieve Passed Time from Banning Time of specific Device
        /// </summary>
        /// <param name="bannedDevice">an instance of <see>XBannedDevice</see></param>
        /// <returns>an instance of <see>DateTime</see> which represent Passed Time</returns>
        private DateTime GetPassedTime(
            XBannedDevice bannedDevice
        )
        {
            //
            var result = bannedDevice.BannedOn
                .AddSeconds(Configuration.BannedDeviceTimeout);

            //
            return result;
        }
        #endregion
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\xIds\Providers\XIdentityManager\XIdentityManager+Friendship.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Threading.Tasks;
using xCommons.Extensions;
using xDataService.Extensions;
using xExceptions.Constants;
using xIdentityModels.Constants;
using xIdentityModels.Dtos;
using xIdentityModels.Navigations;
using xModels.Dtos;

namespace xIds.Providers
{
    public partial class XIdentityManager
    {
        //
        #region Friendship Actions ...
        //
        #region Actions ...
        /// <summary>
        /// Send a Follow Request for userSelectByParam to 
        /// destUserSelectByParam
        /// </summary>
        /// <param name="userSelectByParam">caller user identifier</param>
        /// <param name="destUserSelectByParam">dest user identifier</param>
        /// <returns>an instance of <see>XFriendshipFollowing</see></returns>
        public async Task<XFriendshipFollowing> Follow(
            string userSelectByParam,
            string destUserSelectByParam
        )
        {
            //
            // Validate Args ...
            ValidationProvider.NotEmpty(
                userSelectByParam,
                destUserSelectByParam
            );

            //
            // Validate and Retrieve User ...
            var xUser = await ValidateUserExistsAndRetrieve(
                userSelectByParam,
                forceAdmin: false,
                checkIsBanned: true,
                containDetails: true,
                ignoreDisabledUser: false,
                checkCanLoginPolicies: true
            );

            //
            // Validate and Retrieve Dest User ...
            var xDestUser = await ValidateUserExistsAndRetrieve(
                destUserSelectByParam,
                forceAdmin: false,
                checkIsBanned: true,
                containDetails: true,
                ignoreDisabledUser: false,
                checkCanLoginPolicies: true
            );

            //
            // Validate Not Same Source and Dest Users ...
            ValidateNotSameUsers(xUser, xDestUser);

            //
            XFriendshipFollowing following = null;
            XFriendshipFollower follower = null;
            var isRequested = IsFollowRequested(xUser, xDestUser);
            //
            // Check Request Happens Or not ...
            if (!isRequested)
            {
                //
                following = new XFriendshipFollowing
                {
                    UserId = xUser.Id,
                    DestId = xDestUser.Id,
                    State = XFriendshipState.Pending
                };

                //
                follower = new XFriendshipFollower
                {
                    UserId = xDestUser.Id,
                    DestId = xUser.Id,
                    State = XFriendshipState.Pending
                };

                //
                xUser.Followings.Add(following);
                xDestUser.Followers.Add(follower);
            }
            else
            {
                //
                // if Request Done Before Must Check State ...
                following = xUser.Followings.FirstOrDefault(f => f.DestId == xDestUser.Id);
                follower = xDestUser.Followers.FirstOrDefault(f => f.DestId == xUser.Id);
                if (following.IsNull() ||
                    follower.IsNull())
                {
                    XException.NotFound.Throw();
                }

                //
                switch (following.State)
                {
                    case XFriendshipState.Accepted:
                    case XFriendshipState.Blocked:
                        throw XException.NotAllowed.ToException();

                    case XFriendshipState.Rejected:
                        following.State = XFriendshipState.Pending;
                        follower.State = XFriendshipState.Pending;
                        break;
                }
            }

            //
            var canContinue = !following.IsNull() && !follower.IsNull();
            if (!canContinue)
            {
                XException.ActionFailed.Throw();
            }

            //
            await UpdateUserAsync(xUser);
            await UpdateUserAsync(xDestUser);

            //
            var result = following;

            //
            return result;
        }

        /// <summary>
        /// Cancel Following
        /// </summary>
        /// <param name="userSelectByParam">caller user identifier</param>
        /// <param name="destUserSelectByParam">dest user identifier</param>
        /// <returns>a boolean value</returns>
        public async Task<bool> Cancel(
            string userSelectByParam,
            string destUserSelectByParam
        )
        {
            //
            // Validate Args ...
            ValidationProvider.NotEmpty(
                userSelectByParam,
                destUserSelectByParam
            );

            //
            // Validate and Retrieve User ...
            var xUser = await ValidateUserExistsAndRetrieve(
                userSelectByParam,
                forceAdmin: false,
                checkIsBanned: true,
                containDetails: true,
                ignoreDisabledUser: false,
                checkCanLoginPolicies: true
            );

            //
            // Validate and Retrieve Dest User ...
            var xDestUser = await ValidateUserExistsAndRetrieve(
                destUserSelectByParam,
                forceAdmin: false,
                checkIsBanned: true,
                containDetails: true,
                ignoreDisabledUser: false,
                checkCanLoginPolicies: true
            );

            //
            // Validate Not Same Source and Dest Users ...
            ValidateNotSameUsers(xUser, xDestUser);

            //
            XFriendshipFollowing following = null;
            XFriendshipFollower follower = null;
            var isRequested = IsFollowRequested(xUser, xDestUser);
            //
            // Check Request Happens Or not ...
            if (!isRequested)
            {
                return false;
            }

            //
            // if Request Done Before Must Check State ...
            following = xUser.Followings.FirstOrDefault(f => f.DestId == xDestUser.Id);
            follower = xDestUser.Followers.FirstOrDefault(f => f.DestId == xUser.Id);
            if (following.IsNull() ||
                follower.IsNull())
            {
                XException.NotFound.Throw();
            }

            //
            switch (following.State)
            {
                case XFriendshipState.Accepted:
                case XFriendshipState.Blocked:
                    throw XException.NotAllowed.ToException();

                case XFriendshipState.Rejected:
                case XFriendshipState.Pending:
                    DbContext.Followers.Remove(follower);
                    DbContext.Followings.Remove(following);
                    break;
            }

            //
            var canContinue = !following.IsNull() && !follower.IsNull();
            if (!canContinue)
            {
                XException.ActionFailed.Throw();
            }

            //
            await DbContext.SaveChangesAsync();

            //
            return true;
        }

        /// <summary>
        /// userSelectByParam remove friendship by it's Follower
        /// destUserSelectByParam
        /// </summary>
        /// <param name="userSelectByParam">caller user identifier</param>
        /// <param name="destUserSelectByParam">dest user identifier</param>
        /// <returns></returns>
        public async Task UnFollowFollower(
            string userSelectByParam,
            string destUserSelectByParam
        )
        {
            //
            // Validate Args ...
            ValidationProvider.NotEmpty(
                userSelectByParam,
                destUserSelectByParam
            );

            //
            // Validate and Retrieve User ...
            var xUser = await ValidateUserExistsAndRetrieve(
                userSelectByParam,
                forceAdmin: false,
                checkIsBanned: true,
                containDetails: true,
                ignoreDisabledUser: false,
                checkCanLoginPolicies: true
            );

            //
            // Validate and Retrieve Dest User ...
            var xDestUser = await ValidateUserExistsAndRetrieve(
                destUserSelectByParam,
                forceAdmin: false,
                checkIsBanned: true,
                containDetails: true,
                ignoreDisabledUser: false,
                checkCanLoginPolicies: true
            );

            //
            // Validate Not Same Source and Dest Users ...
            ValidateNotSameUsers(xUser, xDestUser);
            ValidateIsFollowers(xUser, xDestUser);

            //
            var follower = xUser.Followers
                .FirstOrDefault(f =>
                    f.DestId == xDestUser.Id &&
                    f.State == XFriendshipState.Accepted);
            var following = xDestUser.Followings
                .FirstOrDefault(f =>
                    f.DestId == xUser.Id &&
                    f.State == XFriendshipState.Accepted);
            if (follower.IsNull() ||
                following.IsNull())
            {
                XException.NotFound.Throw();
            }

            //
            DbContext.Followers.Remove(follower);
            DbContext.Followings.Remove(following);

            //
            await DbContext.SaveChangesAsync();
        }

        /// <summary>
        /// userSelectByParam remove friendship by it's Followings
        /// destUserSelectByParam
        /// </summary>
        /// <param name="userSelectByParam">caller user identifier</param>
        /// <param name="destUserSelectByParam">dest user identifier</param>
        /// <returns></returns>
        public async Task UnFollowFollowing(
            string userSelectByParam,
            string destUserSelectByParam
        )
        {
            //
            // Validate Args ...
            ValidationProvider.NotEmpty(
                userSelectByParam,
                destUserSelectByParam
            );

            //
            // Validate and Retrieve User ...
            var xUser = await ValidateUserExistsAndRetrieve(
                userSelectByParam,
                forceAdmin: false,
                checkIsBanned: true,
                containDetails: true,
                ignoreDisabledUser: false,
                checkCanLoginPolicies: true
            );

            //
            // Validate and Retrieve Dest User ...
            var xDestUser = await ValidateUserExistsAndRetrieve(
                destUserSelectByParam,
                forceAdmin: false,
                checkIsBanned: true,
                containDetails: true,
                ignoreDisabledUser: false,
                checkCanLoginPolicies: true
            );

            //
            // Validate Not Same Source and Dest Users ...
            ValidateNotSameUsers(xUser, xDestUser);
            ValidateIsFollowings(xUser, xDestUser);

            //
            var following = xUser.Followings
                .FirstOrDefault(f =>
                    f.DestId == xDestUser.Id &&
                    f.State == XFriendshipState.Accepted);
            var follower = xDestUser.Followers
                .FirstOrDefault(f =>
                    f.DestId == xUser.Id &&
                    f.State == XFriendshipState.Accepted);
            if (follower.IsNull() ||
                following.IsNull())
            {
                XException.NotAllowed.Throw();
            }

            //
            DbContext.Followers.Remove(follower);
            DbContext.Followings.Remove(following);

            //
            await DbContext.SaveChangesAsync();
        }

        /// <summary>
        /// userSelectByParam Block it's follower destUserSelectByParam
        /// </summary>
        /// <param name="userSelectByParam">caller user identifier</param>
        /// <param name="destUserSelectByParam">dest user identifier</param>
        /// <returns>an instance of <see>XFriendshipFollowing</see></returns>
        public async Task<XFriendshipFollowing> Block(
            string userSelectByParam,
            string destUserSelectByParam
        )
        {
            //
            // Validate Args ...
            ValidationProvider.NotEmpty(
                userSelectByParam,
                destUserSelectByParam
            );

            //
            // Validate and Retrieve User ...
            var xUser = await ValidateUserExistsAndRetrieve(
                userSelectByParam,
                forceAdmin: false,
                checkIsBanned: true,
                containDetails: true,
                ignoreDisabledUser: false,
                checkCanLoginPolicies: true
            );

            //
            // Validate and Retrieve Dest User ...
            var xDestUser = await ValidateUserExistsAndRetrieve(
                destUserSelectByParam,
                forceAdmin: false,
                checkIsBanned: true,
                containDetails: true,
                ignoreDisabledUser: false,
                checkCanLoginPolicies: true
            );

            //
            // Validate Not Same Source and Dest Users ...
            ValidateNotSameUsers(xUser, xDestUser);

            //
            // Validate XDestUser is Accepted Follower of XUser ...
            ValidateIsFollowers(xUser, xDestUser);

            //
            // Retrieve FriendShip Models ...
            var following = xDestUser.Followings
                .FirstOrDefault(f =>
                    f.DestId == xUser.Id &&
                    (
                        f.State == XFriendshipState.Accepted
                    )
                );
            var follower = xUser.Followers
                .FirstOrDefault(f =>
                    f.DestId == xDestUser.Id &&
                    (
                        f.State == XFriendshipState.Accepted
                    )
                );
            if (following.IsNull() ||
                follower.IsNull())
            {
                XException.NotAllowed.Throw();
            }

            //
            follower.State = XFriendshipState.Blocked;
            following.State = XFriendshipState.Blocked;

            //
            DbContext.Followers.Update(follower);
            DbContext.Followings.Update(following);

            //
            await DbContext.SaveChangesAsync();

            //
            var result = following;

            //
            return result;
        }

        /// <summary>
        /// userSelectByParam UnBlock it's follower destUserSelectByParam
        /// </summary>
        /// <param name="userSelectByParam">caller user identifier</param>
        /// <param name="destUserSelectByParam">dest user identifier</param>
        /// <returns>an instance of <see>XFriendshipFollowing</see></returns>
        public async Task<XFriendshipFollowing> UnBlock(
            string userSelectByParam,
            string destUserSelectByParam
        )
        {
            //
            // Validate Args ...
            ValidationProvider.NotEmpty(
                userSelectByParam,
                destUserSelectByParam
            );

            //
            // Validate and Retrieve User ...
            var xUser = await ValidateUserExistsAndRetrieve(
                userSelectByParam,
                forceAdmin: false,
                checkIsBanned: true,
                containDetails: true,
                ignoreDisabledUser: false,
                checkCanLoginPolicies: true
            );

            //
            // Validate and Retrieve Dest User ...
            var xDestUser = await ValidateUserExistsAndRetrieve(
                destUserSelectByParam,
                forceAdmin: false,
                checkIsBanned: true,
                containDetails: true,
                ignoreDisabledUser: false,
                checkCanLoginPolicies: true
            );

            //
            // Validate Not Same Source and Dest Users ...
            ValidateNotSameUsers(xUser, xDestUser);

            //
            // Validate XDestUser is Accepted Follower of XUser ...
            ValidateIsBlock(xUser, xDestUser);

            //
            // Retrieve FriendShip Models ...
            var following = xDestUser.Followings
                .FirstOrDefault(f =>
                    f.DestId == xUser.Id &&
                    (
                        f.State == XFriendshipState.Blocked
                    )
                );
            var follower = xUser.Followers
                .FirstOrDefault(f =>
                    f.DestId == xDestUser.Id &&
                    (
                        f.State == XFriendshipState.Blocked
                    )
                );
            if (
                following.IsNull() ||
                follower.IsNull()
            )
            {
                XException.NotAllowed.Throw();
            }

            //
            follower.State = XFriendshipState.Accepted;
            following.State = XFriendshipState.Accepted;

            //
            DbContext.Followers.Update(follower);
            DbContext.Followings.Update(following);

            //
            await DbContext.SaveChangesAsync();

            //
            var result = following;

            //
            return result;
        }
        #endregion

        //
        #region Request Handlers ...
        /// <summary>
        /// userSelectByParam Accept Follow Request of
        /// destUserSelectByParam
        /// </summary>
        /// <param name="userSelectByParam">caller user identifier</param>
        /// <param name="destUserSelectByParam">dest user identifier</param>
        /// <returns>an instance of <see>XFriendshipFollower</see></returns>
        public async Task<XFriendshipFollower> AcceptRequest(
            string userSelectByParam,
            string destUserSelectByParam
        )
        {
            //
            // Validate Args ...
            ValidationProvider.NotEmpty(
                userSelectByParam,
                destUserSelectByParam
            );

            //
            // Validate and Retrieve User ...
            var xUser = await ValidateUserExistsAndRetrieve(
                userSelectByParam,
                forceAdmin: false,
                checkIsBanned: true,
                containDetails: true,
                ignoreDisabledUser: false,
                checkCanLoginPolicies: true
            );

            //
            // Validate and Retrieve Dest User ...
            var xDestUser = await ValidateUserExistsAndRetrieve(
                destUserSelectByParam,
                forceAdmin: false,
                checkIsBanned: true,
                containDetails: true,
                ignoreDisabledUser: false,
                checkCanLoginPolicies: true
            );

            //
            // Validate Not Same Source and Dest Users ...
            ValidateNotSameUsers(xUser, xDestUser);

            //
            // Validate Request Sent and in Pending State ...
            ValidateFollowingRequestForAccept(xUser, xDestUser);

            //
            // Retrieve FriendShip Models ...
            var following = xDestUser.Followings
                .FirstOrDefault(f =>
                    f.DestId == xUser.Id &&
                    (
                        f.State == XFriendshipState.Pending ||
                        f.State == XFriendshipState.Rejected
                    )
                );
            var follower = xUser.Followers
                .FirstOrDefault(f =>
                    f.DestId == xDestUser.Id &&
                    (
                        f.State == XFriendshipState.Pending ||
                        f.State == XFriendshipState.Rejected
                    )
                );
            if (following.IsNull() ||
                follower.IsNull())
            {
                XException.NotAllowed.Throw();
            }

            //
            follower.State = XFriendshipState.Accepted;
            following.State = XFriendshipState.Accepted;

            //
            await UpdateUserAsync(xUser);
            await UpdateUserAsync(xDestUser);

            //
            var result = follower;

            //
            return result;
        }

        /// <summary>
        /// Reject a Follow Request of destUserSelectByParam
        /// with userSelectByParam
        /// </summary>
        /// <param name="userSelectByParam">caller user identifier</param>
        /// <param name="destUserSelectByParam">dest user identifier</param>
        /// <returns>an instance of <see>XFriendshipFollower</see></returns>
        public async Task<XFriendshipFollower> RejectRequest(
            string userSelectByParam,
            string destUserSelectByParam
        )
        {
            //
            // Validate Args ...
            ValidationProvider.NotEmpty(
                userSelectByParam,
                destUserSelectByParam
            );

            //
            // Validate and Retrieve User ...
            var xUser = await ValidateUserExistsAndRetrieve(
                userSelectByParam,
                forceAdmin: false,
                checkIsBanned: true,
                containDetails: true,
                ignoreDisabledUser: false,
                checkCanLoginPolicies: true
            );

            //
            // Validate and Retrieve Dest User ...
            var xDestUser = await ValidateUserExistsAndRetrieve(
                destUserSelectByParam,
                forceAdmin: false,
                checkIsBanned: true,
                containDetails: true,
                ignoreDisabledUser: false,
                checkCanLoginPolicies: true
            );

            //
            // Validate Not Same Source and Dest Users ...
            ValidateNotSameUsers(xUser, xDestUser);

            //
            // Validate Request Sent and in Pending State ...
            ValidateFollowingRequest(xUser, xDestUser);

            //
            // Retrieve Pending Specified User Request Friendship models ...
            var following = xDestUser.Followings
                .FirstOrDefault(f =>
                    f.DestId == xUser.Id &&
                    f.State == XFriendshipState.Pending);
            var follower = xUser.Followers
                .FirstOrDefault(f =>
                    f.DestId == xDestUser.Id &&
                    f.State == XFriendshipState.Pending);
            if (following.IsNull() ||
                follower.IsNull())
            {
                XException.NotFound.Throw();
            }

            //
            follower.State = XFriendshipState.Rejected;
            following.State = XFriendshipState.Rejected;

            //
            DbContext.Followers.Update(follower);
            DbContext.Followings.Update(following);

            //
            await DbContext.SaveChangesAsync();

            //
            var result = follower;

            //
            return result;
        }
        #endregion

        //
        #region Getters ...
        /// <summary>
        /// determines destUserSelectByParam is in followers of
        /// userSelectByParam or not
        /// </summary>
        /// <param name="userSelectByParam">caller user identifier</param>
        /// <param name="destUserSelectByParam">dest user identifier</param>
        /// <param name="checkIsBanned">check user is banned or not, default is true</param>
        /// <param name="checkCanLoginPolicies">check a user can log in in system or not, default is true</param>
        /// <returns>a boolean value</returns>
        public async Task<bool> IsFollower(
            string userSelectByParam,
            string destUserSelectByParam,
            bool checkIsBanned = true,
            bool checkCanLoginPolicies = true
        )
        {
            //
            // Validate Args ...
            ValidationProvider.NotEmpty(
                userSelectByParam,
                destUserSelectByParam
            );

            //
            // Validate and Retrieve User ...
            var xUser = await ValidateUserExistsAndRetrieve(
                userSelectByParam,
                forceAdmin: false,
                containDetails: true,
                ignoreDisabledUser: false,
                checkIsBanned: checkIsBanned,
                checkCanLoginPolicies: checkCanLoginPolicies
            );

            //
            // Validate and Retrieve Dest User ...
            var xDestUser = await ValidateUserExistsAndRetrieve(
                destUserSelectByParam,
                forceAdmin: false,
                containDetails: true,
                ignoreDisabledUser: false,
                checkIsBanned: checkIsBanned,
                checkCanLoginPolicies: checkCanLoginPolicies
            );

            //
            // Validate Not Same Source and Dest Users ...
            ValidateNotSameUsers(xUser, xDestUser);

            //
            var result = IsFollowRequested(xDestUser, xUser, XFriendshipState.Accepted);

            //
            return result;
        }

        /// <summary>
        /// retrieve Friendship state of destUserSelectByParam
        /// in Followers of userSelectByParam
        /// </summary>
        /// <param name="userSelectByParam">caller user identifier</param>
        /// <param name="destUserSelectByParam">dest user identifier</param>
        /// <param name="checkIsBanned">check user is banned or not, default is true</param>
        /// <param name="checkCanLoginPolicies">check a user can log in in system or not, default is true</param>
        /// <returns>a member of <see>XFriendshipState</see></returns>
        public async Task<XFriendshipState> GetFollowerState(
            string userSelectByParam,
            string destUserSelectByParam,
            bool checkIsBanned = true,
            bool checkCanLoginPolicies = true
        )
        {
            //
            // Validate Args ...
            ValidationProvider.NotEmpty(
                userSelectByParam,
                destUserSelectByParam
            );

            //
            // Validate and Retrieve User ...
            var xUser = await ValidateUserExistsAndRetrieve(
                userSelectByParam,
                forceAdmin: false,
                containDetails: true,
                ignoreDisabledUser: false,
                checkIsBanned: checkIsBanned,
                checkCanLoginPolicies: checkCanLoginPolicies
            );

            //
            // Validate and Retrieve Dest User ...
            var xDestUser = await ValidateUserExistsAndRetrieve(
                destUserSelectByParam,
                forceAdmin: false,
                containDetails: true,
                ignoreDisabledUser: false,
                checkIsBanned: checkIsBanned,
                checkCanLoginPolicies: checkCanLoginPolicies
            );

            //
            // Validate Not Same Source and Dest Users ...
            ValidateNotSameUsers(xUser, xDestUser);

            //
            var isFollow = IsFollowRequested(xDestUser, xUser);
            if (!isFollow)
            {
                return XFriendshipState.None;
            }

            //
            var follower = xUser.Followers.FirstOrDefault(f => f.DestId == xDestUser.Id);
            if (follower.IsNull())
            {
                XException.NotFound.Throw();
            }

            //
            return follower.State;
        }

        /// <summary>
        /// get follower friendship model of destUserSelectByParam
        /// in followers of userSelectByParam
        /// </summary>
        /// <param name="userSelectByParam">caller user identifier</param>
        /// <param name="destUserSelectByParam">dest user identifier</param>
        /// <returns>an instance of <see>XFriendshipFollower</see></returns>
        public async Task<XFriendshipFollower> GetFollower(
            string userSelectByParam,
            string destUserSelectByParam
        )
        {
            //
            // Validate Args ...
            ValidationProvider.NotEmpty(
                userSelectByParam,
                destUserSelectByParam
            );

            //
            // Validate and Retrieve User ...
            var xUser = await ValidateUserExistsAndRetrieve(
                userSelectByParam,
                forceAdmin: false,
                checkIsBanned: true,
                containDetails: true,
                ignoreDisabledUser: false,
                checkCanLoginPolicies: true
            );

            //
            // Validate and Retrieve Dest User ...
            var xDestUser = await ValidateUserExistsAndRetrieve(
                destUserSelectByParam,
                forceAdmin: false,
                checkIsBanned: true,
                containDetails: true,
                ignoreDisabledUser: false,
                checkCanLoginPolicies: true
            );

            //
            // Validate Not Same Source and Dest Users ...
            ValidateNotSameUsers(xUser, xDestUser);

            //
            var isFollow = IsFollowRequested(xDestUser, xUser);
            if (!isFollow)
            {
                return null;
            }

            //
            var follower = xUser.Followers
                .FirstOrDefault(f => f.DestId == xDestUser.Id);
            if (follower.IsNull())
            {
                XException.NotFound.Throw();
            }

            //
            var result = follower;

            //
            return result;
        }

        /// <summary>
        /// Retrieve Accepted Followers list of userSelectByParam
        /// </summary>
        /// <param name="userSelectByParam">caller user identifier</param>
        /// <returns>a collection of <see>XFriendshipFollower</see> instances</returns>
        public async Task<IEnumerable<XFriendshipFollower>> GetFollowers(
            string userSelectByParam
        )
        {
            //
            // Validate Args ...
            ValidationProvider.NotEmpty(userSelectByParam);

            //
            // Validate and Retrieve User ...
            var xUser = await ValidateUserExistsAndRetrieve(
                userSelectByParam,
                forceAdmin: false,
                checkIsBanned: true,
                containDetails: true,
                ignoreDisabledUser: false,
                checkCanLoginPolicies: true
            );

            //
            var result = xUser.Followers
                .Where(f => f.State == XFriendshipState.Accepted);

            //
            return result;
        }

        /// <summary>
        /// Retrieve all Followers list of userSelectByParam
        /// </summary>
        /// <param name="userSelectByParam">caller user identifier</param>
        /// <returns>a collection of <see>XFriendshipFollower</see> instances</returns>
        public async Task<IEnumerable<XFriendshipFollower>> GetAllFollowers(
            string userSelectByParam
        )
        {
            //
            // Validate Args ...
            ValidationProvider.NotEmpty(userSelectByParam);

            //
            // Validate and Retrieve User ...
            var xUser = await ValidateUserExistsAndRetrieve(
                userSelectByParam,
                forceAdmin: false,
                checkIsBanned: true,
                containDetails: true,
                ignoreDisabledUser: false,
                checkCanLoginPolicies: true
            );

            //
            var result = xUser.Followers;

            //
            return result;
        }

        /// <summary>
        /// Read Specified User's Follower's List based on Query Model ...
        /// </summary>
        /// <param name="query"></param>
        /// <param name="userSelectByParam"></param>
        /// <returns></returns>
        public async Task<XQueryResult<XFriendDto>> QueryFollowers(
            XQuery query,
            string userSelectByParam
        )
        {
            //
            // Validate Args ...
            ValidationProvider.NotNull(query);
            ValidationProvider.NotEmpty(userSelectByParam);

            //
            // Validate and Retrieve User ...
            var xUser = await ValidateUserExistsAndRetrieve(
                userSelectByParam,
                forceAdmin: false,
                checkIsBanned: false,
                containDetails: false,
                ignoreDisabledUser: false,
                checkCanLoginPolicies: false
            );

            //
            // Prepare Query ...

            //
            if (query.PageSize < DataConfiguration
                .PagingConfiguration
                .MinAvailablePageSize)
            {
                //
                query.PageSize = DataConfiguration
                    .PagingConfiguration
                    .DefaultPageSize;
            }

            //
            if (query.PageSize > DataConfiguration
                .PagingConfiguration
                .MaxAvailablePageSize)
            {
                //
                query.PageSize = DataConfiguration
                    .PagingConfiguration
                    .MaxAvailablePageSize;
            }

            //
            // Prepare Enumerator ...
            Expression<Func<XFriendshipFollower, bool>> whereClause = x => x.UserId == xUser.Id;
            var enumerator = DbContext.Followers.AsAsyncEnumerable();
            var resultItems = new List<XFriendDto>();
            await foreach (var entity in enumerator)
            {
                //
                var isApproved = whereClause.Compile()(entity);
                if (isApproved)
                {
                    //
                    // Convert Approved Entity to Dto ...
                    // then Validate it and Add it to Results ...
                    var dto = await ToDto(entity);
                    if (!dto.IsNull())
                    {
                        resultItems.Add(dto);
                    }
                }
            }

            //
            // Enumerable ...
            var result = resultItems.AsEnumerable();

            //
            // Count Total Items ...
            var totalItemsCount = result.Count();

            //
            // Apply Filter ...
            if (!query.Filter.IsNullOrEmpty())
            {
                result = result.ApplyFilter(query.Filter);
            }

            //
            // Count Filtered Items ...
            var totalFilteredItemsCount = result.Count();

            //
            // Apply Paging ...
            if (totalItemsCount > 0 &&
                totalFilteredItemsCount > 0)
            {
                //
                // Apply Sorting ...
                if (!query.SortBy.IsNullOrEmpty())
                {
                    //
                    // Since Sorting Based on Date is Very Important ...
                    // we have to do Sorting at first Time then 
                    // try to apply Paging ...
                    result = result
                        .ApplySorting(
                            query.SortBy,
                            query.IsAscending)
                        .ToList();
                }

                //
                // Apply Paging ...
                result = result
                    .ApplyPaging(
                        query.Page,
                        query.PageSize)
                    .ToList();
            }

            //
            // Calculating Page Count ...
            int pagesCount = totalItemsCount / query.PageSize;
            if (totalItemsCount % query.PageSize > 0)
            {
                pagesCount++;
            }

            //
            // Generate Result Object ...
            var queryResult = new XQueryResult<XFriendDto>
            {
                Page = query.Page,
                TotalPages = pagesCount,
                PageSize = query.PageSize,
                TotalItems = totalItemsCount,
                Items = result.AsEnumerable(),
                TotalFilteredItems = totalFilteredItemsCount
            };

            //
            return queryResult;
        }

        /// <summary>
        /// determines destUserSelectByParam is in followings of
        /// userSelectByParam or not
        /// </summary>
        /// <param name="userSelectByParam">caller user identifier</param>
        /// <param name="destUserSelectByParam">dest user identifier</param>
        /// <param name="checkIsBanned">check user is banned or not, default is true</param>
        /// <param name="checkCanLoginPolicies">check a user can log in in system or not, default is true</param>
        /// <returns>a boolean value</returns>
        public async Task<bool> IsFollowing(
            string userSelectByParam,
            string destUserSelectByParam,
            bool checkIsBanned = true,
            bool checkCanLoginPolicies = true
        )
        {
            //
            // Validate Args ...
            ValidationProvider.NotEmpty(
                userSelectByParam,
                destUserSelectByParam
            );

            //
            // Validate and Retrieve User ...
            var xUser = await ValidateUserExistsAndRetrieve(
                userSelectByParam,
                forceAdmin: false,
                containDetails: true,
                ignoreDisabledUser: false,
                checkIsBanned: checkIsBanned,
                checkCanLoginPolicies: checkCanLoginPolicies
            );

            //
            // Validate and Retrieve Dest User ...
            var xDestUser = await ValidateUserExistsAndRetrieve(
                destUserSelectByParam,
                forceAdmin: false,
                containDetails: true,
                ignoreDisabledUser: false,
                checkIsBanned: checkIsBanned,
                checkCanLoginPolicies: checkCanLoginPolicies
            );

            //
            // Validate Not Same Source and Dest Users ...
            ValidateNotSameUsers(xUser, xDestUser);

            //
            var result = IsFollowRequested(xUser, xDestUser, XFriendshipState.Accepted);

            //
            return result;
        }

        /// <summary>
        /// retrieve Frindship State of destUserSelectByParam
        /// in Followings of userSelectByParam
        /// </summary>
        /// <param name="userSelectByParam">caller user identifier</param>
        /// <param name="destUserSelectByParam">dest user identifier</param>
        /// <param name="checkIsBanned">check user is banned or not, default is true</param>
        /// <param name="checkCanLoginPolicies">check a user can log in in system or not, default is true</param>
        /// <returns>a member of <see>XFriendshipState</see></returns>
        public async Task<XFriendshipState> GetFollowingState(
            string userSelectByParam,
            string destUserSelectByParam,
            bool checkIsBanned = true,
            bool checkCanLoginPolicies = true
        )
        {
            //
            // Validate Args ...
            ValidationProvider.NotEmpty(
                userSelectByParam,
                destUserSelectByParam
            );

            //
            // Validate and Retrieve User ...
            var xUser = await ValidateUserExistsAndRetrieve(
                userSelectByParam,
                forceAdmin: false,
                containDetails: true,
                ignoreDisabledUser: false,
                checkIsBanned: checkIsBanned,
                checkCanLoginPolicies: checkCanLoginPolicies
            );

            //
            // Validate and Retrieve Dest User ...
            var xDestUser = await ValidateUserExistsAndRetrieve(
                destUserSelectByParam,
                forceAdmin: false,
                containDetails: true,
                ignoreDisabledUser: false,
                checkIsBanned: checkIsBanned,
                checkCanLoginPolicies: checkCanLoginPolicies
            );

            //
            // Validate Not Same Source and Dest Users ...
            ValidateNotSameUsers(xUser, xDestUser);

            //
            var isFollow = IsFollowRequested(xUser, xDestUser);
            if (!isFollow)
            {
                return XFriendshipState.None;
            }

            //
            var following = xUser.Followings.FirstOrDefault(f => f.DestId == xDestUser.Id);
            if (following.IsNull())
            {
                XException.NotFound.Throw();
            }

            //
            return following.State;
        }

        /// <summary>
        /// get following friendship model of destUserSelectByParam
        /// in followings of userSelectByParam
        /// </summary>
        /// <param name="userSelectByParam">caller user identifier</param>
        /// <param name="destUserSelectByParam">dest user identifier</param>
        /// <returns>an instance of <see>XFriendshipFollowing</see></returns>
        public async Task<XFriendshipFollowing> GetFollowing(
            string userSelectByParam,
            string destUserSelectByParam
        )
        {
            //
            // Validate Args ...
            ValidationProvider.NotEmpty(
                userSelectByParam,
                destUserSelectByParam
            );

            //
            // Validate and Retrieve User ...
            var xUser = await ValidateUserExistsAndRetrieve(
                userSelectByParam,
                forceAdmin: false,
                checkIsBanned: true,
                containDetails: true,
                ignoreDisabledUser: false,
                checkCanLoginPolicies: true
            );

            //
            // Validate and Retrieve Dest User ...
            var xDestUser = await ValidateUserExistsAndRetrieve(
                destUserSelectByParam,
                forceAdmin: false,
                checkIsBanned: true,
                containDetails: true,
                ignoreDisabledUser: false,
                checkCanLoginPolicies: true
            );

            //
            // Validate Not Same Source and Dest Users ...
            ValidateNotSameUsers(xUser, xDestUser);

            //
            var isFollow = IsFollowRequested(xUser, xDestUser);
            if (!isFollow)
            {
                return null;
            }

            //
            var following = xUser.Followings.FirstOrDefault(f => f.DestId == xDestUser.Id);
            if (following.IsNull())
            {
                XException.NotFound.Throw();
            }

            //
            var result = following;

            //
            return result;
        }

        /// <summary>
        /// Retrieve accepted Followings List of userSelectByParam
        /// </summary>
        /// <param name="userSelectByParam">caller user identifier</param>
        /// <returns>a collection of <see>XFriendshipFollowing</see> instances</returns>
        public async Task<IEnumerable<XFriendshipFollowing>> GetFollowings(
            string userSelectByParam
        )
        {
            //
            // Validate Args ...
            ValidationProvider.NotEmpty(userSelectByParam);

            //
            // Validate and Retrieve User ...
            var xUser = await ValidateUserExistsAndRetrieve(
                userSelectByParam,
                forceAdmin: false,
                checkIsBanned: true,
                containDetails: true,
                ignoreDisabledUser: false,
                checkCanLoginPolicies: true
            );

            //
            var result = xUser.Followings
                .Where(f => f.State == XFriendshipState.Accepted);

            //
            return result;
        }

        /// <summary>
        /// Retrieve all Followings List of userSelectByParam
        /// </summary>
        /// <param name="userSelectByParam">caller user identifier</param>
        /// <returns>a collection of <see>XFriendshipFollowing</see> instances</returns>
        public async Task<IEnumerable<XFriendshipFollowing>> GetAllFollowings(string userSelectByParam)
        {
            //
            // Validate Args ...
            ValidationProvider.NotEmpty(userSelectByParam);

            //
            // Validate and Retrieve User ...
            var xUser = await ValidateUserExistsAndRetrieve(
                userSelectByParam,
                forceAdmin: false,
                checkIsBanned: true,
                containDetails: true,
                ignoreDisabledUser: false,
                checkCanLoginPolicies: true
            );

            //
            var result = xUser.Followings;

            //
            return result;
        }

        /// <summary>
        /// Read Specified User's Following's List based on Query Model ...
        /// </summary>
        /// <param name="query"></param>
        /// <param name="userSelectByParam"></param>
        /// <returns></returns>
        public async Task<XQueryResult<XFriendDto>> QueryFollowings(
            XQuery query,
            string userSelectByParam
        )
        {
            //
            // Validate Args ...
            ValidationProvider.NotNull(query);
            ValidationProvider.NotEmpty(userSelectByParam);

            //
            // Validate and Retrieve User ...
            var xUser = await ValidateUserExistsAndRetrieve(
                userSelectByParam,
                forceAdmin: false,
                checkIsBanned: false,
                containDetails: false,
                ignoreDisabledUser: false,
                checkCanLoginPolicies: false
            );

            //
            // Prepare Query ...

            //
            if (query.PageSize < DataConfiguration
                .PagingConfiguration
                .MinAvailablePageSize)
            {
                //
                query.PageSize = DataConfiguration
                    .PagingConfiguration
                    .DefaultPageSize;
            }

            //
            if (query.PageSize > DataConfiguration
                .PagingConfiguration
                .MaxAvailablePageSize)
            {
                //
                query.PageSize = DataConfiguration
                    .PagingConfiguration
                    .MaxAvailablePageSize;
            }

            //
            // Prepare Enumerator ...
            Expression<Func<XFriendshipFollowing, bool>> whereClause = x => x.UserId == xUser.Id;
            var enumerator = DbContext.Followings.AsAsyncEnumerable();
            var resultItems = new List<XFriendDto>();
            await foreach (var entity in enumerator)
            {
                //
                var isApproved = whereClause.Compile()(entity);
                if (isApproved)
                {
                    //
                    // Convert Approved Entity to Dto ...
                    // then Validate it and Add it to Results ...
                    var dto = await ToDto(entity);
                    if (!dto.IsNull())
                    {
                        resultItems.Add(dto);
                    }
                }
            }

            //
            // Enumerable ...
            var result = resultItems.AsEnumerable();

            //
            // Count Total Items ...
            var totalItemsCount = result.Count();

            //
            // Apply Filter ...
            if (!query.Filter.IsNullOrEmpty())
            {
                result = result.ApplyFilter(query.Filter);
            }

            //
            // Count Filtered Items ...
            var totalFilteredItemsCount = result.Count();

            //
            // Apply Paging ...
            if (totalItemsCount > 0 &&
                totalFilteredItemsCount > 0)
            {
                //
                // Apply Sorting ...
                if (!query.SortBy.IsNullOrEmpty())
                {
                    //
                    // Since Sorting Based on Date is Very Important ...
                    // we have to do Sorting at first Time then 
                    // try to apply Paging ...
                    result = result
                        .ApplySorting(
                            query.SortBy,
                            query.IsAscending)
                        .ToList();
                }

                //
                // Apply Paging ...
                result = result
                    .ApplyPaging(
                        query.Page,
                        query.PageSize)
                    .ToList();
            }

            //
            // Calculating Page Count ...
            int pagesCount = totalItemsCount / query.PageSize;
            if (totalItemsCount % query.PageSize > 0)
            {
                pagesCount++;
            }

            //
            // Generate Result Object ...
            var queryResult = new XQueryResult<XFriendDto>
            {
                Page = query.Page,
                TotalPages = pagesCount,
                PageSize = query.PageSize,
                TotalItems = totalItemsCount,
                Items = result.AsEnumerable(),
                TotalFilteredItems = totalFilteredItemsCount
            };

            //
            return queryResult;
        }
        #endregion

        //
        #region Others ...
        /// <summary>
        /// Retrieve List Of All Followings User Id's
        /// of userSelectByParam
        /// </summary>
        /// <param name="userSelectByParam">caller user identifier</param>
        /// <returns>a collection of user identifiers</returns>
        public async Task<ICollection<string>> GetFollowingList(
            string userSelectByParam
        )
        {
            //
            // Validate Args ...
            ValidationProvider.NotEmpty(userSelectByParam);

            //
            // Validate and Retrieve followings List ...
            var followings = await GetFollowings(userSelectByParam);

            //
            var result = followings.Select(f => f.DestId);

            //
            return result.ToList();
        }

        /// <summary>
        /// Retrieve List Of All Followers User Id's
        /// of userSelectByParam
        /// </summary>
        /// <param name="userSelectByParam">caller user identifier</param>
        /// <returns>a collection of user identifiers</returns>
        public async Task<ICollection<string>> GetFollowersList(
            string userSelectByParam
        )
        {
            //
            // Validate Args ...
            ValidationProvider.NotEmpty(userSelectByParam);

            //
            // Validate and Retrieve followings List ...
            var followers = await GetFollowers(userSelectByParam);

            //
            var result = followers.Select(f => f.DestId);

            //
            return result.ToList();
        }

        /// <summary>
        /// retrieve Friendship Info Model for Specific User
        /// </summary>
        /// <param name="userSelectByParam">caller user identifier</param>
        /// <param name="destUserSelectByParam">dest user identifier</param>
        /// <param name="checkCanLoginPolicies">check a user can log in in system or not, default is true</param>
        /// <param name="checkIsBanned">check user is banned or not, default is true</param>
        /// <returns>an instance of <see>XFriendshipInfoDto</see></returns>
        public async Task<XFriendshipInfoDto> GetFriendshipInfo(
            string userSelectByParam,
            string destUserSelectByParam,
            bool checkCanLoginPolicies = true,
            bool checkIsBanned = true
        )
        {
            //
            // Validate Args ...
            ValidationProvider.NotEmpty(
                userSelectByParam,
                destUserSelectByParam
            );

            //
            // Validate and Retrieve Dest User ...
            var xSourceUser = await ValidateUserExistsAndRetrieve(
                userSelectByParam,
                forceAdmin: false,
                containDetails: true,
                ignoreDisabledUser: false,
                checkIsBanned: checkIsBanned,
                checkCanLoginPolicies: checkCanLoginPolicies
            );

            //
            // Validate and Retrieve Dest User ...
            var xDestUser = await ValidateUserExistsAndRetrieve(
                destUserSelectByParam,
                forceAdmin: false,
                containDetails: true,
                ignoreDisabledUser: false,
                checkIsBanned: checkIsBanned,
                checkCanLoginPolicies: checkCanLoginPolicies
            );

            //
            var isSame = xSourceUser.Id == xDestUser.Id;
            var isFollower = false;
            var isFollowing = false;
            var followerState = XFriendshipState.None;
            var followingState = XFriendshipState.None;

            //
            if (!isSame)
            {
                //
                isFollower = await IsFollower(
                    userSelectByParam,
                    destUserSelectByParam,
                    checkIsBanned: checkIsBanned,
                    checkCanLoginPolicies: checkCanLoginPolicies
                );

                //
                isFollowing = await IsFollowing(
                    userSelectByParam,
                    destUserSelectByParam,
                    checkIsBanned: checkIsBanned,
                    checkCanLoginPolicies: checkCanLoginPolicies
                );

                //
                followerState = await GetFollowerState(
                    userSelectByParam,
                    destUserSelectByParam,
                    checkIsBanned: checkIsBanned,
                    checkCanLoginPolicies: checkCanLoginPolicies
                );

                //
                followingState = await GetFollowingState(
                    userSelectByParam,
                    destUserSelectByParam,
                    checkIsBanned: checkIsBanned,
                    checkCanLoginPolicies: checkCanLoginPolicies
                );
            }

            //
            var result = new XFriendshipInfoDto
            {
                UserId = xDestUser.Id,
                IsFollower = isFollower,
                IsFollowing = isFollowing,
                FollowerState = followerState,
                FollowingState = followingState,
                Followers = xDestUser.Followers
                .Count(f => f.State == XFriendshipState.Accepted),
                Followings = xDestUser.Followings
                .Count(f => f.State == XFriendshipState.Accepted)
            };

            //
            return result;
        }
        #endregion
        #endregion        
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\xIds\Providers\XIdentityManager\XIdentityManager+Identity.cs

using System;
using System.Net.Http;
using System.Threading.Tasks;
using IdentityModel.Client;
using Microsoft.Extensions.Logging;
using xCommons.Extensions;
using xExceptions.Constants;
using xExceptions.Models;
using xIdentityModels.Extensions;
using xIdentityModels.Models;
using xIds.Extensions;
using static IdentityModel.OidcConstants;

namespace xIds.Providers
{
    public partial class XIdentityManager
    {
        //
        #region Identity Actions ...
        /// <summary>
        /// Request for Discovery Document 
        /// </summary>
        /// <returns>an instance of <see>DiscoveryDocumentResponse</see></returns>
        public async Task<DiscoveryDocumentResponse> RequestDiscoveryDocument()
        {
            //
            var httpClient = GetHttpClient();
            var result = httpClient
                .GetDiscoveryDocumentAsync(IdentityResourceConfiguration.Authority)
                .ContinueWith(docTask =>
                {
                    //
                    httpClient.Dispose();
                    return docTask.Result;
                });

            //
            return await result;
        }

        /// <summary>
        /// Request AccessToken for Specific XApiScope
        /// </summary>
        /// <param name="scope">a member of <see>XApiScope</see></param>
        /// <returns>an instance of <see>TokenResponse</see></returns>
        public async Task<IdentityModel.Client.TokenResponse> RequestScopeAccessToken(
            string scope
        )
        {
            //
            // Validate Args ...
            if (scope.IsNullOrEmpty())
            {
                XException.InvalidArgs.Throw();
            }

            //
            // Retrieve Disco Doc ...
            var discoDoc = await RequestDiscoveryDocument();
            if (discoDoc.IsError)
            {
                XException.ActionFailed.Throw();
            }

            //
            var request = new ClientCredentialsTokenRequest
            {
                Address = discoDoc.TokenEndpoint,
                GrantType = GrantTypes.ClientCredentials,
                ClientId = IdentityResourceConfiguration.ClientId,
                ClientSecret = IdentityResourceConfiguration.ClientSecret,
                Scope = scope
            };

            //
            var httpClient = GetHttpClient();
            var result = await httpClient
                .RequestClientCredentialsTokenAsync(request)
                .ContinueWith(response =>
                {
                    //
                    httpClient.Dispose();
                    return response.Result;
                });

            //
            return result;
        }

        /// <summary>
        /// Authenticate a User
        /// </summary>
        /// <param name="model">an instance of <see>XLoginRequest</see> class which represent Authentication requirements</param>
        /// <returns>an instance of <see>TokenResponse</see></returns>
        public async Task<IdentityModel.Client.TokenResponse> Authenticate(
            XLoginRequest model
        )
        {
            //
            // Validate Args ...
            ValidationProvider
                .GroupValidationBuilder()
                .AddNotNull(model)
                .AddNotEmpty(
                    model.UserSelectBy,
                    model.Password
                )
                .ValidateGroup();

            //
            // Retrieve Disco Doc ...
            var discoDoc = await RequestDiscoveryDocument();
            if (discoDoc.IsError)
            {
                XException.ActionFailed.Throw();
            }

            //
            // Create Request ...
            var request = new PasswordTokenRequest
            {
                //
                Address = discoDoc.TokenEndpoint,

                //
                GrantType = GrantTypes.ClientCredentials,
                ClientId = IdentityResourceConfiguration.ClientId,
                ClientSecret = IdentityResourceConfiguration.ClientSecret,

                //
                UserName = model.UserSelectBy,
                Password = model.Password,

                //
                // Pass Device to Request ...
                Parameters = { { "force", false.ToJSON () }
                }
            };

            //
            var httpClient = GetHttpClient();
            var result = await httpClient
                .RequestPasswordTokenAsync(request)
                .ContinueWith(response =>
                {
                    //
                    httpClient.Dispose();
                    return response.Result;
                });

            //
            return result;
        }

        /// <summary>
        /// Do Login based on XLoginRequest
        /// </summary>
        /// <param name="model">an instance of <see>XLoginRequest</see> class which represent Authentication requirements</param>
        /// <returns>an instance of <see>XLoginResponse</see></returns>
        public async Task<XLoginResponse> Login(
            XLoginRequest model
        )
        {
            //
            // Validate Args ...
            ValidationProvider
                .GroupValidationBuilder()
                .AddNotNull(model, model.Device)
                .AddNotEmpty(
                    model.UserSelectBy,
                    model.Password
                )
                .ValidateGroup();

            //
            // Get Token Response ...
            //
            // Retrieve Disco Doc ...
            var discoDoc = await RequestDiscoveryDocument();
            Logger.LogInformation($"discoDoc: {discoDoc.ToJSON()}");

            if (discoDoc.IsError)
            {
                XException.ActionFailed.Throw();
            }

            //
            // Create Request ...
            var request = new PasswordTokenRequest
            {
                //
                Address = discoDoc.TokenEndpoint,

                //
                GrantType = GrantTypes.ClientCredentials,
                ClientId = IdentityResourceConfiguration.ClientId,
                ClientSecret = IdentityResourceConfiguration.ClientSecret,

                //
                UserName = model.UserSelectBy,
                Password = model.Password,

                //
                // Pass Device to Request ...
                Parameters = { { "force", false.ToJSON () },
                { "device", model.Device.ToJSON () },
                { "language", model.Language }
                }
            };

            //
            var httpClient = GetHttpClient();
            var authResponse = await httpClient
                .RequestPasswordTokenAsync(request)
                .ContinueWith(response =>
                {
                    //
                    httpClient.Dispose();
                    return response.Result;
                });

            //
            // Check If Response Has Error ...
            Logger.LogInformation($"AuthResponse: {authResponse.ToJSON()}");

            //
            if (authResponse.IsError)
            {
                throw authResponse.GetException();
            }

            //
            // Create XLoginResponse Model ...
            var result = authResponse.CreateXLoginResponse();

            //
            // Get ans Set User Profile ...
            result.Profile = await GetUserProfileAsync(model.UserSelectBy, model.UserSelectBy);

            //
            return result;
        }

        /// <summary>
        /// Refresh Tokens 
        /// </summary>
        /// <param name="model">Authentication Tokens, instance of <see>XTokenResponse</see></param>
        /// <returns>an instance of <see>XTokenResponse</see></returns>
        public async Task<XTokenResponse> RefreshTokens(
            XTokenResponse model
        )
        {
            //
            // Validate Args ...
            ValidationProvider
                .GroupValidationBuilder()
                .AddNotNull(model)
                .AddNotEmpty(
                    model.AccessToken,
                    model.RefreshToken
                )
                .ValidateGroup();

            //
            var authResponse = await RequestDiscoveryDocument()
                .ContinueWith((discoTask) =>
                {
                    //
                    var discoDoc = discoTask.Result;
                    if (discoDoc.IsError)
                    {
                        XException.ActionFailed.Throw();
                    }

                    //
                    using (var httpClient = GetHttpClient())
                    {
                        return httpClient.RequestRefreshTokenAsync(new RefreshTokenRequest
                        {
                            //
                            Address = discoDoc.TokenEndpoint,
                            GrantType = GrantTypes.RefreshToken,
                            ClientId = IdentityResourceConfiguration.ClientId,
                            ClientSecret = IdentityResourceConfiguration.ClientSecret,
                            RefreshToken = model.RefreshToken
                        }).Result;
                    }
                });

            //
            // Check If Response Has Error ...
            if (authResponse.IsError)
            {
                //
                XError error = authResponse.ErrorDescription.FromJSON<XError>();
                throw error.ToException();
            }

            //
            // Create XLoginResponse Model ...
            var result = authResponse.CreateXTokenResponse();

            //
            return result;
        }
        #endregion

        //
        #region Requirements ...
        /// <summary>
        /// Get an Instance of Http Client 
        /// </summary>
        /// <returns>an instance of <see>HttpClient</see></returns>
        public HttpClient GetHttpClient()
        {
            //
            HttpClient httpClient = null;
            httpClient = new HttpClient();
            var httpClientHandler = new HttpClientHandler()
            {
                ServerCertificateCustomValidationCallback = (sender, cert, chain, sslPolicyErrors) =>
                {
                    //
                    Logger.LogInformation(
                        $"SSL Handler: {Environment.NewLine} sender: {sender}, {Environment.NewLine} cert: {cert}, {Environment.NewLine} chain: {chain}, {Environment.NewLine} sslPolicyErrors: {sslPolicyErrors}"
                    );

                    //
                    return true;
                },
                ClientCertificateOptions = ClientCertificateOption.Manual,
            };

            //
            httpClient = new HttpClient(httpClientHandler);

            //
            return httpClient;
        }
        #endregion
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\xIds\Providers\XIdentityManager\XIdentityManager+MessageProvider.cs

using System;
using xCommons.Extensions;
using xExceptions.Constants;
using xIdentityModels.Navigations;
using xMessageService.Models;

namespace xIds.Providers
{
    public partial class XIdentityManager
    {
        //
        #region Message Provider ...
        /// <summary>
        /// Generate and Prepare an XMessage Instance for 
        /// User Invite Action
        /// </summary>
        /// <param name="lang">specify destination language</param>
        /// <param name="emailAddress">reciever email address</param>
        /// <param name="inviteToken">invitation token</param>
        /// <param name="returnUrl">return url for invitation user to redirect</param>
        /// <returns>an instance of <see>XMessage</see></returns>
        private XMessage GetUserInviteMessage(
            string lang,
            string emailAddress,
            string inviteToken,
            string returnUrl
        )
        {
            //
            ValidationProvider
                .NotEmpty(lang, emailAddress, inviteToken, returnUrl);
            ValidationProvider
                .EmailAddress(emailAddress);
            ValidationProvider
                .Url(returnUrl);

            //
            HandleMessageProviderPreperation(lang);

            //
            var msgStr = IdentityMessageProvider.InviteMsg +
                Environment.NewLine +
                returnUrl +
                "?t=" +
                inviteToken;

            //
            var message = new XMessage
            {
                Message = msgStr,
            };
            message.Recievers.Add(emailAddress);

            //
            return message;
        }

        /// <summary>
        /// Generate and Prepare an XMessage Instance for 
        /// New Device LoggedIn Action
        /// </summary>
        /// <param name="lang">specify destination language</param>
        /// <param name="emailAddress">reciever email address</param>
        /// <param name="device">an instance of <see>XDevice</see> which represent user new Device</param>
        /// <returns>an instance of <see>XMessage</see></returns>
        private XMessage GetUserNewDeviceLoggedInMessage(
            string lang,
            string emailAddress,
            XDevice device
        )
        {
            //
            ValidationProvider
                .NotEmpty(lang, emailAddress);
            ValidationProvider
                .EmailAddress(emailAddress);
            ValidationProvider
                .NotNull(device);

            //
            HandleMessageProviderPreperation(lang);

            //
            // Generate Specific Message ...
            var msgStr = IdentityMessageProvider.NewDeviceLoggedInMsg +
                Environment.NewLine +
                nameof(XDevice.Os) + ": " + device.Os +
                Environment.NewLine +
                nameof(XDevice.OsVersion) + ": " + device.OsVersion +
                Environment.NewLine +
                nameof(XDevice.Browser) + ": " + device.Browser +
                Environment.NewLine +
                nameof(XDevice.UserAgent) + ": " + device.UserAgent;

            //
            // Create XMessage Instance ...
            var message = new XMessage
            {
                Message = msgStr,
            };
            message.Recievers.Add(emailAddress);

            //
            return message;
        }

        /// <summary>
        /// Generate and Prepare an XMessage Instance for 
        /// Verification Code Action
        /// </summary>
        /// <param name="lang">specify destination language</param>
        /// <param name="mobileNumberOrEmail">an string which points to a user email address or mobile number</param>
        /// <param name="verificationCode">user verification code</param>
        /// <returns>an instance of <see>XMessage</see></returns>
        private XMessage GetVerificationCodeMessage(
            string lang,
            string mobileNumberOrEmail,
            string verificationCode
        )
        {
            //
            ValidationProvider
                .NotEmpty(lang, mobileNumberOrEmail, verificationCode);

            //
            HandleMessageProviderPreperation(lang);

            //
            mobileNumberOrEmail = mobileNumberOrEmail.ToNormalString();

            //
            // Validate Mobile or Email ...
            var isValidEmail = mobileNumberOrEmail.IsValidEmail();
            var isValidMobileNumber = mobileNumberOrEmail.IsValidMobileNumber();
            if (!isValidEmail &&
                !isValidMobileNumber)
            {
                XException.InvalidData.Throw();
            }

            //
            // Prepare Message String ...
            var msgStr = IdentityMessageProvider.VerificationCodeMsg +
                Environment.NewLine +
                verificationCode;

            //
            // Create XMessage Instance ...
            var message = new XMessage
            {
                Message = msgStr,
            };
            message.Recievers.Add(mobileNumberOrEmail);

            //
            return message;
        }

        /// <summary>
        /// Generate and Prepare an XMessage Instance for 
        /// Registration Approve Action
        /// </summary>
        /// <param name="lang">specify destination language</param>
        /// <param name="emailAddress">reciever email address</param>
        /// <param name="actionToken">a token which approved user action</param>
        /// <param name="returnUrl">return url for redirect</param>
        /// <returns>an instance of <see>XMessage</see></returns>
        private XMessage GetRegistrationConfirmMessage(
            string lang,
            string emailAddress,
            string actionToken,
            string returnUrl
        )
        {
            //
            ValidationProvider
                .NotEmpty(lang, emailAddress, actionToken, returnUrl);
            ValidationProvider
                .EmailAddress(emailAddress);
            ValidationProvider
                .Url(returnUrl);

            //
            HandleMessageProviderPreperation(lang);

            //
            // Prepare Message Str ...
            var msgStr = IdentityMessageProvider.RegistrationApproveMsg +
                Environment.NewLine +
                returnUrl +
                "?t=" +
                actionToken;

            //
            var message = new XMessage
            {
                Message = msgStr,
            };
            message.Recievers.Add(emailAddress);

            //
            return message;
        }

        /// <summary>
        /// Generate and Prepare an XMessage Instance for 
        /// Registration Finished Action
        /// </summary>
        /// <param name="lang">specify destination language</param>
        /// <param name="emailAddress">reciever email address</param>
        /// <param name="returnUrl">return url for redirect</param>
        /// <returns>an instance of <see>XMessage</see></returns>
        private XMessage GetRegistrationFinishedMessage(
            string lang,
            string emailAddress,
            string returnUrl
        )
        {
            //
            ValidationProvider
                .NotEmpty(lang, emailAddress, returnUrl);
            ValidationProvider
                .EmailAddress(emailAddress);
            ValidationProvider
                .Url(returnUrl);

            //
            HandleMessageProviderPreperation(lang);

            //
            var msgStr = IdentityMessageProvider.RegisteredMsg +
                Environment.NewLine +
                returnUrl;

            //
            var message = new XMessage
            {
                Message = msgStr,
            };
            message.Recievers.Add(emailAddress);

            //
            return message;
        }

        /// <summary>
        /// Generate and Prepare an XMessage Instance for 
        /// Password Changed Action
        /// </summary>
        /// <param name="lang">specify destination language</param>
        /// <param name="emailAddress">reciever email address</param>
        /// <param name="returnUrl">return url for redirect</param>
        /// <param name="throwException">specify throw exceptions on failure or not, default is true</param>
        /// <returns>an instance of <see>XMessage</see></returns>
        private XMessage GetPasswordChangedMessage(
            string lang,
            string emailAddress,
            string returnUrl,
            bool throwException = true
        )
        {
            //
            if (throwException)
            {
                ValidationProvider
                    .NotEmpty(lang, emailAddress, returnUrl);
                ValidationProvider
                    .EmailAddress(emailAddress);
                ValidationProvider
                    .Url(returnUrl);
            }

            //
            HandleMessageProviderPreperation(lang);

            //
            var msgStr = IdentityMessageProvider.PasswordChangedMsg +
                (returnUrl.IsNullOrEmpty() ?
                    "" :
                    Environment.NewLine +
                    returnUrl);

            //
            var message = new XMessage
            {
                Message = msgStr,
            };
            message.Recievers.Add(emailAddress);

            //
            return message;
        }

        /// <summary>
        /// Generate and Prepare an XMessage Instance for 
        /// Reset Password Action
        /// </summary>
        /// <param name="lang">specify destination language</param>
        /// <param name="emailAddress">reciever email address</param>
        /// <param name="actionToken">a token which approved user action</param>
        /// <param name="returnUrl">return url for redirect</param>
        /// <returns>an instance of <see>XMessage</see></returns>
        private XMessage GetResetPasswordMessage(
            string lang,
            string emailAddress,
            string actionToken,
            string returnUrl
        )
        {
            //
            ValidationProvider
                .NotEmpty(lang, emailAddress, actionToken, returnUrl);
            ValidationProvider
                .EmailAddress(emailAddress);
            ValidationProvider
                .Url(returnUrl);

            //
            HandleMessageProviderPreperation(lang);

            //
            // Prepare Message Str ...
            var msgStr = IdentityMessageProvider.ChangePasswordMsg +
                Environment.NewLine +
                returnUrl +
                "?t=" +
                actionToken;

            //
            var message = new XMessage
            {
                Message = msgStr,
            };
            message.Recievers.Add(emailAddress);

            //
            return message;
        }
        #endregion
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\xIds\Providers\XIdentityManager\XIdentityManager+Open.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using xCommons.Extensions;
using xExceptions.Constants;
using xIdentityModels.Dtos;

namespace xIds.Providers
{
    public partial class XIdentityManager
    {
        //
        #region OpenGet ...
        public async Task<XOpenActionInnerDto> OpenGet(
            XOpenActionInnerDto model
        )
        {
            //
            // Validate Args ...
            await ValidationProvider
                .GroupValidationBuilder()
                .AddNotNull(model)
                .AddNotEmpty(model.Token)
                .AddNotEmpty(model.Payload)
                .ValidateGroupAsync();

            //
            return await OpenGet(
                token: model.Token,
                actionRequest: model.Payload
            );
        }

        //
        public async Task<XOpenActionInnerDto> OpenGet(
            string token,
            string actionRequest
        )
        {
            //
            // Validatr Args ...
            await ValidationProvider
                .GroupValidationBuilder()
                .AddNotEmpty(token)
                .AddNotEmpty(actionRequest)
                .ValidateGroupAsync();
            //
            // Try to Decrypt Request ...
            var requestModel = ParseModel(
                token: token,
                request: actionRequest
            );
            if (requestModel.IsNull() ||
                requestModel.Action.IsNullOrEmpty())
            {
                XException.BadRequest.Throw();
            }

            //
            var responseJson = string.Empty;
            switch (requestModel.Action)
            {
                //
                case XOpenActions.GetUserInfo:
                    //
                    ValidationProvider.NotEmpty(requestModel.Payload);
                    var userInfo = await GetUserInfo(requestModel);
                    if (userInfo.IsNull())
                    {
                        XException.InvalidData.Throw();
                    }

                    //
                    responseJson = userInfo.ToJSON();
                    break;

                //
                case XOpenActions.GetUserInfos:
                    ValidationProvider.NotEmpty(requestModel.Payload);
                    var userInfos = await GetUserInfos(requestModel);
                    if (userInfos.IsNull())
                    {
                        XException.InvalidData.Throw();
                    }

                    //
                    responseJson = userInfos.ToJSON();
                    break;
            }

            //
            // Encrypt Json Str ...
            var responseStr = SecurityProvider.Encrypt(responseJson);
            requestModel.Payload = responseStr;
            requestModel.Timestamp = DateTime.UtcNow
                .AddMinutes(5)
                .ToTimestamp()
                .ToString();

            //
            token = requestModel.ToOpenActionToken();
            requestModel.Checksum = token;
            var result = new XOpenActionInnerDto
            {
                Token = token,
                Payload = requestModel.ToJSON()
            };

            //
            // Check Result ...
            if (result.IsNull())
            {
                XException.ActionFailed.Throw();
            }

            //
            return result;
        }
        #endregion

        public async Task<XOpenActionUserInfoDto> GetUserInfo(
            XOpenActionRequestDto model
        )
        {
            //
            // Retrieve User Profile ...
            var userProfile = await GetUserProfileAsync(
                checkIsBanned: false,
                checkCanLoginPolicies: false,
                requestedUserSelectByParam: "",
                forceCheckRequestedUser: false,
                userSelectByParam: model.Payload
            );

            //
            //  Generate a Dynamic Object ...
            var result = new XOpenActionUserInfoDto
            {
                Username = userProfile.UserName,
                Firstname = userProfile.FirstName,
                Lastname = userProfile.LastName,
                Avatar = userProfile.Avatar
            };

            //
            return result;
        }

        public async Task<IEnumerable<XOpenActionUserInfoDto>> GetUserInfos(
            XOpenActionRequestDto model
        )
        {
            //
            var ids = model.Payload.ParseListString<string>().ToList();
            var profiles = await GetUserProfilesAsync(
                ids: ids,
                checkIsBanned: false,
                checkCanLoginPolicies: false,
                requestedUserSelectByParam: "",
                forceCheckRequestedUser: false
            );
            var result = profiles.Select(x => new XOpenActionUserInfoDto
            {
                Avatar = x.Avatar,
                Username = x.UserName,
                Lastname = x.LastName,
                Firstname = x.FirstName,
            });

            //
            return result;
        }

        //
        #region Private ...
        private XOpenActionRequestDto ParseModel(
            string token,
            string request
        )
        {
            //
            // Decript request to get Json string of request object ...
            var result = new XOpenActionRequestDto();

            //
            var jsonStr = SecurityProvider.Decrypt(request);
            result = jsonStr.FromJSON<XOpenActionRequestDto>();
            if (result.IsNull() ||
                !result.Validate() ||
                token != result.Checksum
            )
            {
                //
                result = null;
                return result;
            }

            //
            var modelChecksum = result.ToOpenActionToken();
            result =
                token == modelChecksum
                ? result
                : null;

            //
            return result;
        }
        #endregion
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\xIds\Providers\XIdentityManager\XIdentityManager+Private.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.EntityFrameworkCore;
using xCommons.Extensions;
using xCommons.Helpers;
using xExceptions.Constants;
using xIdentityModels;
using xIdentityModels.Constants;
using xIdentityModels.Dtos;
using xIdentityModels.Models;
using xIdentityModels.Navigations;

namespace xIds.Providers
{
    public partial class XIdentityManager
    {
        //
        #region Generators ...
        /// <summary>
        /// Generate a Random Number ...
        /// </summary>
        /// <returns>a long value</returns>
        private long GenerateRandom()
        {
            return new Random().Next(100000, 999999);
        }
        #endregion

        //
        #region UserSelectBy Actions ...
        /// <summary>
        /// Retrieve UserSelectByType based on Given Info 
        /// </summary>
        /// <param name="userSelectByParam">a user identifier</param>
        /// <param name="forceUserSelectByParamNotEmpty">a boolean value which specify the identifier 
        /// must be specific and not empty, default is true</param>
        /// <param name="forceUserSelectByTypeMustSpecified">a boolean value which specify the type 
        /// must be specific, default is false</param>
        /// <returns>a member of <see>XUserSelectBy</see></returns>
        private XUserSelectBy GetUserSelectByType(
            string userSelectByParam,
            bool forceUserSelectByParamNotEmpty = true,
            bool forceUserSelectByTypeMustSpecified = false
        )
        {
            //
            if (forceUserSelectByParamNotEmpty)
            {
                ValidationProvider.NotEmpty(userSelectByParam);
            }

            //
            var result = XUserSelectBy.NotSpecified;
            var normalizedString = userSelectByParam.ToNormalString();
            if (userSelectByParam.IsValidEmail())
            {
                //
                // Find User by Email ...
                result = XUserSelectBy.Email;
            }
            else if (userSelectByParam.IsValidMobileNumber())
            {
                //
                // Find User by Mobile Number ...
                result = XUserSelectBy.MobileNumber;
            }
            else if (userSelectByParam.IsGuid())
            {
                //
                // Find User By it's ID ...
                result = XUserSelectBy.ID;
            }
            else
            {
                //
                // UserName ...
                result = XUserSelectBy.Username;
            }

            //
            if (forceUserSelectByTypeMustSpecified &&
                result == XUserSelectBy.NotSpecified)
            {
                XException.InvalidData.Throw();
            }

            //
            return result;
        }

        /// <summary>
        /// Retrieve UserSelectByParam based on XUser Object
        /// </summary>
        /// <param name="user">an instance of <see>XUser</see></param>
        /// <param name="forceNotNull">a boolean value which specify the identifier must nut empty, 
        /// and throw exception if it is empty, default is true</param>
        /// <param name="excludes">a collection of <see>XUserSelectBy</see> members which 
        /// exclude them from result, default is null</param>
        /// <returns>a user identifier</returns>
        private string GetUserSelectByParam(
            XUser user,
            bool forceNotNull = true,
            ICollection<XUserSelectBy> excludes = null
        )
        {
            //
            // Validate Args ...
            ValidationProvider.NotNull(user);

            //
            var id = user.Id;
            var userName = user.UserName;
            var email = user.Email;
            var phoneNumber = user.PhoneNumber;

            //
            if (excludes != null)
            {
                if (excludes.Contains(XUserSelectBy.ID))
                {
                    id = null;
                }
                if (excludes.Contains(XUserSelectBy.Email))
                {
                    email = null;
                }
                if (excludes.Contains(XUserSelectBy.MobileNumber))
                {
                    phoneNumber = null;
                }
                if (excludes.Contains(XUserSelectBy.Username))
                {
                    userName = null;
                }
            }

            var selectByParam =
                id.IsNullOrEmpty() ?
                userName.IsNullOrEmpty() ?
                email.IsNullOrEmpty() ?
                phoneNumber.IsNullOrEmpty() ? null : phoneNumber : email : userName : id;

            //
            // Check result ...
            if (forceNotNull &&
                selectByParam.IsNullOrEmpty())
            {
                XException.InvalidData.Throw();
            }

            //
            return selectByParam;
        }

        /// <summary>
        /// Retrieve UserSelectByParam based on <see>XActionRequestContext</see> instance
        /// </summary>
        /// <param name="context">an instance of <see>XActionRequestContext</see></param>
        /// <param name="forceNotNull">a boolean value which specify the identifier must nut empty, 
        /// and throw exception if it is empty, default is true</param>
        /// <param name="excludes">a collection of <see>XUserSelectBy</see> members which 
        /// exclude them from result, default is null</param>
        /// <returns>a user identifier</returns>
        private string GetUserSelectByParam(
            XActionRequestContext context,
            bool forceNotNull = true,
            ICollection<XUserSelectBy> excludes = null
        )
        {
            //
            // Validate Args ...
            ValidationProvider.NotNull(context);

            //
            // Generate User SelectBy ...
            var id = context.UserId;
            var userName = context.UserName;
            var email = context.Email;
            var phoneNumber = context.MobileNumber;

            //
            if (excludes != null)
            {
                //
                if (excludes.Contains(XUserSelectBy.ID))
                {
                    id = null;
                }
                if (excludes.Contains(XUserSelectBy.Email))
                {
                    email = null;
                }
                if (excludes.Contains(XUserSelectBy.MobileNumber))
                {
                    phoneNumber = null;
                }
                if (excludes.Contains(XUserSelectBy.Username))
                {
                    userName = null;
                }
            }

            var selectByParam =
                id.IsNullOrEmpty() ?
                userName.IsNullOrEmpty() ?
                email.IsNullOrEmpty() ?
                phoneNumber.IsNullOrEmpty() ? null : phoneNumber : email : userName : id;

            //
            // Check param ...
            if (forceNotNull &&
                selectByParam.IsNullOrEmpty())
            {
                XException.InvalidData.Throw();
            }

            //
            return selectByParam;
        }

        /// <summary>
        /// Retrieve UserSelectByParam based on <see>XActionRequestToken</see> instance
        /// </summary>
        /// <param name="request">an instance of <see>XActionRequestToken</see> which
        /// provides required informations</param>
        /// <param name="forceNotNull">a boolean value which specify the identifier must nut empty, 
        /// and throw exception if it is empty, default is true</param>
        /// <param name="excludes">a collection of <see>XUserSelectBy</see> members which 
        /// exclude them from result, default is null</param>
        /// <returns>a user identifier</returns>
        private string GetUserSelectByParam(
            XActionRequestToken request,
            bool forceNotNull = true,
            ICollection<XUserSelectBy> excludes = null
        )
        {
            //
            // Validate Args ...
            ValidationProvider.NotNull(request);

            //
            // Generate User SelectBy ...
            return GetUserSelectByParam(
                context: request.Context,
                forceNotNull: forceNotNull,
                excludes: excludes
            );
        }

        /// <summary>
        /// Retrieve Available UserSelectByParams from given XUser
        /// </summary>
        /// <param name="user">an instance of <see>XUser</see></param>
        /// <returns></returns>
        private ICollection<string> GenerateUserSelectByParams(
            XUser user
        )
        {
            //
            if (user == null)
            {
                return null;
            }

            //
            var result = new List<string> {
                user.Id,
                user.UserName,
                user.PhoneNumber,
                user.Email,
            };

            //
            return result;
        }

        /// <summary>
        /// Retrieve Required XUserSelectByTypes
        /// </summary>
        /// <param name="ignores">a collection of <see>XUserSelectBy</see> members which
        /// ignored in result</param>
        /// <returns>a collection of available <see>XUserSelectBy</see> members</returns>
        private ICollection<XUserSelectBy> GenerateUserSelectByExcludes(
            ICollection<XUserSelectBy> ignores
        )
        {
            //
            var result = ObjectHelper
                .ToEnumerableValues<XUserSelectBy>()
                .Except(ignores);

            //
            return result.ToList();
        }
        #endregion

        //
        #region XAction Actions ...
        /// <summary>
        /// Retrieve Action Result Response based on XToken
        /// </summary>
        /// <param name="xToken">an instance of <see>XToken</see></param>
        /// <returns>an instance of <see>XActionResponse</see></returns>
        private XActionResponse GetActionResultResponse(
            XToken xToken
        )
        {
            //
            ValidationProvider.NotNull(xToken);
            ValidationProvider.NotEmpty(xToken.Hash, xToken.Token);

            //
            ValidateToken(xToken.Token);

            //
            var expDate = GetTokenExpirationDate(xToken.Token);
            ValidationProvider.NotNull(expDate);

            //
            // Generate Result class ...
            var result = new XActionResponse
            {
                Token = xToken.Hash,
                Expiration = expDate
            };

            //
            return result;
        }
        #endregion

        //
        #region XIdentityMessage Actions ...
        /// <summary>
        /// Prepare Message Provider and Check it's State
        /// </summary>
        /// <param name="lang">specify destination language</param>
        private void HandleMessageProviderPreperation(
            string lang
        )
        {
            //
            ValidationProvider
                .NotEmpty(lang);

            //
            // Prepare Identity Messages ...
            // the PrepareMessageMethod check IsReady of Helper automatically ...
            IdentityMessageProvider.PrepareMessages(lang);

            //
            // Check Message Provider ...
            var isMessageProviderReady = MessageProvider.IsReady(true);
            if (!isMessageProviderReady)
            {
                XException.MessageServiceInitialFailed.Throw();
            }
        }
        #endregion

        //
        #region Friendship Actions ...
        /// <summary>
        /// Check Follow Request Sent Before 
        /// from dest to source
        /// </summary>
        /// <param name="source">an instance of <see>XUser</see></param>
        /// <param name="dest">an instance of <see>XUser</see></param>
        /// <returns>a boolean value</returns>
        private bool IsFollowRequested(
            XUser source,
            XUser dest
        )
        {
            //
            // Validate Args ...
            ValidationProvider.NotNull(source, dest);

            //
            var result = source.Followings.Any(f => f.DestId == dest.Id);

            //
            return result;
        }

        /// <summary>
        /// Check Follow Request Sent Before
        /// from dest to source
        /// </summary>
        /// <param name="source">an instance of <see>XUser</see></param>
        /// <param name="dest">an instance of <see>XUser</see></param>
        /// <param name="state">a member of <see>XFriendshipState</see></param>
        /// <returns>a boolean value</returns>
        private bool IsFollowRequested(
            XUser source,
            XUser dest,
            XFriendshipState state
        )
        {
            //
            // Validate Args ...
            ValidationProvider.NotNull(source, dest);

            //
            var result = source.Followings
                .Any(f =>
                    f.DestId == dest.Id &&
                    f.State == state);

            //
            return result;
        }

        /// <summary>
        /// Converts to XFriendDto ...
        /// </summary>
        /// <param name="entity"></param>
        /// <returns></returns>
        private async Task<XFriendDto> ToDto(XFriendshipFollower entity)
        {
            //
            XFriendDto result = null;

            //
            if (entity.IsNull())
            {
                return result;
            }

            //
            // Reading Dest User Profile ...
            var profile = await GetUserProfileAsync(
                userSelectByParam: entity.DestId,
                requestedUserSelectByParam: entity.UserId,
                forceCheckRequestedUser: false,
                checkCanLoginPolicies: false,
                checkIsBanned: false
            );

            //
            // Preparing Result ...
            result = new XFriendDto
            {
                UserId = profile.UserId,
                Avatar = profile.Avatar,
                Username = profile.UserName,
                Lastname = profile.LastName,
                Firstname = profile.FirstName,
                Type = XFriendshipType.Follower,
                State = profile.FriendshipInfo.FollowerState,
            };

            //
            return result;
        }

        /// <summary>
        /// Converts to XFriendDto ...
        /// </summary>
        /// <param name="entity"></param>
        /// <returns></returns>
        private async Task<XFriendDto> ToDto(XFriendshipFollowing entity)
        {
            //
            XFriendDto result = null;

            //
            if (entity.IsNull())
            {
                return result;
            }

            //
            // Reading Dest User Profile ...
            var profile = await GetUserProfileAsync(
                checkIsBanned: false,
                checkCanLoginPolicies: false,
                forceCheckRequestedUser: false,
                userSelectByParam: entity.DestId,
                requestedUserSelectByParam: entity.UserId
            );

            //
            // Preparing Result ...
            result = new XFriendDto
            {
                UserId = profile.UserId,
                Avatar = profile.Avatar,
                Username = profile.UserName,
                Lastname = profile.LastName,
                Firstname = profile.FirstName,
                Type = XFriendshipType.Following,
                State = profile.FriendshipInfo.FollowingState,
            };

            //
            return result;
        }
        #endregion

        //
        #region User Profile ...
        /// <summary>
        /// Count User's Page
        /// </summary>
        /// <param name="pageSize">an integer value which represent page size</param>
        /// <returns>an inetger value which represent pages count</returns>
        public async Task<int> UserPagesCount(
            int pageSize
        )
        {
            //
            int count = await UserManager.Users.CountAsync();
            int pagesCount = count / pageSize;

            //
            if (count % pageSize > 0)
            {
                pagesCount++;
            }

            //
            return pagesCount;
        }

        /// <summary>
        /// Count Avatar's Page
        /// </summary>
        /// <param name="pageSize">an integer value which represent page size</param>
        /// <returns>an inetger value which represent pages count</returns>
        public async Task<int> ProfileImagePagesCount(
            int pageSize
        )
        {
            //
            int count = await DbContext.Avatars.CountAsync();
            int pagesCount = count / pageSize;

            //
            if (count % pageSize > 0)
            {
                pagesCount++;
            }

            //
            return pagesCount;
        }
        #endregion
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\xIds\Providers\XIdentityManager\XIdentityManager+Profile.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Http;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Logging;
using xCommons.Extensions;
using xExceptions.Constants;
using xIdentityModels.Constants;
using xIdentityModels.Dtos;
using xIdentityModels.Models;
using xIdentityModels.Navigations;
using xModels.Dtos;
using xIds.Extensions;
using xIdentityModels.Extensions;
using xIdentityHelper;
using xIdentityHelper.Extensions;
using xDataService.Extensions;

namespace xIds.Providers
{
    public partial class XIdentityManager
    {
        //
        #region Retrieve Actions ...
        /// <summary>
        /// Retrieve User Profile
        /// </summary>
        /// <param name="userSelectByParam">a user identifier</param>
        /// <param name="requestedUserSelectByParam">requested user's identifier</param>
        /// <param name="forceCheckRequestedUser">specify check requested user's identifier not empty
        /// and throw exception if it is, default true</param>
        /// <param name="checkCanLoginPolicies">check a user can log in in system or not, default is true</param>
        /// <param name="checkIsBanned">check user is banned or not, default is true</param>
        /// <returns>an instance of <see>XUserProfileDto</see></returns>
        public async Task<XUserProfileDto> GetUserProfileAsync(
            string userSelectByParam,
            string requestedUserSelectByParam,
            bool forceCheckRequestedUser = true,
            bool checkCanLoginPolicies = true,
            bool checkIsBanned = true
        )
        {
            //
            // Data Validation ...
            if (forceCheckRequestedUser)
            {
                ValidationProvider.NotEmpty(
                    userSelectByParam,
                    requestedUserSelectByParam);
            }
            else
            {
                ValidationProvider.NotEmpty(userSelectByParam);
            }

            //
            var xUser = await ValidateUserExistsAndRetrieve(
                userSelectByParam,
                containDetails: true,
                checkCanLoginPolicies: false,
                checkIsBanned: false,
                ignoreDisabledUser: true,
                forceAdmin: false
            );

            //
            var isAdmin = false;
            var isSameUser = false;
            if (forceCheckRequestedUser &&
                !requestedUserSelectByParam.IsNullOrEmpty())
            {
                //
                var xRequestedUser = await ValidateUserExistsAndRetrieve(
                    requestedUserSelectByParam,
                    containDetails: true,
                    checkCanLoginPolicies: false,
                    checkIsBanned: false,
                    ignoreDisabledUser: true,
                    forceAdmin: false
                );

                //
                isSameUser = xUser.Id == xRequestedUser.Id;

                //
                var xRequestUserRoleNames = await GetRoleNamesAsync(
                    userSelectByParam: requestedUserSelectByParam,
                    checkCanLoginPolicies: false,
                    checkIsBanned: false
                    );
                isAdmin = xRequestUserRoleNames.Contains(XUserRole.Admin.GetStringValue());
            }

            //
            var roleNames = await GetRoleNamesAsync(
                userSelectByParam,
                checkIsBanned: checkIsBanned,
                checkCanLoginPolicies: checkCanLoginPolicies
            );

            //
            var xFriendshipInfo =
                requestedUserSelectByParam.IsNullOrEmpty()
                ? null
                : await GetFriendshipInfo(
                    requestedUserSelectByParam,
                    userSelectByParam,
                    checkIsBanned: checkIsBanned,
                    checkCanLoginPolicies: checkCanLoginPolicies
                );

            //
            var result = xUser.ToXProfileDto(
                isAdmin: isAdmin,
                roles: roleNames,
                isSameUser: isSameUser,
                friendship: xFriendshipInfo,
                profileConfig: Configuration.Policy.Profile
            );

            //
            return result;
        }

        /// <summary>
        /// Retrieve a Collection of User Profiles
        /// </summary>
        /// <param name="ids">a collection of user identifiers</param>
        /// <param name="requestedUserSelectByParam">requested user's identifier</param>
        /// <param name="forceCheckRequestedUser">specify check requested user's identifier not empty
        /// and throw exception if it is, default true</param>
        /// <param name="checkCanLoginPolicies">check a user can log in in system or not, default is true</param>
        /// <param name="checkIsBanned">check user is banned or not, default is true</param>
        /// <returns>an collection of <see>XUserProfileDto</see> instances</returns>
        public async Task<IEnumerable<XUserProfileDto>> GetUserProfilesAsync(
            ICollection<string> ids,
            string requestedUserSelectByParam,
            bool forceCheckRequestedUser = true,
            bool checkCanLoginPolicies = true,
            bool checkIsBanned = true
        )
        {
            //
            // Data Validation ...
            if (forceCheckRequestedUser)
            {
                ValidationProvider.NotEmpty(requestedUserSelectByParam);
            }
            ValidationProvider.NotZeroChilds(ids);

            //
            var result = new List<XUserProfileDto>();
            foreach (var id in ids)
            {
                //
                var xProfile = await GetUserProfileAsync(
                    id,
                    requestedUserSelectByParam,
                    checkIsBanned: checkIsBanned,
                    checkCanLoginPolicies: checkCanLoginPolicies,
                    forceCheckRequestedUser: forceCheckRequestedUser
                );
                result.Add(xProfile);
            }

            //
            return result;
        }

        /// <summary>
        /// Query User Profiles
        /// </summary>
        /// <param name="requestedUserSelectByParam">requested user's identifier</param>
        /// <param name="query">how to filter results based on <see>XQuery</see> structure</param>
        /// <returns>an instance of <see>XQueryResult</see> of <see>XUserProfileDto</see></returns>
        public async Task<XQueryResult<XUserProfileDto>> QueryUsers(
            string requestedUserSelectByParam,
            XQuery query
        )
        {
            //
            // Validation ...
            if (query.IsNull())
            {
                XException.InvalidArgs.Throw();
            }

            //
            // Normalize ...
            query = query.NormalizeQuery(DataConfiguration.ToXDataServiceConfig());

            //
            // Since in Resourceable Entities we have to Search on Locales
            // we Must Implement Senario Custom ...
            var totalEntities = GetUsersDbSet()
                .ToList()
                .Where(u => !u.ContainsUserSelectByParam(requestedUserSelectByParam))
                .Select(u => u.Id)
                .ToList();

            //
            var items = await GetUserProfilesAsync(
                totalEntities,
                requestedUserSelectByParam,
                checkIsBanned: false,
                checkCanLoginPolicies: false,
                forceCheckRequestedUser: false
            );

            //
            var totalItemsCount = items.Count();

            //
            // Apply Filter ...
            if (!query.Filter.IsNullOrEmpty())
            {
                //
                items = items
                    .ApplyFilter(query.Filter);
            }
            int filteredItemsCount = items.Count();

            //
            // Count Pages ...
            var totalPagesCount = query.CountPages(totalItemsCount);
            var filteredPagesCount = query.CountPages(filteredItemsCount);

            //
            // Apply Paging and Sorting ...
            if (totalItemsCount > 0 &&
                filteredItemsCount > 0)
            {
                //
                // Apply Sorting ...
                items = items
                    .ToList()
                    .ApplySorting(
                        query.SortBy,
                        query.IsAscending
                    );

                //
                // Apply Paging ...
                items = items
                    .ToList()
                    .ApplyPaging(
                        query.Page,
                        query.PageSize
                    );
            }

            //
            // Generate Result Object ...
            // Query = query,
            var result = new XQueryResult<XUserProfileDto>
            {
                Items = items,
                Page = query.Page,
                PageSize = query.PageSize,
                TotalPages = totalPagesCount,
                TotalItems = totalItemsCount,
                TotalFilteredPages = filteredPagesCount,
                TotalFilteredItems = filteredItemsCount
            };

            //
            return result;
        }

        /// <summary>
        /// Query In Roles User Profiles
        /// </summary>
        /// <param name="requestedUserSelectByParam">requested user's identifier</param>
        /// <param name="role">an string which represent user role</param>
        /// <param name="query">how to filter results based on <see>XQuery</see> structure</param>
        /// <param name="forceRole">if it's true the user must has exact role, otherwise top level users also listed, default is false</param>
        /// <returns>an instance of <see>XQueryResult</see> of <see>XUserProfileDto</see></returns>
        public async Task<XQueryResult<XUserProfileDto>> QueryInRoleUsers(
            string requestedUserSelectByParam,
            string role,
            XQuery query,
            bool forceRole = false
        )
        {
            //
            // Validation ...
            if (query.IsNull() || role.IsNullOrEmpty())
            {
                XException.InvalidArgs.Throw();
            }

            //
            // Check Role Exists ...
            var isExistsRole = await IsRoleExistsAsync(role);
            if (!isExistsRole)
            {
                XException.NotFound.Throw();
            }

            //
            // Normalize ...
            query = query.NormalizeQuery(DataConfiguration.ToXDataServiceConfig());

            //
            #region Select Users Based on Specific Roles ...
            var selectedUsers = new List<string>();
            var usersEnumerator = GetUsersDbSet(query.ContainsDetail).AsAsyncEnumerable();
            await
            foreach (var user in usersEnumerator)
            {
                //
                if (user.ContainsUserSelectByParam(requestedUserSelectByParam))
                {
                    continue;
                }

                //
                // Set Default Value is True ...
                var isInRole = false;

                //
                // if Force Role ...
                if (forceRole)
                {
                    isInRole = await UserManager.IsInRoleAsync(user, role);
                }
                else
                {
                    //
                    // Select User Top Role ...
                    var userRoles = await GetRoleNamesAsync(
                        checkIsBanned: false,
                        userSelectByParam: user.Id,
                        checkCanLoginPolicies: false
                    );
                    isInRole = userRoles.HasRolePermissions(role);
                }

                //
                if (isInRole)
                {
                    selectedUsers.Add(user.Id);
                }
            }
            #endregion

            //
            var items = await GetUserProfilesAsync(
                selectedUsers,
                requestedUserSelectByParam,
                checkIsBanned: false,
                checkCanLoginPolicies: false,
                forceCheckRequestedUser: false
            );

            //
            var totalItemsCount = items.Count();

            //
            // Apply Filter ...
            if (!query.Filter.IsNullOrEmpty())
            {
                //
                items = items
                    .ApplyFilter(query.Filter);
            }
            int filteredItemsCount = items.Count();

            //
            // Count Pages ...
            var totalPagesCount = query.CountPages(totalItemsCount);
            var filteredPagesCount = query.CountPages(filteredItemsCount);

            //
            // Apply Paging and Sorting ...
            if (totalItemsCount > 0 &&
                filteredItemsCount > 0)
            {
                //
                // Apply Sorting ...
                items = items
                    .ToList()
                    .ApplySorting(
                        query.SortBy,
                        query.IsAscending
                    );

                //
                // Apply Paging ...
                items = items
                    .ToList()
                    .ApplyPaging(
                        query.Page,
                        query.PageSize
                    );
            }

            //
            // Generate Result Object ...
            // Query = query,
            var result = new XQueryResult<XUserProfileDto>
            {
                Items = items,
                Page = query.Page,
                PageSize = query.PageSize,
                TotalPages = totalPagesCount,
                TotalItems = totalItemsCount,
                TotalFilteredPages = filteredPagesCount,
                TotalFilteredItems = filteredItemsCount
            };

            //
            return result;
        }

        /// <summary>
        /// Query Specified User's Profile Images
        /// </summary>
        /// <param name="userSelectByParam">a user identifier</param>
        /// <param name="query">how to filter results based on <see>XQuery</see> structure</param>
        /// <returns>an instance of <see>XQueryResult</see> of <see>XProfileImage</see></returns>
        public async Task<XQueryResult<XProfileImage>> QueryAvatars(
            string userSelectByParam,
            XQuery query
        )
        {
            //
            // Validation ...
            if (query.IsNull())
            {
                XException.InvalidArgs.Throw();
            }

            //
            // Normalize ...
            query = query.NormalizeQuery(DataConfiguration.ToXDataServiceConfig());

            //
            var xUser = await ValidateUserExistsAndRetrieve(
                userSelectByParam,
                containDetails: true,
                checkCanLoginPolicies: true,
                checkIsBanned: true
            );

            //
            var items = query.ContainsDetail ?
                DbContext.Avatars
                .Include(pf => pf.User)
                .AsEnumerable() :
                DbContext.Avatars
                    .AsEnumerable();
            items = items
                .Where(pfi => pfi.UserId == xUser.Id);

            //
            var totalItemsCount = items.Count();

            //
            // Apply Filter ...
            if (!query.Filter.IsNullOrEmpty())
            {
                //
                items = items
                    .ApplyFilter(query.Filter);
            }
            int filteredItemsCount = items.Count();

            //
            // Count Pages ...
            var totalPagesCount = query.CountPages(totalItemsCount);
            var filteredPagesCount = query.CountPages(filteredItemsCount);

            //
            // Apply Paging and Sorting ...
            if (totalItemsCount > 0 &&
                filteredItemsCount > 0)
            {
                //
                // Apply Sorting ...
                items = items
                    .ToList()
                    .ApplySorting(
                        query.SortBy,
                        query.IsAscending
                    );

                //
                // Apply Paging ...
                items = items
                    .ToList()
                    .ApplyPaging(
                        query.Page,
                        query.PageSize
                    );
            }

            //
            // Generate Result Object ...
            // Query = query,
            var result = new XQueryResult<XProfileImage>
            {
                Items = items,
                Page = query.Page,
                PageSize = query.PageSize,
                TotalPages = totalPagesCount,
                TotalItems = totalItemsCount,
                TotalFilteredPages = filteredPagesCount,
                TotalFilteredItems = filteredItemsCount
            };

            //
            return result;
        }

        /// <summary>
        /// Check specific user Confirmed Email or not
        /// </summary>
        /// <param name="userSelectByParam">a user identifier</param>
        /// <returns>a boolean value</returns>
        public async Task<bool> IsConfirmedEmail(
            string userSelectByParam
        )
        {
            //
            // Validate Args ...
            ValidationProvider.NotEmpty(userSelectByParam);

            //
            var xUser = await ValidateUserExistsAndRetrieve(
                userSelectByParam,
                containDetails: false,
                checkCanLoginPolicies: false,
                checkIsBanned: false,
                ignoreDisabledUser: true,
                forceAdmin: false
            );

            //
            return xUser.EmailConfirmed;
        }

        /// <summary>
        /// Ceck specific user Confirmed Mobile or not
        /// </summary>
        /// <param name="userSelectByParam">a user identifier</param>
        /// <returns>a boolean value</returns>
        public async Task<bool> IsConfirmedMobile(
            string userSelectByParam
        )
        {
            //
            // Validate Args ...
            ValidationProvider.NotEmpty(userSelectByParam);

            //
            var xUser = await ValidateUserExistsAndRetrieve(
                userSelectByParam,
                containDetails: false,
                checkCanLoginPolicies: false,
                checkIsBanned: false,
                ignoreDisabledUser: true,
                forceAdmin: false
            );

            //
            return xUser.PhoneNumberConfirmed;
        }
        #endregion

        //
        #region Update Actions ...
        /// <summary>
        /// Update User Profile (FirstName/LastName/DateOfBirth) ...
        /// </summary>
        /// <param name="userSelectByParam">a user identifier</param>
        /// <param name="requestedUserSelectByParam">requested user's identifier</param>
        /// <param name="model">user update info, an instance of <see>XProfileUpdateRequest</see></param>
        /// <returns>an instance of <see>XUserProfileDto</see></returns>
        public async Task<XUserProfileDto> ProfileUpdateAsync(
            string userSelectByParam,
            string requestedUserSelectByParam,
            XProfileUpdateRequest model
        )
        {
            //
            // Data Validation ...
            ValidationProvider.NotEmpty(
                userSelectByParam,
                requestedUserSelectByParam);
            ValidationProvider.NotNull(model);

            //
            var xUser = await ValidateUserExistsAndRetrieve(
                userSelectByParam,
                containDetails: true,
                checkCanLoginPolicies: false,
                checkIsBanned: false,
                ignoreDisabledUser: true,
                forceAdmin: false
            );

            //
            var xRequestedUser = await ValidateUserExistsAndRetrieve(
                requestedUserSelectByParam,
                containDetails: true,
                checkCanLoginPolicies: false,
                checkIsBanned: false,
                ignoreDisabledUser: true,
                forceAdmin: false
            );

            //
            await ValidateUserForDangerousAction(xUser, xRequestedUser);

            //
            // FirstName ...
            if (!model.FirstName.IsNullOrEmpty())
            {
                xUser.FirstName = model.FirstName;
            }

            //
            // Last Name ...
            if (!model.LastName.IsNullOrEmpty())
            {
                xUser.LastName = model.LastName;
            }

            //
            // Date of Birth ...
            if (model.DateOfBirth.HasValue)
            {
                xUser.DateOfBirth = model.DateOfBirth.Value;
            }

            //
            // Bio ...
            xUser.Bio = model.Bio;

            //
            // Cover Image ...
            xUser.CoverImage = model.CoverImage;

            //
            // Open To Search ...
            xUser.OpenToSearch = model.OpenToSearch;

            //
            var updateResult = await UpdateUserAsync(xUser);
            if (!updateResult.Succeeded)
            {
                XException.ActionFailed.Throw();
            }

            //
            var result = await GetUserProfileAsync(userSelectByParam, requestedUserSelectByParam);
            return result;
        }

        /// <summary>
        /// Update User Profile
        /// </summary>
        /// <param name="userSelectByParam">a user identifier</param>
        /// <param name="requestedUserSelectByParam">requested user's identifier</param>
        /// <param name="model">user update info, an instance of <see>XProfileUpdateRequest</see></param>
        /// <returns>an instance of <see>XUserProfileDto</see></returns>
        public async Task<XUserProfileDto> FullProfileUpdateAsync(
            string userSelectByParam,
            string requestedUserSelectByParam,
            XProfileUpdateRequest model
        )
        {
            //
            // Data Validation ...
            ValidationProvider.NotEmpty(
                userSelectByParam,
                requestedUserSelectByParam);
            ValidationProvider.NotNull(model);

            //
            var xUser = await ValidateUserExistsAndRetrieve(
                userSelectByParam,
                containDetails: true,
                checkCanLoginPolicies: false,
                checkIsBanned: false,
                ignoreDisabledUser: true,
                forceAdmin: false
            );

            //
            var xRequestedUser = await ValidateUserExistsAndRetrieve(
                requestedUserSelectByParam,
                containDetails: true,
                checkCanLoginPolicies: false,
                checkIsBanned: false,
                ignoreDisabledUser: true,
                forceAdmin: false
            );

            //
            await ValidateUserForDangerousAction(xUser, xRequestedUser);

            //
            #region Fill User with Models Value ...
            //
            // FirstName ...
            xUser.FirstName = !model.FirstName.IsNullOrEmpty() ?
                model.FirstName :
                xUser.FirstName;
            //
            // LastName ...
            xUser.LastName = !model.LastName.IsNullOrEmpty() ?
                model.LastName :
                xUser.LastName;

            //
            // Email ...
            xUser.Email = !model.Email.IsNullOrEmpty() ?
                model.Email :
                xUser.Email;

            //
            // EmailConfirmed ...
            if (model.EmailConfirmed.HasValue)
            {
                xUser.EmailConfirmed = model.EmailConfirmed.Value;
            }

            //
            // PhoneNumber ...
            xUser.PhoneNumber = !model.PhoneNumber.IsNullOrEmpty() ?
                model.PhoneNumber :
                xUser.PhoneNumber;

            //
            // PhoneNumberConfirmed ,,,
            if (model.PhoneNumberConfirmed.HasValue)
            {
                xUser.PhoneNumberConfirmed = model.PhoneNumberConfirmed.Value;
            }

            //
            // DateOfBirth ...
            if (model.DateOfBirth.HasValue)
            {
                xUser.DateOfBirth = model.DateOfBirth.Value;
            }

            //
            // CreationDate ...
            if (model.CreationDate.HasValue)
            {
                xUser.CreationDate = model.CreationDate.Value;
            }

            //
            // LastLogin ...
            if (model.LastLogin.HasValue)
            {
                xUser.LastLogin = model.LastLogin.Value;
            }

            //
            // Avatar ...
            xUser.Avatar = !model.Avatar.IsNullOrEmpty() ?
                model.Avatar :
                xUser.Avatar;

            //
            // Gender ...
            if (model.Gender.HasValue)
            {
                xUser.Gender = model.Gender.Value;
            }

            //
            // IsEnable ...
            if (model.IsEnable.HasValue)
            {
                xUser.IsEnable = model.IsEnable.Value;
            }

            //
            // IsBanned ...
            if (model.IsBanned.HasValue)
            {
                xUser.IsBanned = model.IsBanned.Value;
            }

            //
            // Bio ...
            xUser.Bio = model.Bio;

            //
            // Cover Image ...
            xUser.CoverImage = model.CoverImage;

            //
            // Open To Search ...
            xUser.OpenToSearch = model.OpenToSearch;
            #endregion

            //
            var updateResult = await UpdateUserAsync(
                xUser,
                checkCanLoginPolicies: false,
                checkIsBanned: false
            );
            if (!updateResult.Succeeded)
            {
                XException.ActionFailed.Throw();
            }

            //
            // Handle Roles ...

            //
            // Remove User from All Roles ...
            if (xUser.Roles.HasChild())
            {
                //
                var roleNames = await GetRoleNamesAsync(
                    xUser.Id,
                    checkIsBanned: false,
                    checkCanLoginPolicies: false
                );

                //
                foreach (var role in roleNames)
                {
                    //
                    var isRoleExists = await IsRoleExistsAsync(role);
                    if (isRoleExists)
                    {
                        //
                        var isInRole = await UserManager.IsInRoleAsync(xUser, role);
                        if (!isInRole)
                        {
                            //
                            var removeRoleResult = await UserManager.RemoveFromRoleAsync(xUser, role);
                            if (!removeRoleResult.Succeeded)
                            {
                                XException.ActionFailed.Throw();
                            }
                        }
                    }
                }
            }

            //
            // Check Roles and Add to Exists ...
            if (model.Roles.HasChild())
            {
                //
                // Check Exists Roles for Add ...
                foreach (var role in model.Roles)
                {
                    //
                    var isRoleExists = await IsRoleExistsAsync(role);
                    if (isRoleExists)
                    {
                        //
                        var isInRole = await UserManager.IsInRoleAsync(xUser, role);
                        if (!isInRole)
                        {
                            //
                            var addToRoleResult = await UserManager.AddToRoleAsync(xUser, role);
                            if (!addToRoleResult.Succeeded)
                            {
                                XException.ActionFailed.Throw();
                            }
                        }
                    }
                }
            }

            //
            var result = await GetUserProfileAsync(
                userSelectByParam,
                requestedUserSelectByParam,
                checkCanLoginPolicies: false,
                checkIsBanned: false
            );
            return result;
        }
        #endregion

        //
        #region Request For Actions ...
        /// <summary>
        /// Request Mobile Confirm
        /// </summary>
        /// <param name="lang">specify destination language</param>
        /// <param name="device">an instance of <see>XDevice</see></param>
        /// <param name="userSelectByParam">a user identifier</param>
        /// <param name="password">user's password</param>
        /// <param name="mobileNumber">mobile number which need to confirm</param>
        /// <returns>an instance of <see>XActionResponse</see></returns>
        public async Task<XActionResponse> RequestConfirmMobile(
            string lang,
            XDevice device,
            string userSelectByParam,
            string password,
            string mobileNumber = null
        )
        {
            //
            // Validate Args ...
            await ValidationProvider
                .GroupValidationBuilder()
                .AddNotEmpty(
                    lang,
                    userSelectByParam,
                    password)
                .AddNotNull(device)
                .ValidateGroupAsync();

            //
            await ValidateDeviceForActions(device);

            //
            // Prepare Request Context ...
            var context = new XActionRequestContext
            {
                Lang = lang,
                Device = device,
                MobileNumber = mobileNumber
            };

            //
            // Validate and Retrieve User ...
            var user = await ValidateUserExistsAndRetrieve(
                userSelectByParam,
                containDetails: false,
                checkCanLoginPolicies: false,
                checkIsBanned: false);

            //
            context.UserName = user.UserName;

            //
            await ValidateUserAndPassword(
                userSelectByParam,
                password,
                false,
                XException.ActionFailed.ToException());

            //            
            ValidationProvider.MobileNumber(user.PhoneNumber);
            if (!mobileNumber.IsNullOrEmpty() &&
                user.PhoneNumber == mobileNumber &&
                user.PhoneNumberConfirmed)
            {
                XException.MobileInUsed.Throw();
            }

            //
            if (mobileNumber.IsNullOrEmpty())
            {
                mobileNumber = user.PhoneNumber;
            }

            //
            // Remove All Prevoius Requests ...
            await HandleRemoveExistsTokens(user.Id);

            //
            // Prepare New Token Result ,
            // by Requesting an Action ...
            var request = await ActionRequest(
                lang,
                device,
                userSelectByParam,
                XAction.RequestMobileVerificationCode,
                context,
                forceRenewToken: true
            );

            //
            Logger.LogInformation($"ActionRequest: {request.ToJSON()}");

            //
            // Call Confirm Method of Registration ...
            var result = await RequestMobileVerificationCode(
                lang,
                device,
                request.Token,
                mobileNumber,
                checkMobileInUse: false);

            //
            return result;
        }

        /// <summary>
        /// Request Email Confirma
        /// </summary>
        /// <param name="lang">specify destination language</param>
        /// <param name="device">an instance of <see>XDevice</see></param>
        /// <param name="userSelectByParam">a user identifier</param>
        /// <param name="password">user's password</param>
        /// <param name="emailAddress">email address which need to confirm</param>
        /// <returns>an instance of <see>XActionResponse</see></returns>
        public async Task<XActionResponse> RequestConfirmEmail(
            string lang,
            XDevice device,
            string userSelectByParam,
            string password,
            string emailAddress = null
        )
        {
            //
            // Validate Args ...
            await ValidationProvider
                .GroupValidationBuilder()
                .AddNotEmpty(
                    lang,
                    userSelectByParam,
                    password)
                .AddNotNull(device)
                .ValidateGroupAsync();

            //
            await ValidateDeviceForActions(device);

            //
            // Prepare Request Context ...
            var context = new XActionRequestContext
            {
                Lang = lang,
                Device = device,
                Email = emailAddress
            };

            //
            // Validate and Retrieve User ...
            var user = await ValidateUserExistsAndRetrieve(
                userSelectByParam,
                containDetails: false,
                checkCanLoginPolicies: false,
                checkIsBanned: false);

            //
            context.UserName = user.UserName;

            //
            // Remove All Prevoius Requests ...
            await HandleRemoveExistsTokens(user.Id);

            //
            await ValidateUserAndPassword(
                userSelectByParam,
                password,
                false,
                XException.ActionFailed.ToException());

            //            
            ValidationProvider.EmailAddress(user.Email);
            if (!emailAddress.IsNullOrEmpty() &&
                user.Email == emailAddress &&
                user.EmailConfirmed)
            {
                XException.EmailInUsed.Throw();
            }

            //
            if (emailAddress.IsNullOrEmpty())
            {
                emailAddress = user.Email;
                context.Email = user.Email;
            }

            //
            // Prepare New Token Result ,
            // by Requesting an Action ...
            var request = await ActionRequest(
                lang,
                device,
                userSelectByParam,
                XAction.RequestEmailVerificationCode,
                context,
                forceRenewToken: true
            );

            //
            // Call Confirm Method of Registration ...
            var result = await RequestEmailVerificationCode(
                lang,
                device,
                request.Token,
                emailAddress,
                checkEmailInUse: false);

            //
            return result;
        }

        /// <summary>
        /// Request Reset Password 
        /// </summary>
        /// <param name="lang">specify destination language</param>
        /// <param name="device">an instance of <see>XDevice</see></param>
        /// <param name="userSelectByParam">a user identifier</param>
        /// <param name="returnUrl">redirection url</param>
        /// <returns>an instance of <see>XActionResponse</see></returns>
        public async Task<XActionResponse> RequestResetPassword(
            string lang,
            XDevice device,
            string userSelectByParam,
            string returnUrl
        )
        {
            //
            // Validate Args ...
            await ValidationProvider
                .GroupValidationBuilder()
                .AddNotEmpty(
                    lang,
                    userSelectByParam,
                    returnUrl)
                .AddNotNull(device)
                .AddUrl(returnUrl)
                .ValidateGroupAsync();

            //
            await ValidateDeviceForActions(device);

            //
            // Validate and Retrieve User ...
            var user = await ValidateUserExistsAndRetrieve(
                userSelectByParam,
                containDetails: false,
                checkCanLoginPolicies: true,
                checkIsBanned: true);

            //
            // Prepare Request Context ...
            var context = new XActionRequestContext
            {
                Lang = lang,
                Device = device,
                Email = user.Email,
                UserName = user.UserName
            };

            //
            // Remove All Prevoius Requests ...
            await HandleCleanUserTokens(user);

            //
            // Prepare New Token Result ,
            // by Requesting an Action ...
            var result = await ActionRequest(
                lang,
                device,
                user.Email,
                XAction.RequestResetPassword,
                context
            );

            //
            // Prepare Message ...
            var xMessage = GetResetPasswordMessage(
                lang,
                user.Email,
                result.Token,
                returnUrl);

            //
            try
            {
                await MessageProvider.SendMailAsync(xMessage);
            }
            catch { }

            //
            return result;
        }

        /// <summary>
        /// Request Registration Confrirm
        /// </summary>
        /// <param name="lang">specify destination language</param>
        /// <param name="device">an instance of <see>XDevice</see></param>
        /// <param name="userSelectByParam">a user identifier</param>
        /// <param name="password">user's password</param>
        /// <param name="returnUrl">redirection url</param>
        /// <returns></returns>
        public async Task RequestConfirmRegistration(
            string lang,
            XDevice device,
            string userSelectByParam,
            string password,
            string returnUrl
        )
        {
            //
            // Validate Args ...
            await ValidationProvider
                .GroupValidationBuilder()
                .AddNotEmpty(
                    lang,
                    userSelectByParam,
                    password,
                    returnUrl)
                .AddNotNull(device)
                .AddUrl(returnUrl)
                .ValidateGroupAsync();

            //
            // Validate user and Retrieve it ...
            var user = await ValidateUserExistsAndRetrieve(
                userSelectByParam,
                containDetails: false,
                checkCanLoginPolicies: false,
                checkIsBanned: true,
                ignoreDisabledUser: true);

            //
            // Prepare Request Context ...
            var context = new XActionRequestContext
            {
                Lang = lang,
                Device = device,
                Email = user.Email
            };

            //
            await ValidateUserAndPassword(
                userSelectByParam,
                password,
                false,
                XException.ActionFailed.ToException());

            //
            // Remove All Prevoius Requests ...
            await HandleRemoveExistsTokens(user.Id);

            //
            // Prepare New Token Result ,
            // by Requesting an Action ...
            var result = await ActionRequest(
                lang,
                device,
                user.Email,
                XAction.Finish,
                context
            );

            //
            // Prepare XMessage Instance ...
            var xMessage = GetRegistrationConfirmMessage(
                lang,
                user.Email,
                result.Token,
                returnUrl);

            //
            // Send Message ...
            try
            {
                await MessageProvider.SendMailAsync(xMessage);
            }
            catch { }
        }
        #endregion

        //
        #region Password Actions ...
        /// <summary>
        /// Change Password
        /// </summary>
        /// <param name="lang">specify destination language</param>
        /// <param name="device">an instance of <see>XDevice</see></param>
        /// <param name="userSelectByParam">a user identifier</param>
        /// <param name="password">user's password</param>
        /// <param name="newPassword">user's new password</param>
        /// <param name="returnUrl">redirection url</param>
        /// <returns></returns>
        public async Task ChangePassword(
            string lang,
            XDevice device,
            string userSelectByParam,
            string password,
            string newPassword,
            string returnUrl
        )
        {
            //
            // Validate Args ...
            await ValidationProvider
                .GroupValidationBuilder()
                .AddNotEmpty(
                    lang,
                    userSelectByParam,
                    password,
                    newPassword,
                    returnUrl)
                .AddNotNull(device)
                .ValidateGroupAsync();

            //
            // Password Unique ...
            if (password == newPassword)
            {
                XException.PasswordsSame.Throw();
            }

            //
            // Validate and Retrieve User ...
            var user = await ValidateUserExistsAndRetrieve(
                userSelectByParam,
                containDetails: false,
                checkCanLoginPolicies: true,
                checkIsBanned: true);

            //
            await ValidateUserAndPassword(
                userSelectByParam,
                password);

            //
            // Check Password Policies ...
            await ValidatePasswordPolicies(user, newPassword);

            //
            // Clean All User Tokens ...
            await HandleCleanUserTokens(user);

            //
            // Try to Change User Password ...
            var passwordResetResult = await UserManager
                .ChangePasswordAsync(
                    user,
                    password,
                    newPassword);

            //
            // Check Result ...
            if (!passwordResetResult.Succeeded)
            {
                XException.ActionFailed.Throw();
            }

            //
            // Prepare Message ...
            var xMessage = GetPasswordChangedMessage(
                lang,
                user.Email,
                returnUrl,
                throwException: false
            );

            //
            // Send Message ...
            try
            {
                await MessageProvider.SendMailAsync(xMessage);
            }
            catch { }
        }

        /// <summary>
        /// Reset User Password
        /// </summary>
        /// <param name="lang">specify destination language</param>
        /// <param name="device">an instance of <see>XDevice</see></param>
        /// <param name="actionToken">a token which approved user action</param>
        /// <param name="newPassword">user's new password</param>
        /// <param name="returnUrl">redirection url</param>
        /// <returns></returns>
        public async Task ResetPassword(
            string lang,
            XDevice device,
            string actionToken,
            string newPassword,
            string returnUrl
        )
        {
            //
            // Validate Args ...
            await ValidationProvider
                .GroupValidationBuilder()
                .AddNotEmpty(
                    lang,
                    actionToken,
                    newPassword,
                    returnUrl)
                .AddNotNull(device)
                .ValidateGroupAsync();

            //
            // Get Related Token to Registration Hash and Validate it,
            // then Parse XActionRequest Instance from Token ...
            var request = await ValidateAndParseActionHash(actionToken);

            //
            // Get User Identifier ...
            var userSelectByParam = GetUserSelectByParam(request);

            //
            // Validate and Retrieve User ...
            var user = await ValidateUserExistsAndRetrieve(
                userSelectByParam,
                containDetails: false,
                checkCanLoginPolicies: true,
                checkIsBanned: true);

            //
            // Check Password Policies ...
            await ValidatePasswordPolicies(user, newPassword);

            //
            // Clean All User Tokens ...
            await HandleCleanUserTokens(user);

            //
            // Try to Remove User Password ...
            var removePasswordResult = await UserManager.RemovePasswordAsync(user);
            if (!removePasswordResult.Succeeded)
            {
                XException.ActionFailed.Throw();
            }

            //
            // try to Add New Password ...
            var passwordResetResult = await UserManager.AddPasswordAsync(user, newPassword);
            if (!passwordResetResult.Succeeded)
            {
                XException.ActionFailed.Throw();
            }

            //
            // Prepare Message ...
            var xMessage = GetPasswordChangedMessage(
                lang,
                user.Email,
                returnUrl);

            //
            // Send Message ...
            try
            {
                await MessageProvider.SendMailAsync(xMessage);
            }
            catch { }
        }
        #endregion

        //
        #region Profile Image Actions ...
        /// <summary>
        /// Add Profile Image to a User
        /// </summary>
        /// <param name="userSelectByParam">a user identifier</param>
        /// <param name="file">an specific File to upload, <see>IFormFile</see></param>
        /// <returns>an instance of <see>XUserProfileDto</see></returns>
        public async Task<XUserProfileDto> AddAvatar(
            string userSelectByParam,
            IFormFile file
        )
        {
            //
            var xUser = await ValidateUserExistsAndRetrieve(
                userSelectByParam,
                containDetails: true,
                checkCanLoginPolicies: false,
                checkIsBanned: false,
                ignoreDisabledUser: true,
                exception: XException.NotFound.ToException()
            );

            //
            // Handle Saving File and Attach it to User ...
            var saveResult = await StorageProvider.HandleProfileImageSave(file);

            //
            var xProfileImage = new XProfileImage
            {
                UserId = xUser.Id,
                Name = saveResult.FileName,
                Path = saveResult.FilePath,
                Thumb = saveResult.Thmbnail,
                ThumbPath = saveResult.ThmbnailPath,
                CreationDate = DateTime.UtcNow
            };

            //
            xUser.Avatars.Add(xProfileImage);
            var updateResult = await UpdateUserAsync(
                xUser,
                checkCanLoginPolicies: false,
                checkIsBanned: false
            );

            //
            if (!updateResult.Succeeded)
            {
                XException.ActionFailed.Throw();
            }

            //
            xUser.Avatar = xProfileImage.ThumbPath;
            updateResult = await UpdateUserAsync(
                xUser,
                checkCanLoginPolicies: false,
                checkIsBanned: false
            );

            //
            if (!updateResult.Succeeded)
            {
                XException.ActionFailed.Throw();
            }

            //
            var result = await GetUserProfileAsync(userSelectByParam, userSelectByParam);
            return result;
        }

        /// <summary>
        /// Add a Collection of Profile Images to a User
        /// </summary>
        /// <param name="userSelectByParam">a user identifier</param>
        /// <param name="files">a collection of Files to upload, <see>IFormFileCollection</see></param>
        /// <returns>an instance of <see>XUserProfileDto</see></returns>
        public async Task<XUserProfileDto> AddAvatars(
            string userSelectByParam,
            IFormFileCollection files
        )
        {
            //
            var xUser = await ValidateUserExistsAndRetrieve(
                userSelectByParam,
                containDetails: true,
                checkCanLoginPolicies: false,
                checkIsBanned: false,
                ignoreDisabledUser: true,
                exception: XException.NotFound.ToException()
            );

            //
            foreach (var file in files)
            {
                //
                // Handle Saving File and Attach it to User ...
                var saveResult = await StorageProvider.HandleProfileImageSave(file);

                //
                var xProfileImage = new XProfileImage
                {
                    UserId = xUser.Id,
                    Name = saveResult.FileName,
                    Path = saveResult.FilePath,
                    Thumb = saveResult.Thmbnail,
                    ThumbPath = saveResult.ThmbnailPath,
                    CreationDate = DateTime.UtcNow
                };

                //
                xUser.Avatars.Add(xProfileImage);
            }

            //
            var updateResult = await UpdateUserAsync(
                xUser,
                checkCanLoginPolicies: false,
                checkIsBanned: false
            );

            //
            if (!updateResult.Succeeded)
            {
                XException.ActionFailed.Throw();
            }

            //
            var result = await GetUserProfileAsync(userSelectByParam, userSelectByParam);
            return result;
        }

        /// <summary>
        /// Set Specific Profie Image as Current Profile Image
        /// </summary>
        /// <param name="userSelectByParam">a user identifier</param>
        /// <param name="id">an integer which reperesent AvatarId to set as current Avatar</param>
        /// <returns>an instance of <see>XUserProfileDto</see></returns>
        public async Task<XUserProfileDto> SetAvatar(
            string userSelectByParam,
            int id
        )
        {
            //
            ValidationProvider.NotEmpty(userSelectByParam);

            //
            var xUser = await ValidateUserExistsAndRetrieve(
                userSelectByParam,
                containDetails: true,
                checkCanLoginPolicies: false,
                checkIsBanned: false,
                ignoreDisabledUser: true,
                exception: XException.NotFound.ToException()
            );

            //
            var xProfileImage = xUser.Avatars.FirstOrDefault(pf => pf.Id == id);
            if (xProfileImage.IsNull())
            {
                XException.NotFound.Throw();
            }

            //
            xUser.Avatar = xProfileImage.ThumbPath;
            var updateResult = await UpdateUserAsync(
                xUser,
                checkCanLoginPolicies: false,
                checkIsBanned: false
            );

            //
            if (!updateResult.Succeeded)
            {
                XException.ActionFailed.Throw();
            }

            //
            var result = await GetUserProfileAsync(userSelectByParam, userSelectByParam);
            return result;
        }

        /// <summary>
        /// Remove a Collection of User's Profile Images
        /// </summary>
        /// <param name="userSelectByParam">a user identifier</param>
        /// <param name="ids">a comma seperated list of avatarIds to remove</param>
        /// <returns>an instance of <see>XUserProfileDto</see></returns>
        public async Task<XUserProfileDto> RemoveAvatar(
            string userSelectByParam,
            ICollection<int> ids
        )
        {
            //
            ValidationProvider.NotEmpty(userSelectByParam);

            //
            var xUser = await ValidateUserExistsAndRetrieve(
                userSelectByParam,
                containDetails: true,
                checkCanLoginPolicies: false,
                checkIsBanned: false,
                ignoreDisabledUser: true,
                exception: XException.NotFound.ToException()
            );

            //
            var xProfileImages = xUser.Avatars
                .Where(pf => ids.Contains(pf.Id));
            if (xProfileImages.HasChild())
            {
                //
                xUser.Avatars = xUser.Avatars
                    .Except(xProfileImages)
                    .ToList();

                //
                // Creat a List of Physical Files to Remove ...
                var xFilePathsForRemove = xProfileImages.Select(pf => pf.Thumb).ToList();
                xFilePathsForRemove.AddRange(xProfileImages.Select(pf => pf.Name));

                //
                StorageProvider.DeleteFiles(
                    xFilePathsForRemove,
                    forceFileExists: false);

                //
                var isCurrentProfileImage = xProfileImages.Any(pfi => pfi.ThumbPath == xUser.Avatar);
                if (isCurrentProfileImage)
                {
                    xUser.Avatar = "";
                }

                //
                await UpdateUserAsync(xUser);
            }

            //
            var result = await GetUserProfileAsync(userSelectByParam, userSelectByParam);
            return result;
        }
        #endregion

        //
        #region Confirmations ...
        /// <summary>
        /// Confirm Registration
        /// </summary>
        /// <param name="lang">specify destination language</param>
        /// <param name="device">an instance of <see>XDevice</see></param>
        /// <param name="actionToken">a token which approved user action</param>
        /// <param name="returnUrl">redirection url</param>
        /// <returns></returns>
        public async Task ConfirmRegistration(
            string lang,
            XDevice device,
            string actionToken,
            string returnUrl
        )
        {
            //
            // Validate Args ...
            await ValidationProvider
                .GroupValidationBuilder()
                .AddNotEmpty(
                    lang,
                    actionToken,
                    returnUrl)
                .AddNotNull(device)
                .ValidateGroupAsync();

            //
            // Check Device Validation ...
            await ValidateDeviceForActions(device);

            //
            // Get Related Token to Registration Hash and Validate it,
            // then Parse XActionRequest Instance from Token ...
            var request = await ValidateAndParseActionHash(actionToken);
            if (request.Action != XAction.Finish)
            {
                XException.ActionFailed.Throw();
            }

            //
            // Extract UserSelectByParam from XActionRequest ...
            var userSelectByParam = GetUserSelectByParam(
                request,
                forceNotNull: true);

            //
            // Validate user and Retrieve it ...
            var user = await ValidateUserExistsAndRetrieve(
                userSelectByParam,
                containDetails: false,
                checkCanLoginPolicies: false,
                ignoreDisabledUser: true,
                checkIsBanned: true);

            //
            // Make User Enabled ...
            var xMessage = GetRegistrationFinishedMessage(
                lang,
                user.Email,
                returnUrl);

            //
            user.IsEnable = true;
            user.EmailConfirmed = true;

            //
            await UpdateUserAsync(
                user,
                checkCanLoginPolicies: false,
                checkIsBanned: false
            );

            //
            // Remove Token ...
            await RemoveTokenByHash(actionToken);

            //
            // Remove All Prevoius Requests ...
            await HandleRemoveExistsTokens(user.Id);

            //
            await RemoveVerificationCodeRequestByDevice(device);

            //
            // Send Mail ...
            try
            {
                await MessageProvider.SendMailAsync(xMessage);
            }
            catch { }
        }

        /// <summary>
        /// Confirm Mobile Number
        /// </summary>
        /// <param name="lang">specify destination language</param>
        /// <param name="device">an instance of <see>XDevice</see></param>
        /// <param name="actionToken">a token which approved user action</param>
        /// <param name="verificationCode">recieved verification code</param>
        /// <returns>an instance of <see>XActionResponse</see></returns>
        public async Task<XActionResponse> ConfirmMobileNumber(
            string lang,
            XDevice device,
            string actionToken,
            string verificationCode
        )
        {
            //
            // Validate Args ...
            await ValidationProvider
                .GroupValidationBuilder()
                .AddNotEmpty(lang, actionToken, verificationCode)
                .AddNotNull(device)
                .ValidateGroupAsync();

            //
            // Check Device Validation ...
            await ValidateDeviceForActions(device);

            //
            // Get Related Token to Registration Hash and Validate it,
            // then Parse XActionRequest Instance from Token ...
            var request = await ValidateAndParseActionHash(actionToken);
            ValidationProvider.MobileNumber(request.Context.MobileNumber);

            //
            // Validate two Device Must Same ...
            ValidateRequestAndGiveDevices(device, request.Context.Device);

            //
            // Check XActionRequest Action Must be Request Mobile Validation ...
            if (request.Action != XAction.RequestMobileVerificationCode)
            {
                XException.InvalidData.Throw();
            }

            //
            // Extract UserSelectByParam from XActionRequest ...
            var userSelectByParam = GetUserSelectByParam(request);

            //
            // since device must Requested before, 
            // Retrieve XVerification instance by Verification Code from Db
            // and Validate it ...
            XVerificationRequest xVerificationRequest = await ValidateAndRetrieveVerificationRequest(verificationCode);

            //
            // Check User Added To Db or Not ...
            // var isUserExists = await IsUserExistsAsync(userSelectByParam);
            var isAddedUser = !request.Context.UserId.IsNullOrEmpty();
            if (isAddedUser)
            {
                //
                // Validate User Exists and Retireve User Object ...
                var user = await ValidateUserExistsAndRetrieve(
                    userSelectByParam,
                    containDetails: false,
                    checkCanLoginPolicies: false,
                    checkIsBanned: false);

                //
                // Update Exists User's Mobile Confirmation ...
                user.PhoneNumberConfirmed = true;

                //
                // Save Changes to Db ...
                await UpdateUserAsync(user, checkCanLoginPolicies: false, checkIsBanned: false);

                //
                request.Context.UserId = user.Id;
            }

            //
            // Update Request Context MobileNumber Verification Code
            // and it's Confirmation Status ...
            request.Context.MobileVerificationCode = verificationCode;
            request.Context.MobileVerified = true;

            //
            // Prepare New Token Result ,
            // by Requesting an Action ...
            var result = await ActionRequest(
                lang,
                device,
                userSelectByParam,
                XAction.ConfirmMobileNumber,
                request.Context,
                forceCheckUserExists: isAddedUser
            );

            //
            // Remove Previous Token ...
            await RemoveTokenByHash(actionToken);

            try
            {
                //
                // Remove XVerificationRequest instance from Db ...
                await RemoveVerificationRequest(verificationCode);
            }
            catch { }

            //
            // Return Result ...
            return result;
        }

        /// <summary>
        /// Confirm Email Address
        /// </summary>
        /// <param name="lang">specify destination language</param>
        /// <param name="device">an instance of <see>XDevice</see></param>
        /// <param name="actionToken">a token which approved user action</param>
        /// <param name="verificationCode">recieved verification code</param>
        /// <returns>an instance of <see>XActionResponse</see></returns>
        public async Task<XActionResponse> ConfirmEmailAddress(
            string lang,
            XDevice device,
            string actionToken,
            string verificationCode
        )
        {
            //
            // Validate Args ...
            await ValidationProvider
                .GroupValidationBuilder()
                .AddNotEmpty(lang, actionToken, verificationCode)
                .AddNotNull(device)
                .ValidateGroupAsync();

            //
            // Check Device Validation ...
            await ValidateDeviceForActions(device);

            //
            // Get Related Token to Registration Hash and Validate it,
            // then Parse XActionRequest Instance from Token ...
            var request = await ValidateAndParseActionHash(actionToken);
            ValidationProvider.EmailAddress(request.Context.Email);

            //
            // Validate two Device Must Same ...
            ValidateRequestAndGiveDevices(device, request.Context.Device);

            //
            // Check XActionRequest Action Must be Request Mobile Validation ...
            if (request.Action != XAction.RequestEmailVerificationCode)
            {
                XException.InvalidData.Throw();
            }

            //
            // Extract UserSelectByParam from XActionRequest ...
            var userSelectByParam = GetUserSelectByParam(request);

            //
            // since device must Requested before, 
            // Retrieve XVerification instance by Verification Code from Db
            // and Validate it ...
            XVerificationRequest xVerificationRequest = await ValidateAndRetrieveVerificationRequest(verificationCode);

            //
            // Check User Added To Db or Not ...
            var isAddedUser = !request.Context.UserId.IsNullOrEmpty();
            if (isAddedUser)
            {
                //
                // Validate User Exists and Retireve User Object ...
                var user = await ValidateUserExistsAndRetrieve(
                    userSelectByParam,
                    containDetails: false,
                    checkCanLoginPolicies: false,
                    checkIsBanned: false);

                //
                // Update Exists User's Email Confirmation ...
                user.EmailConfirmed = true;

                //
                // Save Changes to Db ...
                await UpdateUserAsync(user, checkCanLoginPolicies: false, checkIsBanned: false);

                //
                request.Context.UserId = user.Id;
            }

            //
            // Update Request Context Email Address Verification Code
            // and it's Confirmation Status ...
            request.Context.EmailVerificationCode = verificationCode;
            request.Context.EmailVerified = true;

            //
            // Prepare New Token Result ,
            // by Requesting an Action ...
            var result = await ActionRequest(
                lang,
                device,
                userSelectByParam,
                XAction.ConfirmEmailAddress,
                request.Context,
                forceCheckUserExists: isAddedUser
            );

            //
            // Remove Previous Token ...
            await RemoveTokenByHash(actionToken);

            //
            // Remove XVerificationRequest instance from Db ...
            await RemoveVerificationRequest(verificationCode);

            //
            // Return Result ...
            return result;
        }
        #endregion
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\xIds\Providers\XIdentityManager\XIdentityManager+Query.cs

using System.Linq;
using System.Threading.Tasks;
using xCommons.Extensions;
using xDataService.Extensions;
using xExceptions.Constants;
using xIdentityModels.Extensions;
using xIds.Extensions;
using xModels.Dtos;

namespace xIds.Providers
{
    public partial class XIdentityManager
    {
        /// <summary>
        /// Retrieve Users as Query Model for Query Service ...
        /// </summary>
        /// <param name="requestedUserSelectByParam"></param>
        /// <param name="query"></param>
        /// <param name="role"></param>
        /// <param name="forceRole"></param>
        /// <returns></returns>
        public async Task<XQueryResult<string>> QueryUsers(
            string requestedUserSelectByParam,
            XQuery query,
            string role = null,
            bool forceRole = false
        )
        {
            //
            // Validation ...
            if (query.IsNull())
            {
                XException.InvalidArgs.Throw();
            }

            //
            // Normalize ...
            query = query.NormalizeQuery(DataConfiguration.ToXDataServiceConfig());

            //
            // Since in Resourceable Entities we have to Search on Locales
            // we Must Implement Senario Custom ...
            var items = GetUsersDbSet()
                .ToList()
                .Where(u => !u.ContainsUserSelectByParam(requestedUserSelectByParam))
                .ToList()
                .AsEnumerable();

            //
            var totalItemsCount = items.Count();

            //
            // Apply Filter ...
            if (!query.Filter.IsNullOrEmpty())
            {
                //
                items = items
                    .ApplyFilter(query.Filter);
            }
            int filteredItemsCount = items.Count();

            //
            // Count Pages ...
            var totalPagesCount = query.CountPages(totalItemsCount);
            var filteredPagesCount = query.CountPages(filteredItemsCount);

            //
            // Apply Paging and Sorting ...
            if (totalItemsCount > 0 &&
                filteredItemsCount > 0)
            {
                //
                // Apply Sorting ...
                items = items
                    .ToList()
                    .ApplySorting(
                        query.SortBy,
                        query.IsAscending
                    );

                //
                // Apply Paging ...
                items = items
                    .ToList()
                    .ApplyPaging(
                        query.Page,
                        query.PageSize
                    );
            }

            //
            // Generate Result Object ...
            // Query = query,
            var result = new XQueryResult<string>
            {
                Items = items
                    .Select(u => u.Id),
                Page = query.Page,
                PageSize = query.PageSize,
                TotalPages = totalPagesCount,
                TotalItems = totalItemsCount,
                TotalFilteredPages = filteredPagesCount,
                TotalFilteredItems = filteredItemsCount
            };

            //
            return await Task.Run(() => result);
        }
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\xIds\Providers\XIdentityManager\XIdentityManager+Registration.cs

using System;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Http;
using xCommons.Extensions;
using xExceptions.Constants;
using xIdentityModels;
using xIdentityModels.Constants;
using xIdentityModels.Models;
using xIdentityModels.Navigations;

namespace xIds.Providers
{
    public partial class XIdentityManager
    {
        //
        #region Registration Actions ...
        /// <summary>
        /// Invite a User to Register on Dashboard
        /// </summary>
        /// <param name="lang">specify destination language</param>
        /// <param name="device">an instance of <see>XDevice</see></param>
        /// <param name="email">which email address is going to invite</param>
        /// <param name="returnUrl">return url for invitation user to redirect</param>
        /// <returns>an instance of <see>XActionResponse</see></returns>
        public async Task<XActionResponse> InviteUser(
            string lang,
            XDevice device,
            string email,
            string returnUrl
        )
        {
            //
            // Validate Args ...
            await ValidationProvider
                .GroupValidationBuilder()
                .AddNotEmpty(
                    lang,
                    email,
                    returnUrl
                )
                .AddNotNull(device)
                .AddEmailAddress(email)
                .ValidateGroupAsync();

            //
            // Check Email is Unique ...
            await ValidateUserNotExists(email);

            //
            // Get Request Result ...
            var result = await ActionRequest(
                lang,
                device,
                email,
                XAction.Invite,
                forceCheckContext: false,
                forceCheckUserExists: false);

            //
            // Prepare Propper Message ...
            var xMessage = GetUserInviteMessage(lang, email, result.Token, returnUrl);

            //
            // Send Message ...
            try
            {
                await MessageProvider.SendMailAsync(xMessage);
            }
            catch { }

            //
            // Send Result ...
            return result;
        }

        /// <summary>
        /// Recieve some Basic Informations and Start Registration Proccess
        /// if they Valid 
        /// 
        /// Registration Proccess Starts with Invoking this Action
        /// </summary>
        /// <param name="lang">specify destination language</param>
        /// <param name="device">an instance of <see>XDevice</see></param>
        /// <param name="invitationHash">optional, if user invited, this is the invitation token</param>
        /// <param name="firstName">user's FirstName</param>
        /// <param name="lastName">user's LastName</param>
        /// <param name="dateOfBirth">user's dob date</param>
        /// <param name="mobileNumber">user's Mobile Number</param>
        /// <param name="emailAddress">user's Email address</param>
        /// <returns>an instance of <see>XActionResponse</see></returns>
        public async Task<XActionResponse> RequestRegistration(
            string lang,
            XDevice device,
            string invitationHash,
            string firstName,
            string lastName,
            DateTime dateOfBirth,
            string mobileNumber = null,
            string emailAddress = null
        )
        {
            //
            // Validate Args ...
            await ValidationProvider
                .GroupValidationBuilder()
                .AddNotEmpty(
                    lang,
                    firstName,
                    lastName
                )
                .AddNotNull(
                    device,
                    dateOfBirth
                )
                .ValidateGroupAsync();

            //
            // Validate Mobile Number if Exists ...
            if (!mobileNumber.IsNullOrEmpty())
            {
                //
                ValidationProvider.MobileNumber(mobileNumber);

                //
                // Check Mobile is Uniqsue ...
                await ValidateUserNotExists(mobileNumber);
            }

            //
            // Validate Email Address if Exists ...
            if (!emailAddress.IsNullOrEmpty())
            {
                //
                ValidationProvider.EmailAddress(emailAddress);

                //
                // Check Email is Unique ...
                await ValidateUserNotExists(emailAddress);
            }

            //
            // Get Related Token and Validate it and
            // Check Related Configurations ...
            await ValidateInvitationHash(invitationHash);

            //
            // Check Device Validation ...
            await ValidateDeviceForActions(device);

            //
            // Validate DateOfBirth ...
            ValidateDateOfBirth(dateOfBirth);

            //
            // Define Empty Objects for Using ...
            var userSelectByParam = "";
            var context = new XActionRequestContext();
            //
            context.Lang = lang;
            context.Device = device;
            context.LastName = lastName;
            context.FirstName = firstName;
            context.DateOfBirth = dateOfBirth;
            context.MobileNumber = mobileNumber ?? "";
            context.Email = !emailAddress.IsNullOrEmpty() ? emailAddress.ToNormalString() : "";

            //
            userSelectByParam = GetUserSelectByParam(context);

            //
            // Token Data Parsing ...
            if (!invitationHash.IsNullOrEmpty())
            {
                //
                // Get Related Token, Validate it and Parse Contains
                // XAction Request and Validate the Request itself and
                // Return it ...
                var inviteRequest = await ValidateAndParseActionHash(invitationHash);

                //
                // Extract User Select By Param and Type ...
                userSelectByParam = GetUserSelectByParam(inviteRequest);
                var userSelectBy = GetUserSelectByType(userSelectByParam);

                //
                // Check Invitation Only done with Email Address ...
                if (userSelectBy != XUserSelectBy.Email)
                {
                    XException.InvalidData.Throw();
                }

                //
                // Check Invited Email and Given Email to be Same ...
                if (emailAddress.IsNullOrEmpty() ||
                    (!emailAddress.IsNullOrEmpty() &&
                        !emailAddress.IsValidEmail()))
                {
                    XException.InvalidEmailAddress.Throw();
                }
                var isSameEmail = inviteRequest.Context.Email.ToNormalString() == emailAddress.ToNormalString();
                if (!isSameEmail)
                {
                    XException.EmailsSame.Throw();
                }

                //
                // Update Context Email for Request Action ...
                context.Email = userSelectByParam.ToNormalString();
                context.EmailVerified = true;
            }

            //
            var result = await ActionRequest(
                lang,
                device,
                userSelectByParam,
                XAction.Registration,
                context,
                forceCheckUserExists: false
            );

            //
            // Remove Invitation Token ...
            if (!invitationHash.IsNullOrEmpty())
            {
                await RemoveTokenByHash(invitationHash);
            }

            //
            // Return Result ...
            return result;
        }

        /// <summary>
        /// Add User Account Info
        /// </summary>
        /// <param name="lang">specify destination language</param>
        /// <param name="device">an instance of <see>XDevice</see></param>
        /// <param name="actionToken">a token which approved user action</param>
        /// <param name="userName">user name</param>
        /// <param name="password">assigne password</param>
        /// <returns>an instance of <see>XActionResponse</see></returns>
        public async Task<XActionResponse> AddAcountInfo(
            string lang,
            XDevice device,
            string actionToken,
            string userName,
            string password
        )
        {
            //
            // Validate Args ...
            await ValidationProvider
                .GroupValidationBuilder()
                .AddNotEmpty(
                    lang,
                    actionToken,
                    userName,
                    password)
                .AddNotNull(device)
                .ValidateGroupAsync();

            //
            // Check Device Validation ...
            await ValidateDeviceForActions(device);

            //
            // Validate a UserSelector is Available or not ...
            await ValidateCanRegister(userName);

            //
            // Check UserName is Unique ...
            await ValidateUserNotExists(userName);

            //
            // Get Related Token to Registration Hash and Validate it,
            // then Parse XActionRequest Instance from Token ...
            var request = await ValidateAndParseActionHash(actionToken);

            //
            // Validate Requeired Data for Register User must be in Action Context ...
            await ValidationProvider
                .GroupValidationBuilder()
                .AddNotNull(
                    request.Context,
                    request.Context.Device,
                    request.Context.DateOfBirth)
                .AddNotEmpty(
                    request.Context.Email,
                    request.Context.MobileNumber,
                    request.Context.FirstName,
                    request.Context.LastName)
                .AddEmailAddress(request.Context.Email)
                .AddMobileNumber(request.Context.MobileNumber)
                .ValidateGroupAsync();

            //
            // Validate two Device Must Same ...
            ValidateRequestAndGivenDevices(device, request.Context.Device);

            //
            // Extract UserSelectByParam from XActionRequest ...
            var userSelectByParam = GetUserSelectByParam(request);

            //
            // Validate Request Pointer User doesn't Exists ...
            await ValidateUserNotExists(userSelectByParam);

            //
            // Create an Empty Instance of XUser ...
            var xUser = new XUser();

            //
            // Start Filling User Fields ...
            xUser.UserName = userName;
            xUser.Email = request.Context.Email;
            xUser.PhoneNumber = request.Context.MobileNumber;

            //            
            xUser.FirstName = request.Context.FirstName;
            xUser.LastName = request.Context.LastName;
            xUser.DateOfBirth = request.Context.DateOfBirth;

            //
            xUser.EmailConfirmed = request.Context.EmailVerified;
            xUser.PhoneNumberConfirmed = request.Context.MobileVerified;

            //
            xUser.CreationDate = DateTime.UtcNow;
            xUser.LastLogin = null;

            //
            #region Handling New User IsEnable State ...
            //
            // By Default New Users will Enables ...
            xUser.IsEnable = true;
            xUser.IsBanned = false;

            //
            // Check Auto Enable Users ...
            if (Configuration.RequireRegistrationConfirm)
            {
                xUser.IsEnable = false;
            }

            //
            // Check Auto Confirm Email Users ...
            if (Configuration.AutoConfirmNewUsersEmail)
            {
                xUser.EmailConfirmed = true;
            }
            #endregion

            //
            // Check Auto Confirm Phone Number Users ...
            if (Configuration.AutoConfirmNewUsersPhoneNumber)
            {
                xUser.PhoneNumberConfirmed = true;
            }

            //
            // Validating given Password ...
            await ValidatePasswordPolicies(xUser, password);

            //
            // Now add new User to Database ...
            var createUserResult = await CreateUserAsync(xUser, password);
            if (!createUserResult.Succeeded)
            {
                XException.ActionFailed.Throw();
            }

            //
            // Update Request UserId Value ...
            request.Context.UserId = xUser.Id;
            request.Context.UserName = xUser.UserName;

            //
            #region Handling New User Role ...
            //
            // Now Try to Assign Default User role ...
            var isContainsDefaultUserRole = !Configuration.NewUsersRole.IsNullOrEmpty();
            if (isContainsDefaultUserRole)
            {
                //
                var newUserRoleName = Configuration.NewUsersRole;
                var isNewUserRoleExists = await IsRoleExistsAsync(newUserRoleName);
                //
                // Make Sure New User role Exists ...
                if (!isNewUserRoleExists)
                {
                    //
                    // Create Default Roles ...
                    await CreateIdentityRoles();
                }

                //
                // Assign User to Role ...
                var assignNewUserToRoleResult = await AddUserToRoleAsync(xUser, newUserRoleName);
                if (!assignNewUserToRoleResult.Succeeded)
                {
                    //
                    // Delete User if Role Assignment Faild ...
                    await UserManager.DeleteAsync(xUser);

                    //
                    // Thrown ActionFailed Error ...
                    XException.ActionFailed.Throw();
                }
            }
            #endregion

            //
            #region Handle Profile Image ...
            // Save and Attach Profile Image to User if it's Added Before ...
            if (!request.Context.UserId.IsNullOrEmpty() &&
                !request.Context.Thubmnail.IsNull())
            {
                //
                xUser = await ValidateUserExistsAndRetrieve(
                    userSelectByParam,
                    containDetails: true,
                    checkCanLoginPolicies: false,
                    checkIsBanned: false,
                    ignoreDisabledUser: true,
                    exception: XException.NotFound.ToException()
                );

                //
                // Handle Saving File and Attach it to User ...
                var saveResult = await StorageProvider
                    .HandleProfileImageSave(request.Context.Thubmnail);

                //
                var xProfileImage = new XProfileImage
                {
                    UserId = request.Context.UserId,
                    Name = saveResult.FileName,
                    Path = saveResult.FilePath,
                    Thumb = saveResult.Thmbnail,
                    ThumbPath = saveResult.ThmbnailPath
                };

                //
                xUser.Avatars.Add(xProfileImage);
                var updateResult = await UpdateUserAsync(
                    xUser,
                    checkCanLoginPolicies: false,
                    checkIsBanned: false
                );

                //
                if (updateResult.Succeeded)
                {
                    //
                    xUser.Avatar = xProfileImage.ThumbPath;
                    await UpdateUserAsync(
                        xUser,
                        checkCanLoginPolicies: false,
                        checkIsBanned: false
                    );
                }
            }
            #endregion

            //
            // Handle Attaching User device ...
            var xUserDevice = await AddUserRelatedDevice(
                userSelectByParam,
                device,
                checkCanLoginPolicies: false);

            //
            // Prepare New Token Result Resource,
            // by Requesting an Action ...
            var result = await ActionRequest(
                lang,
                device,
                userSelectByParam,
                XAction.Finish,
                request.Context,
                forceCheckUserExists: false
            );

            //
            // Remove Previous Token ...
            await RemoveTokenByHash(actionToken);

            //
            // Return Result ...
            return result;
        }

        /// <summary>
        /// Attach Profile Image
        /// </summary>
        /// <param name="actionToken">a token which approved user action</param>
        /// <param name="file">an instance of <see>IFormFile</see> for user's Avatar</param>
        /// <returns>an instance of <see>XActionResponse</see></returns>
        public async Task<XActionResponse> AttachProfileImage(
            string actionToken,
            IFormFile file
        )
        {
            //
            // Validate Args ...
            await ValidationProvider
                .GroupValidationBuilder()
                .AddNotEmpty(actionToken)
                .AddNotNull(file)
                .ValidateGroupAsync();

            //
            // Get Related Token to Registration Hash and Validate it,
            // then Parse XActionRequest Instance from Token ...
            var request = await ValidateAndParseActionHash(actionToken);

            //
            // Extract UserSelectByParam from XActionRequest ...
            var userSelectByParam = GetUserSelectByParam(request);
            if (userSelectByParam.IsNullOrEmpty())
            {
                XException.InvalidData.Throw();
            }

            //
            // Validate Given FormFile as Profile Image ...
            StorageProvider.ValidateProfileImage(file);

            //
            request.Context.Thubmnail = file;

            //
            // Save and Attach Profile Image to User if it's Added Before ...
            if (!request.Context.UserId.IsNullOrEmpty())
            {
                //
                var xUser = await ValidateUserExistsAndRetrieve(
                    userSelectByParam,
                    containDetails: true,
                    checkCanLoginPolicies: false,
                    checkIsBanned: false,
                    ignoreDisabledUser: true,
                    exception: XException.NotFound.ToException()
                );

                //
                // Handle Saving File and Attach it to User ...
                var saveResult = await StorageProvider.HandleProfileImageSave(file);

                //
                var xProfileImage = new XProfileImage
                {
                    UserId = request.Context.UserId,
                    Name = saveResult.FileName,
                    Path = saveResult.FilePath,
                    Thumb = saveResult.Thmbnail,
                    ThumbPath = saveResult.ThmbnailPath
                };

                //
                xUser.Avatars.Add(xProfileImage);
                var updateResult = await UpdateUserAsync(
                    xUser,
                    checkCanLoginPolicies: false,
                    checkIsBanned: false
                );

                //
                if (updateResult.Succeeded)
                {
                    //
                    xUser.Avatar = xProfileImage.ThumbPath;
                    await UpdateUserAsync(
                        xUser,
                        checkCanLoginPolicies: false,
                        checkIsBanned: false
                    );
                }
            }

            //
            // Remove Invitation Token ...
            if (!actionToken.IsNullOrEmpty())
            {
                await RemoveTokenByHash(actionToken);
            }

            //
            var result = await ActionRequest(
                request.Context.Lang,
                request.Context.Device,
                userSelectByParam,
                XAction.ProfileAction,
                request.Context,
                forceCheckUserExists: false
            );

            //
            // Return Result ...
            return result;
        }

        /// <summary>
        /// Finishing Registration 
        /// </summary>
        /// <param name="lang">specify destination language</param>
        /// <param name="device">an instance of <see>XDevice</see></param>
        /// <param name="userSelectByParam">user identifier</param>
        /// <param name="password">assigne password</param>
        /// <param name="returnUrl">return url for invitation user to redirect</param>
        /// <returns></returns>
        public async Task FinishRegistration(
            string lang,
            XDevice device,
            string userSelectByParam,
            string password,
            string returnUrl
        )
        {
            //
            // Validate Args ...
            await ValidationProvider
                .GroupValidationBuilder()
                .AddNotEmpty(lang, userSelectByParam, password, returnUrl)
                .AddNotNull(device)
                .AddUrl(returnUrl)
                .ValidateGroupAsync();

            //
            // Validate User Exists And Retrieve it ...
            var xUser = await ValidateUserExistsAndRetrieve(
                userSelectByParam,
                containDetails: false,
                checkCanLoginPolicies: false,
                checkIsBanned: false,
                ignoreDisabledUser: true,
                forceAdmin: false
            );

            //
            #region Handling New User Email Notification Senario ...
            //
            // Here we Check if User is Enable and Approved Email
            // send RegisteredMsg and if User is not Enable and 
            // Verify Registration value in Configuration is True
            // send Verify Registration mail to user and handle it ...
            if (Configuration.RequireRegistrationConfirm)
            {
                //
                if (xUser.IsEnable)
                {
                    //
                    // Send Registration Finished Message ...
                    // since in this step we need to prevent errors from 
                    // going forward. add this try catch here ...
                    try
                    {
                        //
                        var xMessage = GetRegistrationFinishedMessage(lang, xUser.Email, returnUrl);

                        //
                        await MessageProvider.SendMailAsync(xMessage);
                    }
                    catch { }
                }
                else
                {
                    //
                    // Send Registration Confirm Message ...
                    // since in this step we need to prevent errors from 
                    // going forward. add this try catch here ...
                    try
                    {
                        //
                        var request = await ActionRequest(
                            lang,
                            device,
                            userSelectByParam,
                            XAction.Finish,
                            forceCheckContext: false,
                            forceCheckUserExists: true);

                        //
                        var xMessage = GetRegistrationConfirmMessage(lang, xUser.Email, request.Token, returnUrl);

                        //
                        await MessageProvider.SendMailAsync(xMessage);
                    }
                    catch { }
                }
            }

            // //
            // await RemoveTokenByDevice (device);
            #endregion
        }
        #endregion
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\xIds\Providers\XIdentityManager\XIdentityManager+Request.cs

using System.Collections.Generic;
using System.Threading.Tasks;
using xCommons.Extensions;
using xExceptions.Constants;
using xIdentityModels.Constants;
using xIdentityModels.Extensions;
using xIdentityModels.Models;
using xIdentityModels.Navigations;

namespace xIds.Providers
{
    public partial class XIdentityManager
    {
        //
        #region Action Handlers ...
        /// <summary>
        /// Request an Action
        /// </summary>
        /// <param name="lang">specify destination language</param>
        /// <param name="device">an instance of <see>XDevice</see></param>
        /// <param name="userSelectByParam">specified user's identifier</param>
        /// <param name="step">a member of <see>XAction</see> which represent Action Step</param>
        /// <param name="context">an instance of <see>XActionRequestContext</see> which provides required informations for specified step</param>
        /// <param name="forceCheckContext">specify checking context, default is false</param>
        /// <param name="forceCheckUserExists">specify check user exists, default is true</param>
        /// <param name="forceCheckUserDevice">specify check user and device relation, default is false</param>
        /// <param name="forceRenewToken">specifies force renew Action Token if it's expired, default is false</param>
        /// <returns>an instance of <see>XActionResponse</see></returns>
        private async Task<XActionResponse> ActionRequest(
            string lang,
            XDevice device,
            string userSelectByParam,
            XAction step,
            XActionRequestContext context = null,
            bool forceCheckContext = false,
            bool forceCheckUserExists = true,
            bool forceCheckUserDevice = false,
            bool forceRenewToken = false
        )
        {
            //
            // Validate Args ...
            ValidationProvider.NotEmpty(lang);
            ValidationProvider.NotNull(device);

            //
            // Check Device not Banned ...
            await ValidateDeviceForActions(device);

            //
            // Check User Exists and Device Relation ...
            if (forceCheckUserExists)
            {
                if (forceCheckUserDevice)
                {
                    //
                    if (context.Device != null &&
                        !device.IsSameAs(context.Device))
                    {
                        XException.InvalidDevice.Throw();
                    }

                    //
                    await ValidateUserAndDeviceRelation(userSelectByParam, device);
                }
                else
                {
                    await ValidateUserExistsAsync(userSelectByParam);
                }
            }

            //
            XToken xToken = null;
            XActionResponse result = null;
            XActionRequestToken xRequest = null;

            //
            var isExists = false;
            var forceUserSelectByParamNotEmpty = true;
            switch (step)
            {
                case XAction.Registration:
                    //
                    forceUserSelectByParamNotEmpty = false;
                    isExists = await IsTokenExistsByDeviceAndType(device, step);

                    //
                    if (isExists)
                    {
                        xToken = await ValidateAndRetieveTokenByDeviceAndType(device, step);
                    }
                    break;

                default:
                    //
                    isExists = await IsTokenExistsByUserAndType(userSelectByParam, step);

                    //
                    if (isExists)
                    {
                        xToken = await ValidateAndRetieveTokenByUserAndType(userSelectByParam, step);
                    }
                    break;
            }

            //
            if (isExists)
            {
                //
                var isValidToken = IsValidToken(xToken.Token);
                if (!isValidToken && !forceRenewToken)
                {
                    switch (step)
                    {
                        case XAction.Registration:
                        case XAction.Invite:
                            forceRenewToken = true;
                            break;

                        default:
                            throw XException.InvalidToken.ToException();
                    }
                }

                //
                if (!isValidToken && forceRenewToken)
                {
                    await ValidateAndHandleToken(xToken.Token);
                    return await ActionRequest(
                        lang,
                        device,
                        userSelectByParam,
                        step,
                        context,
                        forceCheckContext,
                        forceCheckUserExists,
                        forceCheckUserDevice,
                        forceRenewToken);
                }

                //
                xRequest = ValidateAndParseActionToken(xToken.Token);

                //
                // Check Exists Context ...
                if (forceCheckContext)
                {
                    //
                    var isSameContext = xRequest.Context.IsSameAs(context);
                    if (!isSameContext)
                    {
                        XException.InvalidData.Throw();
                    }
                }
            }
            else
            {
                //
                if (context != null)
                {
                    //
                    var contextUserSelectByParam = GetUserSelectByParam(
                        context,
                        false,
                        new List<XUserSelectBy> {
                            XUserSelectBy.ID,
                            XUserSelectBy.Email,
                            XUserSelectBy.MobileNumber
                        });
                    var contextLang = context.Lang;
                    var contextDevice = context.Device;

                    //
                    // prevent from issues on Registration Request ...
                    if (forceUserSelectByParamNotEmpty)
                    {
                        var userSelectByType = GetUserSelectByType(userSelectByParam);
                        var contextUserSelectByType = GetUserSelectByType(contextUserSelectByParam);
                        if (contextUserSelectByType != userSelectByType)
                        {
                            //
                            var excludesList = GenerateUserSelectByExcludes(new List<XUserSelectBy> { userSelectByType });

                            //
                            contextUserSelectByParam = GetUserSelectByParam(context, false, excludesList);
                        }
                    }

                    //
                    // Fix Device Not Same on Invitation and Request
                    if (step == XAction.Registration)
                    {
                        //
                        context.Device = device;
                        contextDevice = context.Device;
                    }

                    //
                    // Validate Context Data must be Same as Request Data ...
                    if ((!contextUserSelectByParam.IsNullOrEmpty() &&
                            contextUserSelectByParam != userSelectByParam) ||
                        (!contextLang.IsNullOrEmpty() &&
                            contextLang != lang) ||
                        (contextDevice != null &&
                            !contextDevice.IsSameAs(device)))
                    {
                        XException.InvalidData.Throw();
                    }
                }
                else
                {
                    //
                    context = new XActionRequestContext
                    {
                        Lang = lang,
                        Device = device
                    };

                    //
                    // Add Content ...
                    var userSelectByType = GetUserSelectByType(
                        userSelectByParam,
                        forceUserSelectByParamNotEmpty);
                    switch (userSelectByType)
                    {
                        case XUserSelectBy.MobileNumber:
                            context.MobileNumber = userSelectByParam;
                            break;

                        case XUserSelectBy.Email:
                            context.Email = userSelectByParam;
                            break;

                        case XUserSelectBy.Username:
                            context.UserName = userSelectByParam;
                            break;

                        case XUserSelectBy.ID:
                            context.UserId = userSelectByParam;
                            break;

                        case XUserSelectBy.NotSpecified:
                        default:
                            if (forceCheckUserExists)
                            {
                                XException.InvalidArgs.Throw();
                            }
                            break;
                    }
                }

                //
                // Generate Registration Request ...
                xRequest = new XActionRequestToken
                {
                    Action = step,
                    Context = context
                };

                //
                // Add User Id if Exists to Context ...
                var isUserExists = await IsUserExistsAsync(userSelectByParam);
                if (isUserExists)
                {
                    //
                    var user = await GetUserAsync(userSelectByParam);
                    if (user != null)
                    {
                        xRequest.Context.UserId = user.Id;
                    }
                }

                //
                xRequest.Prepare(Configuration.IdentitySecretKey);

                //
                xToken = await HashRequest(
                    xRequest,
                    forceUserSelectByParamNotEmpty);
            }

            //
            // When XToken Exists Passed XToken ...
            result = GetActionResultResponse(xToken);

            //
            if (result == null)
            {
                XException.ActionFailed.Throw();
            }

            //
            return result;
        }

        /// <summary>
        /// Request a Mobile Verification Code
        /// </summary>
        /// <param name="lang">specify destination language</param>
        /// <param name="device">an instance of <see>XDevice</see></param>
        /// <param name="actionToken">a token which approved user action</param>
        /// <param name="mobileNumber">the mobile number which is going to request a verification code</param>
        /// <param name="checkMobileInUse">check mobile number is in use or not, default is true</param>
        /// <returns>an instance of <see>XActionResponse</see></returns>
        private async Task<XActionResponse> RequestMobileVerificationCode(
            string lang,
            XDevice device,
            string actionToken,
            string mobileNumber,
            bool checkMobileInUse = true
        )
        {
            //
            // Validate Args ...
            await ValidationProvider
                .GroupValidationBuilder()
                .AddNotEmpty(lang, actionToken, mobileNumber)
                .AddMobileNumber(mobileNumber)
                .AddNotNull(device)
                .ValidateGroupAsync();

            //
            // Check Device Validation ...
            await ValidateDeviceForActions(device);

            //
            // Check Mobile is Unique ...
            if (checkMobileInUse)
            {
                var isUserExists = await IsUserExistsAsync(mobileNumber);
                if (isUserExists)
                {
                    //
                    var xUser = await GetUserAsync(mobileNumber);

                    //
                    if (xUser.PhoneNumberConfirmed)
                    {
                        XException.MobileInUsed.Throw();
                    }
                }
            }

            //
            // Get Related Token to Registration Hash and Validate it,
            // then Parse XActionRequest Instance from Token ...
            var request = await ValidateAndParseActionHash(actionToken);

            //
            // Validate two Device Must Same ...
            ValidateRequestAndGiveDevices(device, request.Context.Device);

            //
            // Extract UserSelectByParam from XActionRequest ...
            var userSelectByParam = GetUserSelectByParam(
                request,
                forceNotNull: false,
                excludes: new List<XUserSelectBy> {
                    XUserSelectBy.ID,
                    XUserSelectBy.Email,
                    XUserSelectBy.MobileNumber
                });

            //
            // if it's null, means user doesn't have Invitation Token
            // and there is no User Selector ...
            if (userSelectByParam.IsNullOrEmpty())
            {
                //
                // Since Mobile is Unique so it can act as a 
                // UserSelector ...
                userSelectByParam = mobileNumber;
            }

            //
            // Define empty Verification Code
            // and Empty Verification Request ...
            var verificationCode = "";
            XVerificationRequest xVerificationRequest = null;

            //
            // Check Device Request Verification Code before or Not ...
            var isDeviceRequested = await IsDeviceRequestedForVerificationCodeBefor(device);
            if (isDeviceRequested)
            {
                //
                // if Requested before, Retrieve XVerification instance by Device from Db
                // and Validate it ...
                xVerificationRequest = await ValidateAndRetrieveVerificationRequest(device);

                //
                if (xVerificationRequest.VerificationCode.IsNullOrEmpty())
                {
                    //
                    verificationCode = GenerateRandom().ToString();
                    xVerificationRequest.VerificationCode = verificationCode;

                    //
                    await RemoveVerificationCodeRequestByDevice(
                        device,
                        saveChanges: false
                    );
                    await AddVerificationRequest(
                        xVerificationRequest,
                        saveChanges: false
                    );

                    //
                    await DbContext.SaveChangesAsync();
                }

                //
                // if XVerificationRequest is Valid, it must Contain an Alive Verification Code
                // so retrieve it and assign it ...
                verificationCode = xVerificationRequest.VerificationCode;
            }
            else
            {
                //
                verificationCode = GenerateRandom().ToString();
            }

            //
            // if it's First Verification Request of given Device
            // Generate a new Verification Code ...
            if (verificationCode.IsNullOrEmpty())
            {
                verificationCode = GenerateRandom().ToString();
            }

            //
            // Check Context Mobile and given Mobile ...
            if (!request.Context.MobileNumber.IsNullOrEmpty() &&
                mobileNumber != request.Context.MobileNumber)
            {
                XException.InvalidMobileNumber.Throw();
            }

            //
            // Check User Added To Db or Not ...
            var isAddedUser = !request.Context.UserId.IsNullOrEmpty();
            if (isAddedUser)
            {
                //
                // Validate User Exists and Retireve User Object ...
                var user = await ValidateUserExistsAndRetrieve(
                    userSelectByParam,
                    containDetails: false,
                    checkCanLoginPolicies: false,
                    checkIsBanned: false);

                //
                // Check Mobiles Same ...
                if (user.PhoneNumber == mobileNumber &&
                    user.PhoneNumberConfirmed)
                {
                    XException.MobilesSame.Throw();
                }

                //
                // Update User Object's Mobile Number and
                // Confirmation Status ...
                user.PhoneNumber = mobileNumber;
                user.PhoneNumberConfirmed = false;

                //
                // Save Changes to Db ...
                await UpdateUserAsync(user, checkCanLoginPolicies: false, checkIsBanned: false);
            }

            //
            // Prepare Verification Request by Checking Next Tries,
            // Device Status, and etc, Update or Add XVerificationRequest to db
            // and Retrieve the added Entity ...
            xVerificationRequest = await HandleVerificationRequestPreparation(verificationCode, request);

            //
            // Update Request Context MobileNumber
            // and it's Confirmation Status ...
            request.Context.MobileNumber = mobileNumber;
            request.Context.MobileVerified = false;

            //
            // Remove Previous Token ...
            await RemoveTokenByHash(actionToken);

            //
            // Prepare New Token Result Resource,
            // by Requesting an Action ...
            var result = await ActionRequest(
                lang,
                device,
                userSelectByParam,
                XAction.RequestMobileVerificationCode,
                request.Context,
                forceCheckUserExists: isAddedUser
            );

            //
            // Prepare Message ...
            var xMessage = GetVerificationCodeMessage(lang, mobileNumber, verificationCode);

            //
            // Send Verification Code Message to User Using SMS Provider ...
            await MessageProvider.SendSmsAsync(xMessage, throwException: false);

            //
            // Return Result ...
            return result;
        }

        /// <summary>
        /// Request a Email Verification Code
        /// </summary>
        /// <param name="lang">specify destination language</param>
        /// <param name="device">an instance of <see>XDevice</see></param>
        /// <param name="actionToken">a token which approved user action</param>
        /// <param name="emailAddress">the email address which is going to request a verification code</param>
        /// <param name="checkEmailInUse">check email address is in use or not, default is true</param>
        /// <returns>an instance of <see>XActionResponse</see></returns>
        public async Task<XActionResponse> RequestEmailVerificationCode(
            string lang,
            XDevice device,
            string actionToken,
            string emailAddress,
            bool checkEmailInUse = true
        )
        {
            //
            // Validate Args ...
            await ValidationProvider
                .GroupValidationBuilder()
                .AddNotEmpty(lang, actionToken, emailAddress)
                .AddEmailAddress(emailAddress)
                .AddNotNull(device)
                .ValidateGroupAsync();

            //
            // Check Device Validation ...
            await ValidateDeviceForActions(device);

            //
            // Check Email is Unique ...
            if (checkEmailInUse)
            {
                var isUserExists = await IsUserExistsAsync(emailAddress);
                if (isUserExists)
                {
                    //
                    var xUser = await GetUserAsync(emailAddress);

                    //
                    if (xUser.EmailConfirmed)
                    {
                        XException.EmailInUsed.Throw();
                    }
                }
            }

            //
            // Get Related Token to Registration Hash and Validate it,
            // then Parse XActionRequest Instance from Token ...
            var request = await ValidateAndParseActionHash(actionToken);

            //
            // Validate two Device Must Same ...
            ValidateRequestAndGiveDevices(device, request.Context.Device);

            //
            // Extract UserSelectByParam from XActionRequest ...
            var userSelectByParam = GetUserSelectByParam(
                request,
                forceNotNull: false,
                excludes: new List<XUserSelectBy> {
                    XUserSelectBy.ID,
                    XUserSelectBy.Email,
                    XUserSelectBy.MobileNumber
                });

            //
            // if it's null, means user doesn't have Invitation Token
            // and there is no User Selector ...
            if (userSelectByParam.IsNullOrEmpty())
            {
                //
                // Since Email is Unique so it can act as a 
                // UserSelector ...
                userSelectByParam = emailAddress;
            }

            //
            // Define empty Verification Code
            // and Empty Verification Request ...
            var verificationCode = "";
            XVerificationRequest xVerificationRequest = null;

            //
            // Check Device Request Verification Code before or Not ...
            var isDeviceRequested = await IsDeviceRequestedForVerificationCodeBefor(device);
            if (isDeviceRequested)
            {
                //
                // if Requested before, Retrieve XVerification instance by Device from Db
                // and Validate it ...
                xVerificationRequest = await ValidateAndRetrieveVerificationRequest(device);

                //
                if (xVerificationRequest.VerificationCode.IsNullOrEmpty())
                {
                    //
                    verificationCode = GenerateRandom().ToString();
                    xVerificationRequest.VerificationCode = verificationCode;

                    //
                    await RemoveVerificationCodeRequestByDevice(
                        device,
                        saveChanges: false
                    );
                    await AddVerificationRequest(
                        xVerificationRequest,
                        saveChanges: true
                    );
                }

                //
                // if XVerificationRequest is Valid, it must Contain an Alive Verification Code
                // so retrieve it and assign it ...
                verificationCode = xVerificationRequest.VerificationCode;
            }
            else
            {
                //
                verificationCode = GenerateRandom().ToString();
            }

            //
            // Check Context Email and given Email ...
            if (!request.Context.Email.IsNullOrEmpty() &&
                emailAddress != request.Context.Email)
            {
                XException.InvalidEmailAddress.Throw();
            }

            //
            // Check User Added To Db or Not ...
            var isAddedUser = !request.Context.UserId.IsNullOrEmpty();
            if (isAddedUser)
            {
                //
                // Validate User Exists and Retireve User Object ...
                var user = await ValidateUserExistsAndRetrieve(
                    userSelectByParam,
                    containDetails: false,
                    checkCanLoginPolicies: false,
                    checkIsBanned: false);

                //
                // Check Email Same ...
                if (user.Email == emailAddress &&
                    user.EmailConfirmed)
                {
                    XException.MobilesSame.Throw();
                }

                //
                // Update User Object's Email and
                // Confirmation Status ...
                user.Email = emailAddress;
                user.EmailConfirmed = false;

                //
                // Save Changes to Db ...
                await UpdateUserAsync(
                    user,
                    checkCanLoginPolicies: false,
                    checkIsBanned: false
                );
            }

            //
            // Prepare Verification Request by Checking Next Tries,
            // Device Status, and etc, Update or Add XVerificationRequest to db
            // and Retrieve the added Entity ...
            xVerificationRequest = await HandleVerificationRequestPreparation(verificationCode, request);

            //
            // Update Request Context Email
            // and it's Confirmation Status ...
            request.Context.Email = emailAddress;
            request.Context.EmailVerified = false;

            //
            // Prepare New Token Result Resource,
            // by Requesting an Action ...
            var result = await ActionRequest(
                lang,
                device,
                userSelectByParam,
                XAction.RequestEmailVerificationCode,
                request.Context,
                forceCheckUserExists: isAddedUser
            );

            //
            // Remove Hash ...
            await RemoveTokenByHash(actionToken);

            //
            // Prepare Message ...
            var xMessage = GetVerificationCodeMessage(lang, emailAddress, verificationCode);

            //
            // Send Verification Code Message to User Using Mail Provider ...
            await MessageProvider.SendMailAsync(xMessage, throwException: false);

            //
            // Return Result ...
            return result;
        }
        #endregion         
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\xIds\Providers\XIdentityManager\XIdentityManager+Role.cs

using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Identity;
using xCommons.Extensions;
using xExceptions.Constants;
using xIdentityModels;

namespace xIds.Providers
{
    public partial class XIdentityManager
    {
        //
        #region Role Actions ...
        /// <summary>
        /// Check a Role exists or not
        /// </summary>
        /// <param name="roleName">role name</param>
        /// <returns>a boolean value</returns>
        public async Task<bool> IsRoleExistsAsync(
            string roleName
        )
        {
            //
            if (roleName.IsNullOrEmpty())
            {
                XException.InvalidArgs.Throw();
            }

            //
            return await RoleManager.RoleExistsAsync(roleName);
        }

        /// <summary>
        /// Create a new Role 
        /// </summary>
        /// <param name="roleName">role name</param>
        /// <returns>an instance of <see>IdentityResult</see></returns>
        public async Task<IdentityResult> CreateRoleAsync(
            string roleName
        )
        {
            //
            var isExists = await RoleManager
                .RoleExistsAsync(roleName);
            if (isExists)
            {
                XException.Duplicate.Throw();
            }

            //
            var result = await RoleManager
                .CreateAsync(new IdentityRole(roleName));

            //
            return result;
        }

        /// <summary>
        /// Get a Role
        /// </summary>
        /// <param name="roleName">role name</param>
        /// <returns>an instance of <see>IdentityRole</see></returns>
        public async Task<IdentityRole> GetRoleAsync(
            string roleName
        )
        {
            //
            var isExists = await IsRoleExistsAsync(roleName);
            if (!isExists)
            {
                XException.NotFound.Throw();
            }

            //
            var result = await RoleManager
                .FindByNameAsync(roleName);

            //
            return result;
        }

        /// <summary>
        /// Remove a User From Role 
        /// </summary>
        /// <param name="user">an instance of <see>XUser</see></param>
        /// <param name="roleName">role name</param>
        /// <returns>an instance of <see>IdentityResult</see></returns>
        public async Task<IdentityResult> RemoveFromRoleAsync(
            XUser user,
            string roleName
        )
        {
            return await UserManager.RemoveFromRoleAsync(user, roleName);
        }

        /// <summary>
        /// Remove a User From Roles
        /// </summary>
        /// <param name="user">an instance of <see>XUser</see></param>
        /// <param name="roleNames">a collection of role names</param>
        /// <returns>an instance of <see>IdentityResult</see></returns>
        public async Task<IdentityResult> RemoveFromRolesAsync(
            XUser user,
            IEnumerable<string> roleNames
        )
        {
            return await UserManager.RemoveFromRolesAsync(user, roleNames);
        }

        /// <summary>
        /// Assign a User to Specific Role
        /// </summary>
        /// <param name="user">an instance of <see>XUser</see></param>
        /// <param name="roleName">role name</param>
        /// <returns>an instance of <see>IdentityResult</see></returns>
        public async Task<IdentityResult> AddUserToRoleAsync(
            XUser user,
            string roleName
        )
        {
            //
            if (user == null ||
                roleName.IsNullOrEmpty())
            {
                XException.InvalidArgs.Throw();
            }

            //
            var userSelectByParam = GetUserSelectByParam(user);
            var isExistsUser = await IsUserExistsAsync(userSelectByParam);
            var isExistsRole = await IsRoleExistsAsync(roleName);
            if (!isExistsUser || !isExistsRole)
            {
                XException.NotFound.Throw();
            }

            //
            var result = await UserManager
                .AddToRoleAsync(user, roleName);

            //
            return result;
        }

        /// <summary>
        /// Retrieve Role Name by it's ID
        /// </summary>
        /// <param name="roleId">role id</param>
        /// <returns>role name as string</returns>
        public async Task<string> GetRoleNameAsync(
            string roleId
        )
        {
            //
            // Validate Args ...
            if (roleId.IsNullOrEmpty())
            {
                XException.InvalidArgs.Throw();
            }

            //
            var role = await RoleManager
                .FindByIdAsync(roleId);

            //
            return role.Name.ToNormalString();
        }

        /// <summary>
        /// Get a List Of User Roles 
        /// </summary>
        /// <param name="userSelectByParam">user identifier</param>
        /// <param name="checkCanLoginPolicies"></param>
        /// <param name="checkIsBanned"></param>
        /// <returns>a collection of role names</returns>
        public async Task<IEnumerable<string>> GetRoleNamesAsync(
            string userSelectByParam,
            bool checkCanLoginPolicies = true,
            bool checkIsBanned = true
        )
        {
            //
            // Validate Args ...
            if (userSelectByParam.IsNullOrEmpty())
            {
                XException.InvalidArgs.Throw();
            }

            //
            var user = await ValidateUserExistsAndRetrieve(
                userSelectByParam,
                containDetails: true,
                checkCanLoginPolicies: checkCanLoginPolicies,
                checkIsBanned: checkIsBanned
            );

            //
            var result = new List<string>();
            foreach (var role in user.Roles)
            {
                //
                var roleName = await GetRoleNameAsync(role.RoleId);
                roleName = roleName.ToNormalString();

                //
                result.Add(roleName);
            }

            //
            return result;
        }

        /// <summary>
        /// Check a User is Adminr not
        /// </summary>
        /// <param name="userSelectByParam">user identifier</param>
        /// <returns>a boolean value</returns>
        public async Task<bool> IsAdmin(
            string userSelectByParam
        )
        {
            //
            // Validate Args ...
            ValidationProvider.NotEmpty(userSelectByParam);

            //
            var user = await ValidateUserExistsAndRetrieve(
                userSelectByParam,
                containDetails: true,
                checkCanLoginPolicies: true);

            //
            var result = await IsAdmin(user);

            //
            return result;
        }

        /// <summary>
        /// Check a User is Adminr not
        /// </summary>
        /// <param name="user">an instance of <see>XUser</see></param>
        /// <returns>a boolean value</returns>
        public async Task<bool> IsAdmin(
            XUser user
        )
        {
            //
            // Validate Args ...
            ValidationProvider.NotNull(user);
            ValidationProvider.NotEmpty(user.Id);

            //
            // Retrieve Admin Role ...
            // TODO: Fix this ...
            var adminRole = "admin";
            // XUserRole.Admin
            //     .GetStringValue ()
            //     .ToNormalString ();

            //
            // Check Admin Role Exists in User Roles or not ...
            var userRoleNames = await GetRoleNamesAsync(user.Id);
            var isContainsAdminRole = userRoleNames.Contains(adminRole);

            //
            // Return Result ...
            return isContainsAdminRole;
        }
        #endregion        
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\xIds\Providers\XIdentityManager\XIdentityManager+Search.cs

using System.Threading.Tasks;
using xCommons.Extensions;
using xExceptions.Constants;
using xIdentityModels.Dtos;
using xModels.Dtos;
using xDataService.Extensions;
using xIds.Extensions;
using System.Linq;
using xIdentityModels.Extensions;

namespace xIds.Providers
{
    public partial class XIdentityManager
    {
        //
        #region Actions ...       
        /// <summary>
        /// Query User Profiles
        /// </summary>
        /// <param name="requestedUserSelectByParam">requested user's identifier</param>
        /// <param name="query">how to filter results based on <see>XQuery</see> structure</param>
        /// <returns>an instance of <see>XQueryResult</see> of <see>XUserProfileDto</see></returns>
        public async Task<XQueryResult<XUserProfileDto>> QueryOpenToSearchUsers(
            string requestedUserSelectByParam,
            XQuery query
        )
        {
            //
            // Validation ...
            if (query.IsNull())
            {
                XException.InvalidArgs.Throw();
            }

            //
            // Normalize ...
            query = query.NormalizeQuery(DataConfiguration.ToXDataServiceConfig());

            //
            // Since in Resourceable Entities we have to Search on Locales
            // we Must Implement Senario Custom ...
            var totalEntities = GetUsersDbSet()
                .Where(u => u.OpenToSearch)
                .ToList()
                .Where(u => !u.ContainsUserSelectByParam(requestedUserSelectByParam))
                .Select(u => u.Id)
                .ToList();

            //
            var items = await GetUserProfilesAsync(
                totalEntities,
                requestedUserSelectByParam,
                checkIsBanned: false,
                checkCanLoginPolicies: false,
                forceCheckRequestedUser: false
            );

            //
            var totalItemsCount = items.Count();
            
            //
            // Apply Filter ...
            if (!query.Filter.IsNullOrEmpty())
            {
                //
                items = items
                    .ApplyFilter(query.Filter);
            }
            int filteredItemsCount = items.Count();
            
            //
            // Count Pages ...
            var totalPagesCount = query.CountPages(totalItemsCount);
            var filteredPagesCount = query.CountPages(filteredItemsCount);
            
            //
            // Apply Paging and Sorting ...
            if (totalItemsCount > 0 &&
                filteredItemsCount > 0)
            {
                //
                // Apply Sorting ...
                items = items
                    .ToList()
                    .ApplySorting(
                        query.SortBy,
                        query.IsAscending
                    );

                //
                // Apply Paging ...
                items = items
                    .ToList()
                    .ApplyPaging(
                        query.Page,
                        query.PageSize
                    );
            }

            //
            // Generate Result Object ...
            // Query = query,
            var result = new XQueryResult<XUserProfileDto>
            {
                Items = items,
                Page = query.Page,
                PageSize = query.PageSize,
                TotalPages = totalPagesCount,
                TotalItems = totalItemsCount,
                TotalFilteredPages = filteredPagesCount,
                TotalFilteredItems = filteredItemsCount
            };

            //
            return result;
        }
        #endregion
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\xIds\Providers\XIdentityManager\XIdentityManager+Seed.cs

using System.Threading.Tasks;
using Microsoft.AspNetCore.Identity;
using xCommons.Extensions;
using xExceptions.Constants;
using xIdentityModels.Descriptors;
using xIdentityModels.Extensions;

namespace xIds.Providers
{
    public partial class XIdentityManager
    {
        //
        #region Default Identity Preparation Actions ...
        /// <summary>
        /// Create Default Roles based on Identity Configuration 
        /// </summary>
        /// <returns></returns>
        public async Task CreateIdentityRoles()
        {
            //
            if (Configuration == null ||
                Configuration.IdentityRoles == null ||
                Configuration.IdentityRoles.Count == 0)
            {
                return;
            }

            //
            // Check New Users Role exists in IdentityRole or not ...
            if (!Configuration.NewUsersRole.IsNullOrEmpty())
            {
                //
                // Ensure NewUsersRole Exists in IdentityRoles ...
                var isNewUserRoleExistsInIdentityRoles = Configuration
                    .IdentityRoles
                    .Contains(Configuration.NewUsersRole);
                if (!isNewUserRoleExistsInIdentityRoles)
                {
                    XException.InvalidArgs.Throw();
                }
            }

            //
            // loop through all roles and create them one by one ...
            foreach (var roleName in Configuration.IdentityRoles)
            {
                //
                var isRoleExists = await RoleManager.RoleExistsAsync(roleName);
                if (!isRoleExists)
                {
                    //
                    var result = await RoleManager.CreateAsync(new IdentityRole(roleName));
                }
            }
        }

        /// <summary>
        /// Create a user Based on User Descriptor
        /// </summary>
        /// <param name="user">an instance of <see>XIdentityUserDescriptor</see></param>
        /// <returns></returns>
        public async Task CreateUserAsync(
            XIdentityUserDescriptor user
        )
        {
            //
            // Validate Args ...
            ValidationProvider.NotNull(user);

            //
            var isExistsRole = await RoleManager.RoleExistsAsync(user.Role);
            if (!isExistsRole)
            {
                //
                // Check Assigned role to user exists in app roles ...
                if (!Configuration
                    .IdentityRoles
                    .Contains(user.Role))
                {
                    XException.InvalidArgs.Throw();
                }

                //
                // Ensure All Roles Created ...
                await CreateIdentityRoles();
            }

            //
            // Check User Exists ...
            var isExistsUser = await IsUserExistsAsync(user.UserName);
            if (!isExistsUser)
            {
                //
                // Create a DashboardUser instance based on Configuration Data ...
                var userEntity = user.ToXUser();

                //
                // Try to Create User ...
                var userCreateResult = await CreateUserAsync(
                    userEntity,
                    user.Password
                );
                if (!userCreateResult.Succeeded)
                {
                    XException.ActionFailed.Throw();
                }

                //
                // Assign Admin User to it's Role ...
                var roleAssignResult = await UserManager.AddToRoleAsync(userEntity, user.Role);
                if (!roleAssignResult.Succeeded)
                {
                    XException.ActionFailed.Throw();
                }

                //
                var claims = await ToJwtClaims(
                    userEntity,
                    checkCanLoginPolicies: true,
                    checkIsBanned: true);

                //
                var addClaimsResult = await UserManager.AddClaimsAsync(userEntity, claims);
                if (!addClaimsResult.Succeeded)
                {
                    XException.ActionFailed.Throw();
                }
            }
        }
        #endregion        
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\xIds\Providers\XIdentityManager\XIdentityManager+Token.cs

using System;
using System.Collections.Generic;
using System.IdentityModel.Tokens.Jwt;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.EntityFrameworkCore;
using Microsoft.IdentityModel.Tokens;
using xCommons.Extensions;
using xCommons.Helpers;
using xExceptions.Constants;
using xIdentityModels;
using xIdentityModels.Constants;
using xIdentityModels.Extensions;
using xIdentityModels.Models;
using xIdentityModels.Navigations;

namespace xIds.Providers
{
    public partial class XIdentityManager
    {
        //
        #region Token Actions ...
        /// <summary>
        /// Check a Token Entity Exists or not
        /// </summary>
        /// <param name="device">an instance of <see>XDevice</see></param>
        /// <param name="type">specifies Action Step by a member of <see>XAction</see></param>
        /// <returns>a boolean value</returns>
        private async Task<bool> IsTokenExistsByDeviceAndType(
            XDevice device,
            XAction type
        )
        {
            //
            ValidationProvider.NotNull(device);

            //
            var isExists = false;
            var enumerator = DbContext.Tokens.AsAsyncEnumerable();
            await
            foreach (var token in enumerator)
            {
                //
                if (token.Type == type &&
                    token.Device.IsSameAs(device))
                {
                    isExists = true;
                    break;
                }
            }

            //
            return isExists;
        }

        /// <summary>
        /// Check a Token Entity Exists or not
        /// </summary>
        /// <param name="userSelectByParam">specified user's identifier</param>
        /// <param name="type">specifies Action Step by a member of <see>XAction</see></param>
        /// <returns>a boolean value</returns>
        private async Task<bool> IsTokenExistsByUserAndType(
            string userSelectByParam,
            XAction type
        )
        {
            //
            ValidationProvider.NotEmpty(userSelectByParam);

            //
            var isExists = false;
            var tokensEnumerator = DbContext.Tokens.AsAsyncEnumerable();
            await
            foreach (var token in tokensEnumerator)
            {
                //
                if (token.Type == type &&
                    token.UserSelectByParam
                    .ToNormalString() == userSelectByParam
                    .ToNormalString())
                {
                    //
                    isExists = true;
                    break;
                }
            }

            //
            return isExists;
        }

        /// <summary>
        /// Check a Token Entity Exists or not
        /// </summary>
        /// <param name="token">represent specified action token</param>
        /// <returns>a boolean value</returns>
        private async Task<bool> IsTokenExistsByToken(
            string token
        )
        {
            //
            var result = await DbContext.Tokens
                .AnyAsync(xt => xt.Token == token);

            //
            return result;
        }

        /// <summary>
        /// Check a Token Entity Exists or not
        /// </summary>
        /// <param name="hash">represent specified action token hash</param>
        /// <returns>a boolean value</returns>
        private async Task<bool> IsTokenExistsByHash(
            string hash
        )
        {
            //
            var result = await DbContext.Tokens
                .AnyAsync(xt => xt.Hash == hash);

            //
            return result;
        }

        /// <summary>
        /// Check a Token Entity Exists or not
        /// </summary>
        /// <param name="item">an instance of <see>XToken</see></param>
        /// <returns>a boolean value</returns>
        private async Task<bool> IsTokenExistsByToken(
            XToken item
        )
        {
            //
            var result = false;
            var tokenEnumerator = DbContext.Tokens
                .AsAsyncEnumerable();
            await
            foreach (var token in tokenEnumerator)
            {
                //
                if (token.Hash == item.Hash &&
                    token.Token == item.Token &&
                    token.Type == item.Type &&
                    token.UserSelectByParam
                    .ToNormalString() == item.UserSelectByParam
                    .ToNormalString() &&
                    token.Device.IsSameAs(item.Device))
                {
                    //
                    result = true;
                    break;
                }
            }

            //
            return result;
        }

        /// <summary>
        /// Check a Token Entity Exists or not
        /// </summary>
        /// <param name="id">specifies token id</param>
        /// <returns>a boolean value</returns>
        private async Task<bool> IsTokenExistsById(
            int id
        )
        {
            return await DbContext.Tokens.AnyAsync(t => t.Id == id);
        }

        /// <summary>
        /// Retrieve Token Entity
        /// </summary>
        /// <param name="device">an instance of <see>XDevice</see></param>
        /// <param name="type">specifies Action Step by a member of <see>XAction</see></param>
        /// <returns>an instance of <see>XToken</see></returns>
        private async Task<XToken> GetTokenByDeviceAndType(
            XDevice device,
            XAction type
        )
        {
            //
            var isExists = await IsTokenExistsByDeviceAndType(device, type);
            if (!isExists)
            {
                return null;
            }

            //
            XToken item = null;
            var enumerator = DbContext.Tokens.AsAsyncEnumerable();
            await
            foreach (var token in enumerator)
            {
                //
                if (token.Type == type &&
                    token.Device.IsSameAs(device))
                {
                    //
                    item = token;
                    break;
                }
            }

            //
            return item;
        }

        /// <summary>
        /// Retrieve Token Entity
        /// </summary>
        /// <param name="userSelectByParam">specified user's identifier</param>
        /// <param name="type">specifies Action Step by a member of <see>XAction</see></param>
        /// <returns>an instance of <see>XToken</see></returns>
        private async Task<XToken> GetTokenByUserAndType(
            string userSelectByParam,
            XAction type
        )
        {
            //
            var isExists = await IsTokenExistsByUserAndType(userSelectByParam, type);
            if (!isExists)
            {
                return null;
            }

            //
            XToken item = null;
            var enumerator = DbContext.Tokens.AsAsyncEnumerable();
            await
            foreach (var token in enumerator)
            {
                //
                if (token.Type == type &&
                    token.UserSelectByParam
                    .ToNormalString() == userSelectByParam
                    .ToNormalString())
                {
                    //
                    item = token;
                    break;
                }
            }

            //
            return item;
        }

        /// <summary>
        /// Retrieve a Token Entity
        /// </summary>
        /// <param name="token">represent specified action token</param>
        /// <returns>an instance of <see>XToken</see></returns>
        private async Task<XToken> GetTokenByToken(
            string token
        )
        {
            //
            var isExists = await IsTokenExistsByToken(token);
            if (!isExists)
            {
                return null;
            }

            //
            var result = await DbContext.Tokens
                .FirstOrDefaultAsync(xt => xt.Token == token);

            //
            return result;
        }

        /// <summary>
        /// Retrieve Related Hash to a Token
        /// </summary>
        /// <param name="token">represent specified action token</param>
        /// <returns>hash string</returns>
        private async Task<string> GetRelatedHashByToken(
            string token
        )
        {
            //
            var item = await GetTokenByToken(token);
            if (item == null)
            {
                return null;
            }

            //
            return item.Hash;
        }

        /// <summary>
        /// Retrieve a Token Entity
        /// </summary>
        /// <param name="hash">represent specified action token hash</param>
        /// <returns>an instance of <see>XToken</see></returns>
        private async Task<XToken> GetTokenByHash(
            string hash
        )
        {
            //
            // Validate Args ...
            ValidationProvider.NotEmpty(hash);

            //
            var isExists = await IsTokenExistsByHash(hash);
            if (!isExists)
            {
                return null;
            }

            //
            var item = await DbContext.Tokens
                .FirstOrDefaultAsync(t => t.Hash == hash);

            //
            return item;
        }

        /// <summary>
        /// Retrieve Related Token to a Hash string
        /// </summary>
        /// <param name="hash">represent specified action token hash</param>
        /// <returns>token string</returns>
        private async Task<string> GetRelatedTokenByHash(
            string hash
        )
        {
            //
            var item = await GetTokenByHash(hash);
            if (item == null)
            {
                return null;
            }

            //
            return item.Token;
        }

        /// <summary>
        /// Retrieve a Token Expiration Date
        /// </summary>
        /// <param name="token">represent specified action token</param>
        /// <returns>an instance of <see>DateTime</see></returns>
        private DateTime GetTokenExpirationDate(
            string token
        )
        {
            //
            ValidationProvider.NotEmpty(token);

            //
            var result = IdentityHelper.GetTokenExpirationDate(token);

            //
            return result;
        }

        /// <summary>
        /// Remove a Token Entity
        /// </summary>
        /// <param name="token">represent specified action token</param>
        /// <returns></returns>
        private async Task RemoveTokenByToken(
            string token
        )
        {
            //
            // Validate Args ...
            ValidationProvider.NotEmpty(token);

            //
            var isExists = await IsTokenExistsByToken(token);
            if (!isExists)
            {
                return;
            }

            //
            var item = await GetTokenByToken(token);
            if (item == null)
            {
                return;
            }

            //
            DbContext.Tokens.Remove(item);
            await DbContext.SaveChangesAsync();
        }

        /// <summary>
        /// Remove a Token Entity
        /// </summary>
        /// <param name="hash">represent specified action token hash</param>
        /// <returns></returns>
        private async Task RemoveTokenByHash(
            string hash
        )
        {
            //
            // Validate Args ...
            ValidationProvider.NotEmpty(hash);

            //
            var isExists = await IsTokenExistsByHash(hash);
            if (!isExists)
            {
                return;
            }

            //
            var item = await GetTokenByHash(hash);
            if (item == null)
            {
                return;
            }

            //
            DbContext.Tokens.Remove(item);
            await DbContext.SaveChangesAsync();
        }

        /// <summary>
        /// Remove a Token Entity
        /// </summary>
        /// <param name="device">an instance of <see>XDevice</see></param>
        /// <returns></returns>
        private async Task RemoveTokenByDevice(
            XDevice device
        )
        {
            //
            // Validate Args ...
            ValidationProvider.NotNull(device);

            //
            XToken items = null;
            var enumerator = DbContext.Tokens.AsAsyncEnumerable();
            await
            foreach (var token in enumerator)
            {
                //
                if (token.Device.IsSameAs(device))
                {
                    //
                    items = token;
                    break;
                }
            }

            //
            if (!items.IsNull())
            {
                DbContext.Tokens.RemoveRange(items);
                await DbContext.SaveChangesAsync();
            }
        }

        /// <summary>
        /// add a token Entity
        /// </summary>
        /// <param name="item">an instance of <see>XToken</see></param>
        /// <returns>an instance of <see>XToken</see></returns>
        private async Task<XToken> AddTokenAsync(
            XToken item
        )
        {
            //
            var isExist = await IsTokenExistsByToken(item);
            if (isExist)
            {
                return await GetTokenByHash(item.Hash);
            }

            //
            var entry = await DbContext.Tokens.AddAsync(item);
            await DbContext.SaveChangesAsync();

            //
            return entry.Entity;
        }

        /// <summary>
        /// Hash a Request Token
        /// </summary>
        /// <param name="request">an instance of <see>XActionRequestToken</see></param>
        /// <param name="forceNotNullUserSelectByParam"></param>
        /// <param name="forceDeviceNotNull"></param>
        /// <returns>an instance of <see>XToken</see></returns>
        private async Task<XToken> HashRequest(
            XActionRequestToken request,
            bool forceNotNullUserSelectByParam = true,
            bool forceDeviceNotNull = true
        )
        {
            //
            // Validate Args ...
            var secretKey = Configuration.IdentitySecretKey;
            ValidationProvider.NotNull(request);
            ValidationProvider.NotEmpty(secretKey);

            //
            ValidateActionRequest(request);

            //
            var type = request.Action;
            var device = request.Context.Device;
            var tokenObject = ToSecurityToken(request);
            var tokenString = ToTokenString(tokenObject);
            var tokenHash = ToHash(tokenString);
            var userSelectByParam = GetUserSelectByParam(request, forceNotNullUserSelectByParam);

            //
            if (forceNotNullUserSelectByParam)
            {
                ValidationProvider.NotEmpty(userSelectByParam);
            }

            //
            ValidationProvider.NotEmpty(tokenString, tokenHash);

            //
            if (forceDeviceNotNull)
            {
                ValidationProvider.NotNull(device);
            }

            //
            ValidationProvider.NotNull(tokenObject);

            //
            var xToken = new XToken
            {
                Type = type,
                Device = device,
                Hash = tokenHash,
                Token = tokenString,
                UserSelectByParam = userSelectByParam
            };

            //
            var addedToken = await AddTokenAsync(xToken);

            //
            return addedToken;
        }

        /// <summary>
        /// Generate Token Hash string
        /// </summary>
        /// <param name="token">represent specified action token</param>
        /// <param name="checkValidation">check token validation parameters, default is true</param>
        /// <returns>hash string</returns>
        private string ToHash(
            string token,
            bool checkValidation = true
        )
        {
            //
            ValidationProvider.NotEmpty(token);

            //
            if (checkValidation)
            {
                ValidateToken(token);
            }

            //
            var result = token.ToMd5String().ToNormalString();

            //
            return result;
        }

        /// <summary>
        /// Generate Token string
        /// </summary>
        /// <param name="token">represent specified action token</param>
        /// <returns>token string</returns>
        private string ToTokenString(
            SecurityToken token
        )
        {
            //
            ValidationProvider.NotNull(token, IdentityHelper);

            //
            var result = IdentityHelper.ToTokenString(token);

            //
            return result;
        }

        /// <summary>
        /// Generate Token string
        /// </summary>
        /// <param name="token">represent specified action token</param>
        /// <returns>token string</returns>
        private string ToTokenString(
            JwtSecurityToken token
        )
        {
            //
            ValidationProvider.NotNull(token, IdentityHelper);

            //
            var result = IdentityHelper.ToTokenString(token);

            //
            return result;
        }

        /// <summary>
        /// Generate Security Token
        /// </summary>
        /// <param name="token">represent specified action token</param>
        /// <returns>an instance of <see>SecurityToken</see></returns>
        private SecurityToken ToSecurityToken(
            string token
        )
        {
            //
            ValidationProvider.NotEmpty(token);

            //
            var result = IdentityHelper.ToSecurityToken(token);

            //
            return result;
        }

        /// <summary>
        /// Generate Security Token
        /// </summary>
        /// <param name="request">an instance of <see>XActionRequestToken</see></param>
        /// <returns>an instance of <see>SecurityToken</see></returns>
        private SecurityToken ToSecurityToken(
            XActionRequestToken request
        )
        {
            //
            ValidationProvider.NotNull(request);

            //
            ValidateActionRequest(request);

            //
            var result = IdentityHelper.ToSecurityToken(request);
            if (result == null)
            {
                XException.InvalidToken.Throw();
            }

            //
            return result;
        }

        /// <summary>
        /// Cleanup all exists tokens related to specified User
        /// </summary>
        /// <param name="userSelectByParam">specified user's identifier</param>
        /// <returns></returns>
        private async Task HandleRemoveExistsTokens(
            string userSelectByParam
        )
        {
            //
            // Validate Args ...
            ValidationProvider.NotEmpty(userSelectByParam);

            //
            var xTokens = new List<XToken>();
            var xTokenEnumerator = DbContext.Tokens.AsAsyncEnumerable();
            await
            foreach (var xToken in xTokenEnumerator)
            {
                //
                if (xToken.UserSelectByParam == userSelectByParam &&
                    ObjectHelper.ToEnumerableValues<XAction>().Contains(xToken.Type))
                {
                    xTokens.Add(xToken);
                }
            }

            //
            if (xTokens.HasChild())
            {
                DbContext.Tokens.RemoveRange(xTokens);
                await DbContext.SaveChangesAsync();
            }
        }

        /// <summary>
        /// Cleanup all tokens related to specified User
        /// </summary>
        /// <param name="userSelectByParams">a collection of user identifiers</param>
        /// <returns></returns>
        private async Task HandleCleanUserTokens(
            ICollection<string> userSelectByParams
        )
        {
            //
            // Validate Args ...
            if (!userSelectByParams.HasChild())
            {
                return;
            }

            //
            foreach (var userSelectByParam in userSelectByParams)
            {
                await HandleRemoveExistsTokens(userSelectByParam);
            }
        }

        /// <summary>
        /// Cleanup all tokens related to specified User
        /// </summary>
        /// <param name="user">an instance of <see>XUser</see></param>
        /// <returns></returns>
        private async Task HandleCleanUserTokens(
            XUser user
        )
        {
            //
            if (user == null)
            {
                return;
            }

            //
            var userSelectByParams = GenerateUserSelectByParams(user);

            //
            await HandleCleanUserTokens(userSelectByParams);
        }
        #endregion        
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\xIds\Providers\XIdentityManager\XIdentityManager+User.cs

using System;
using System.Collections.Generic;
using System.IdentityModel.Tokens.Jwt;
using System.Linq;
using System.Security.Claims;
using System.Threading.Tasks;
using IdentityModel;
using Microsoft.AspNetCore.Identity;
using Microsoft.EntityFrameworkCore;
using xCommons.Constants;
using xCommons.Extensions;
using xExceptions.Constants;
using xIdentityModels;
using xIdentityModels.Constants;
using xIdentityModels.Dtos;
using xIdentityModels.Extensions;
using xIdentityModels.Navigations;

namespace xIds.Providers
{
    public partial class XIdentityManager
    {
        //
        #region User Handlers ...
        /// <summary>
        /// Check a User Exists or not
        /// </summary>
        /// <param name="userSelectByParam">specified user's identifier</param>
        /// <returns>a boolean value</returns>
        public async Task<bool> IsUserExistsAsync(
            string userSelectByParam
        )
        {
            //
            // Validate Args ...
            if (userSelectByParam.IsNullOrEmpty())
            {
                return false;
            }

            //
            var selectType = GetUserSelectByType(userSelectByParam);

            //
            var result = false;
            XUser user = null;
            switch (selectType)
            {
                case XUserSelectBy.MobileNumber:
                    user = await GetUsersDbSet()
                        .Where(ur => ur.PhoneNumber == userSelectByParam)
                        .FirstOrDefaultAsync();
                    break;

                case XUserSelectBy.Email:
                    user = await UserManager
                        .FindByEmailAsync(userSelectByParam);
                    break;

                case XUserSelectBy.Username:
                    user = await UserManager
                        .FindByNameAsync(userSelectByParam);
                    break;

                case XUserSelectBy.ID:
                default:
                    user = await UserManager
                        .FindByIdAsync(userSelectByParam);
                    break;
            }

            //
            result = user != null;

            //
            return result;
        }

        /// <summary>
        /// Check a User Selector is Available for Registration or Not
        /// </summary>
        /// <param name="userSelectByParam">specified user's identifier</param>
        /// <returns>a boolean value</returns>
        public async Task<bool> CanRegister(
            string userSelectByParam
        )
        {
            //
            // Validate ARgs ...
            ValidationProvider.NotEmpty(userSelectByParam);

            //
            var selectByType = GetUserSelectByType(userSelectByParam);

            //
            if (selectByType == XUserSelectBy.Username &&
                !ValidateUserName(userSelectByParam))
            {
                return false;
            }

            //
            var isExists = await IsUserExistsAsync(userSelectByParam);
            if (isExists)
            {
                return false;
            }

            //
            return true;
        }

        /// <summary>
        /// Get a User object
        /// </summary>
        /// <param name="userSelectByParam">specified user's identifier</param>
        /// <param name="containDetails">specifies returned object contains all Navigation Properties or not, default is false</param>
        /// <returns>an instance of <see>XUser</see></returns>
        public async Task<XUser> GetUserAsync(
            string userSelectByParam,
            bool containDetails = false
        )
        {
            //
            var isExists = await IsUserExistsAsync(userSelectByParam);
            if (!isExists)
            {
                XException.NotFound.Throw();
            }

            //
            // Fill User ...
            var selectType = GetUserSelectByType(userSelectByParam);
            XUser user = null;
            var usersStore = GetUsersDbSet(containDetails);

            //
            // Select Type ...
            switch (selectType)
            {
                case XUserSelectBy.MobileNumber:
                    user = await usersStore
                        .FirstOrDefaultAsync(ur => ur.PhoneNumber ==
                            userSelectByParam);
                    break;

                case XUserSelectBy.Email:
                    user = await usersStore
                        .FirstOrDefaultAsync(ur => ur.Email ==
                            userSelectByParam);
                    break;

                case XUserSelectBy.Username:
                    user = await usersStore
                        .FirstOrDefaultAsync(ur => ur.UserName ==
                            userSelectByParam);
                    break;

                case XUserSelectBy.ID:
                default:
                    user = await usersStore
                        .FirstOrDefaultAsync(ur => ur.Id ==
                            userSelectByParam);
                    break;
            }

            //
            return user;
        }

        /// <summary>
        /// Retrieve User Names based on UserIds
        /// </summary>
        /// <param name="userIds">a collection of user identifiers</param>
        /// <returns>a collection of Usernames</returns>
        public async Task<IEnumerable<string>> GetUserNamesAsync(
            IEnumerable<string> userIds
        )
        {
            //
            // Validate Args ...
            if (userIds == null ||
                userIds.Count() == 0)
            {
                return null;
            }

            //
            var result = await GetUsersDbSet()
                .Where(
                    xu =>
                    userIds
                    .Contains(xu.Id))
                .Select(xt => xt.UserName)
                .ToListAsync();

            //
            return result;
        }

        /// <summary>
        /// get user ids and retrieve corresponding user names
        /// </summary>
        /// <param name="model">an instance of <see>XUserNameIdRequest</see> which represent required UserIds collection</param>
        /// <returns>a collection of <see>XUserNameIdResponse</see> instances</returns>
        public async Task<IEnumerable<XUserNameIdResponse>> GetUserNameIdsAsync(
            XUserNameIdRequest model
        )
        {
            //
            // Validate Args ...
            if (model.IsNull() || !model.Ids.HasChild())
            {
                return null;
            }

            //
            var result = await GetUsersDbSet()
                .Where(
                    xu =>
                    model.Ids.Contains(xu.Id) ||
                    model.Ids.Contains(xu.Email) ||
                    model.Ids.Contains(xu.UserName) ||
                    model.Ids.Contains(xu.PhoneNumber))
                .Select(xt => new XUserNameIdResponse
                {
                    Id = xt.Id,
                    UserName = xt.UserName,
                })
                .ToListAsync();

            //
            return result;
        }

        /// <summary>
        /// Create a User
        /// </summary>
        /// <param name="user">an instance of <see>XUser</see></param>
        /// <param name="password">user's password</param>
        /// <param name="checkCanLoginPolicies">check a user can log in in system or not, default is false</param>
        /// <param name="checkIsBanned">check user is banned or not, default is false</param>
        /// <returns>an instance of <see>IdentityResult</see></returns>
        public async Task<IdentityResult> CreateUserAsync(
            XUser user,
            string password,
            bool checkCanLoginPolicies = false,
            bool checkIsBanned = false
        )
        {
            //
            if (user == null ||
                password.IsNullOrEmpty())
            {
                XException.InvalidArgs.Throw();
            }

            //
            // Get User Select By param
            var userSelectByParam = GetUserSelectByParam(user, excludes: new List<XUserSelectBy> { XUserSelectBy.ID });

            //
            // Check User Created before or not ...
            var isExists = await IsUserExistsAsync(userSelectByParam);
            if (isExists)
            {
                XException.Duplicate.Throw();
            }

            //
            var result = await UserManager.CreateAsync(user, password);
            if (result.Succeeded)
            {
                //
                var claims = await ToJwtClaims(
                    user,
                    checkCanLoginPolicies: checkCanLoginPolicies,
                    checkIsBanned: checkIsBanned);

                //
                var addClaimsResult = await UserManager.AddClaimsAsync(user, claims);

                //
                return addClaimsResult;
            }

            //
            return result;
        }

        /// <summary>
        /// Update a User Information
        /// </summary>
        /// <param name="user">an instance of <see>XUser</see></param>
        /// <param name="checkCanLoginPolicies">check a user can log in in system or not, default is true</param>
        /// <param name="checkIsBanned">check user is banned or not, default is true</param>
        /// <returns>an instance of <see>IdentityResult</see></returns>
        public async Task<IdentityResult> UpdateUserAsync(
            XUser user,
            bool checkCanLoginPolicies = true,
            bool checkIsBanned = true
        )
        {
            //
            var updateResult = await this.UserManager.UpdateAsync(user);
            if (updateResult.Succeeded)
            {
                //
                var claims = await ToJwtClaims(
                    user,
                    checkCanLoginPolicies: checkCanLoginPolicies,
                    checkIsBanned: checkIsBanned
                );
                var existsClaims = await UserManager.GetClaimsAsync(user);

                //
                await UserManager.RemoveClaimsAsync(user, existsClaims);
                var addClaimsResult = await UserManager.AddClaimsAsync(user, claims);

                //
                return addClaimsResult;
            }

            //
            return updateResult;
        }

        /// <summary>
        /// Generate JWT Claims froma DashboardUser object
        /// </summary>
        /// <param name="user">an instance of <see>XUser</see></param>
        /// <param name="checkCanLoginPolicies">check a user can log in in system or not, default is true</param>
        /// <param name="checkIsBanned">check user is banned or not, default is true</param>
        /// <returns>a collection of <see>Claim</see> instances</returns>
        public async Task<Claim[]> ToJwtClaims(
            XUser user,
            bool checkCanLoginPolicies = true,
            bool checkIsBanned = true
        )
        {
            //
            // Get New Instance of Claims ...
            var claims = new List<Claim> {
            //
            // Mapping to User.Identity.Name ...
            new Claim (JwtClaimTypes.Name, user.UserName),

            //
            // Mapping to User.Identity.Name ...
            new Claim (JwtRegisteredClaimNames.UniqueName, user.UserName),

            //
            // Other Usefull User Related Data ...
            new Claim (JwtClaimTypes.GivenName, user.FirstName),
            new Claim (JwtClaimTypes.FamilyName, user.LastName),

            //
            // User Gendre ...
            new Claim (JwtClaimTypes.Gender, user.Gender.ToString (), ClaimValueTypes.Integer),

            //
            // User Profile Picture ...
            new Claim (JwtClaimTypes.Picture, !user.Avatar.IsNullOrEmpty () ?
            user.Avatar.ToString () :
            ""),

            //
            // The Unique Identifier for Each Token ...
            new Claim (JwtRegisteredClaimNames.Jti, Guid.NewGuid ().ToString ()),

            //
            // Add isEnable and isBanned feature ...
            new Claim (
            XCustomClaims.IsEnabled,
            user.IsEnable.ToString (),
            ClaimValueTypes.Boolean
            ),
            new Claim (
            XCustomClaims.IsBanned,
            user.IsBanned.ToString (),
            ClaimValueTypes.Boolean
            ),
            };

            //
            #region Set Claims based on Profile Policies ...
            //
            if (Configuration.Policy.Profile.ContainsDateOfBirth)
            {
                claims.Add(new Claim(JwtRegisteredClaimNames.Birthdate, user.DateOfBirth.ToString()));
            }

            //
            if (Configuration.Policy.Profile.ContainsEmail)
            {
                claims.Add(new Claim(JwtClaimTypes.Email, user.Email));
                claims.Add(new Claim(
                    JwtClaimTypes.EmailVerified,
                    user.EmailConfirmed.ToString(),
                    ClaimValueTypes.Boolean));
            }

            //
            if (Configuration.Policy.Profile.ContainsPhoneNumber)
            {
                claims.Add(new Claim(JwtClaimTypes.PhoneNumber, user.PhoneNumber));
                claims.Add(new Claim(
                    JwtClaimTypes.PhoneNumberVerified,
                    user.PhoneNumberConfirmed.ToString(),
                    ClaimValueTypes.Boolean));
            }

            //
            if (Configuration.Policy.Profile.ContainsRoles)
            {
                var roleNames = await GetRoleNamesAsync(
                    user.UserName,
                    checkCanLoginPolicies: checkCanLoginPolicies,
                    checkIsBanned: checkIsBanned);
                roleNames.ToList()
                    .ForEach(rn =>
                    {
                        claims.Add(new Claim(JwtClaimTypes.Role, rn));
                    });
            }

            //
            if (Configuration.Policy.Profile.ContainsLastLogin)
            {
                claims.Add(new Claim(
                    JwtClaimTypes.AuthenticationTime,
                    user.LastLogin.ToString(),
                    ClaimValueTypes.DateTime));
            }
            #endregion

            //
            // Return Result ...
            return claims.ToArray();
        }

        /// <summary>
        /// Check User and Password relation
        /// </summary>
        /// <param name="user">an instance of <see>XUser</see></param>
        /// <param name="password">user's password</param>
        /// <param name="device">an instance of <see>XDevice</see></param>
        /// <param name="language">specify destination language</param>
        /// <param name="lockoutOnFailure">specify account lockout on failure log in</param>
        /// <param name="isForced">specify log in force without checking <see>XDevice</see> and lang relation</param>
        /// <returns>an instance of <see>SignInResult</see></returns>
        public async Task<SignInResult> CheckPasswordSignInAsync(
            XUser user,
            string password,
            XDevice device,
            string language,
            bool lockoutOnFailure,
            bool isForced = true
        )
        {
            //
            var result = await SignInManager.CheckPasswordSignInAsync(
                user, password, lockoutOnFailure
            );

            //
            if (result.Succeeded && isForced)
            {
                //
                var isExistsDevice = user.Devices.Any(d => d.IsSameAs(device));
                if (!isExistsDevice && !user.Email.IsNullOrEmpty() && user.EmailConfirmed)
                {
                    //
                    user.Devices.Add(device);

                    //
                    var updateUserResult = await UpdateUserAsync(user);
                    if (updateUserResult.Succeeded)
                    {
                        //
                        try
                        {
                            //
                            var xMessage = GetUserNewDeviceLoggedInMessage(
                                language,
                                user.Email,
                                device
                            );

                            //
                            await MessageProvider.SendMailAsync(xMessage);
                        }
                        catch { }
                    }
                }
            }

            //
            return result;
        }
        #endregion
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\xIds\Providers\XIdentityManager\XIdentityManager+Validators.cs

using System;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Identity;
using xCommons.Extensions;
using xExceptions.Constants;
using xIdentityModels;
using xIdentityModels.Constants;
using xIdentityModels.Extensions;
using xIdentityModels.Models;
using xIdentityModels.Navigations;

namespace xIds.Providers
{
    public partial class XIdentityManager
    {
        //
        #region User Validators ...
        /// <summary>
        /// Validate User Name for Registration based on Policies
        /// </summary>
        /// <param name="userName">provided user name</param>
        /// <returns>a boolean value</returns>
        private bool ValidateUserName(
            string userName
        )
        {
            //
            // Check min/max Length ...
            if (userName.IsNullOrEmpty() ||
                userName.Length < Configuration.Policy.User.MinLength ||
                userName.Length > Configuration.Policy.User.MaxLength)
            {
                return false;
            }

            //
            // Check Allowed UserName Characters ...
            if (!UserManager.Options.User.AllowedUserNameCharacters.IsNullOrEmpty() &&
                userName.Any(c => !UserManager.Options.User.AllowedUserNameCharacters.Contains(c)))
            {
                return false;
            }

            //
            // Check invalid UserNames ...
            if (Configuration.Policy.User.InvalidUserNames
                .HasChild() && Configuration.Policy.User.InvalidUserNames
                .Any(u => userName
                    .ToNormalString()
                    .Contains(u.ToNormalString())))
            {
                return false;
            }

            //
            return true;
        }

        /// <summary>
        /// Validate a User Exists
        /// </summary>
        /// <param name="userSelectByParam">specifies user identifier</param>
        /// <param name="exception">specify <see>Excetion</see> to thrown on failure</param>
        /// <returns></returns>
        private async Task ValidateUserExistsAsync(
            string userSelectByParam,
            Exception exception = null
        )
        {
            //
            ValidationProvider
                .NotEmpty(userSelectByParam);

            //
            if (exception == null)
            {
                exception = XException.NotFound.ToException();
            }

            //
            // Check User Exists ...
            var isExists = await IsUserExistsAsync(userSelectByParam);
            if (!isExists)
            {
                throw exception;
            }
        }

        /// <summary>
        /// Validate a User Not Exists
        /// </summary>
        /// <param name="userSelectByParam">specifies user identifier</param>
        /// <param name="exception">specify <see>Excetion</see> to thrown on failure</param>
        /// <returns></returns>
        private async Task ValidateUserNotExists(
            string userSelectByParam,
            Exception exception = null
        )
        {
            //
            ValidationProvider
                .NotEmpty(userSelectByParam);

            //
            if (exception == null)
            {
                exception = XException.UserRegisteredBefore.ToException();
            }

            //
            // Check User Exists ...
            var isExists = await IsUserExistsAsync(userSelectByParam);
            if (isExists)
            {
                throw exception;
            }
        }

        /// <summary>
        /// Validate User Exists and Some Usefull Checks
        /// </summary>
        /// <param name="userSelectByParam">specifies user identifier</param>
        /// <param name="containDetails">specifies returned object contains all Navigation Properties or not, default is false</param>
        /// <param name="checkCanLoginPolicies">check a user can log in in system or not, default is false</param>
        /// <param name="checkIsBanned">check user is banned or not, default is true</param>
        /// <param name="ignoreDisabledUser">specify do not thrown <see>Exception</see> if user is Disabled, default is false</param>
        /// <param name="forceAdmin">specify requested person is Admin role, default is false</param>
        /// <param name="exception">specify <see>Excetion</see> to thrown on failure</param>
        /// <returns>an instance of <see>XUser</see></returns>
        public async Task<XUser> ValidateUserExistsAndRetrieve(
            string userSelectByParam,
            bool containDetails = false,
            bool checkCanLoginPolicies = false,
            bool checkIsBanned = true,
            bool ignoreDisabledUser = false,
            bool forceAdmin = false,
            Exception exception = null
        )
        {
            //
            ValidationProvider
                .NotEmpty(userSelectByParam);
            ValidationProvider.NotNull(
                Configuration,
                Configuration.Policy,
                Configuration.Policy.SignIn);

            //
            // Prepare Default Exception ...
            if (exception == null)
            {
                exception = XException.InvalidData.ToException();
            }

            //
            // Check User Exists ...
            await ValidateUserExistsAsync(userSelectByParam);

            //
            // Retrieve User ...
            var result = await GetUserAsync(userSelectByParam, containDetails);
            if (result == null)
            {
                throw exception;
            }

            //
            // Check Force Admin ...
            if (forceAdmin)
            {
                //
                var isAdmin = await IsAdmin(result);
                if (!isAdmin)
                {
                    XException.NotAuthorized.Throw();
                }
            }

            //
            // Check User not Bann ...
            if (checkIsBanned &&
                result.IsBanned)
            {
                XException.UserBanned.Throw();
            }

            //
            var requireConfirmedEmail = Configuration.Policy.SignIn.RequireConfirmedEmail;
            var requireConfirmedPhoneNumber = Configuration.Policy.SignIn.RequireConfirmedPhoneNumber;
            var requireEnabled = Configuration.Policy.SignIn.RequiredEnabled;

            //
            var isEnabled = result.IsEnable;
            var isMobileConfirmed = result.PhoneNumberConfirmed;
            var isEmailConfirmed = result.EmailConfirmed;

            //
            if (checkCanLoginPolicies)
            {
                //
                // Check IsEnabled ...
                if (!ignoreDisabledUser &&
                    requireEnabled &&
                    !isEnabled)
                {
                    XException.UserDisabled.Throw();
                }

                //
                // Check Email Confirmed ...
                if (requireConfirmedEmail &&
                    !isEmailConfirmed)
                {
                    XException.EmailNotConfirmed.Throw();
                }

                //
                // Check Mobile Confirmed ...
                if (requireConfirmedPhoneNumber &&
                    !isMobileConfirmed)
                {
                    XException.MobileNotConfirmed.Throw();
                }
            }

            //
            // Return Result ...
            return result;
        }

        /// <summary>
        /// Validate a Device for User Actions
        /// </summary>
        /// <param name="device">an instance of <see>XDevice</see></param>
        /// <returns></returns>
        private async Task ValidateDeviceForActions(
            XDevice device
        )
        {
            //
            ValidationProvider
                .NotNull(device);

            //
            // Check is Device Banned or not ...
            var isDeviceBanned = await IsDeviceBanned(device);
            if (isDeviceBanned)
            {
                //
                // Retrieve Banned Device ...
                var xBannedDevice = await GetBannedDevice(device);
                if (xBannedDevice == null)
                {
                    XException.InvalidArgs.Throw();
                }

                //
                // Check Banned Device Time out Passed or not ...
                var isDelayTimePassed = IsDelayTimePassed(xBannedDevice);
                if (!isDelayTimePassed)
                {
                    //
                    var passedTime = GetPassedTime(xBannedDevice);

                    //
                    XException.DeviceBanned
                        .AddContentToException(passedTime.ToString());
                }

                //
                // if Delay Passed of Banned Device
                // the device must Removed ...
                await BannedDeviceRemove(xBannedDevice);
            }
        }

        /// <summary>
        /// Validate a DateOfBirth for Registration
        /// </summary>
        /// <param name="dateOfBirth">users dob date, an instance of <see>DateTime</see></param>
        /// <param name="exception">specify <see>Excetion</see> to thrown on failure</param>
        /// <returns></returns>
        private void ValidateDateOfBirth(
            DateTime dateOfBirth,
            Exception exception = null
        )
        {
            //
            // Validate Args ...
            ValidationProvider.NotNull(dateOfBirth);

            //
            if (exception.IsNull())
            {
                exception = XException.InvalidDate.ToException();
            }

            //
            var currentDate = DateTime.UtcNow;
            if (dateOfBirth >= currentDate)
            {
                throw exception;
            }

            //
            var zeroDate = (new DateTime(1, 1, 1)).ToUniversalTime();
            var minAge = Configuration.Policy.User.MinAgeForRegistration;
            var maxAge = Configuration.Policy.User.MaxAgeForRegistration;

            //
            var timeSpan = currentDate - dateOfBirth;
            var age = (zeroDate + timeSpan).Year - 1;

            //
            if (age > maxAge || age < minAge)
            {
                throw exception;
            }
        }

        /// <summary>
        /// Validate a Given User Can Registere
        /// </summary>
        /// <param name="userSelectByParam">specifies user identifier</param>
        /// <returns></returns>
        private async Task ValidateCanRegister(
            string userSelectByParam
        )
        {
            //
            // Validate Args ...
            ValidationProvider.NotEmpty(userSelectByParam);

            //
            var canRegister = await CanRegister(userSelectByParam);
            if (!canRegister)
            {
                XException.Unavailable.Throw();
            }
        }

        /// <summary>
        /// Validate Password by Gicen Policies
        /// </summary>
        /// <param name="user">an instance of <see>XUser</see></param>
        /// <param name="password">user's password</param>
        /// <param name="exception">specify <see>Excetion</see> to thrown on failure</param>
        /// <returns></returns>
        private async Task ValidatePasswordPolicies(
            XUser user,
            string password,
            Exception exception = null
        )
        {
            //
            // Validate Args ...
            ValidationProvider.NotNull(user);
            ValidationProvider.NotEmpty(password);

            //
            // Prepare Default Exception ...
            if (exception == null)
            {
                exception = XException.InvalidPassword.ToException();
            }

            //
            // Check new Password Validation ...
            var passwordValidator = new PasswordValidator<XUser>();
            var checkPasswordResult = await passwordValidator.ValidateAsync(UserManager, user, password);
            if (!checkPasswordResult.Succeeded)
            {
                throw exception;
            }
        }

        /// <summary>
        /// Validate a User for Dangerous Actions
        /// </summary>
        /// <param name="user">an instance of <see>XUser</see></param>
        /// <param name="requester">specified which user request Action by an instance of <see>XUser</see></param>
        /// <returns></returns>
        private async Task ValidateUserForDangerousAction(
            XUser user,
            XUser requester
        )
        {
            //
            // Validate ARgs ...
            ValidationProvider.NotNull(user, requester);

            //
            var requesterRoleNames = await GetRoleNamesAsync(requester.Id);

            //
            var isSame = user.Id == requester.Id;
            var isRequesterAdmin = requesterRoleNames.Any(r => r.ToNormalString() == "admin");
            if (!isSame && !isRequesterAdmin)
            {
                XException.NotAllowed.Throw();
            }
        }
        #endregion

        //
        #region Device Validators ...
        /// <summary>
        /// Validate a Device for Specified User
        /// </summary>
        /// <param name="userSelectByParam">specifies user identifier</param>
        /// <param name="device">an instance of <see>XDevice</see></param>
        /// <param name="exception">specify <see>Excetion</see> to thrown on failure</param>
        /// <returns></returns>
        private async Task ValidateUserAndDeviceRelation(
            string userSelectByParam,
            XDevice device,
            Exception exception = null
        )
        {
            //
            ValidationProvider.NotEmpty(userSelectByParam);
            ValidationProvider.NotNull(device);

            //
            if (exception == null)
            {
                exception = XException.InvalidDevice.ToException();
            }

            //
            var user = await ValidateUserExistsAndRetrieve(
                userSelectByParam,
                containDetails: true);

            //
            var result = await IsDeviceRelateDToUser(
                userSelectByParam,
                device
            );
            if (!result)
            {
                throw exception;
            }
        }
        #endregion

        //
        #region Token Validators ...
        /// <summary>
        /// Validate a Token
        /// </summary>
        /// <param name="token">token string</param>
        /// <param name="exception">specify <see>Excetion</see> to thrown on failure</param>
        private void ValidateToken(
            string token,
            Exception exception = null
        )
        {
            //
            ValidationProvider.NotEmpty(token);

            //
            if (exception == null)
            {
                exception = XException.InvalidToken.ToException();
            }

            //
            var result = IdentityHelper.ValidateToken(token);
            if (!result)
            {
                throw exception;
            }
        }

        /// <summary>
        /// Validate a Token is Specified to a Device and User
        /// </summary>
        /// <param name="device">an instance of <see>XDevice</see></param>
        /// <param name="type">specifies Action type by a member of <see>XAction</see></param>
        /// <param name="exception">specify <see>Excetion</see> to thrown on failure</param>
        /// <returns>an instance of <see>XToken</see></returns>
        private async Task<XToken> ValidateAndRetieveTokenByDeviceAndType(
            XDevice device,
            XAction type,
            Exception exception = null
        )
        {
            //
            ValidationProvider.NotNull(device);

            //
            // Prepare Default Exception ...
            if (exception == null)
            {
                exception = XException.NotFound.ToException();
            }

            //
            var isExists = await IsTokenExistsByDeviceAndType(device, type);
            if (!isExists)
            {
                throw exception;
            }

            //
            var item = await GetTokenByDeviceAndType(device, type);
            if (item == null)
            {
                throw exception;
            }

            //
            return item;
        }

        /// <summary>
        /// Validate a Token By User and Specified Type
        /// </summary>
        /// <param name="userSelectByParam">specifies user identifier</param>
        /// <param name="type">specifies Action type by a member of <see>XAction</see></param>
        /// <param name="exception">specify <see>Excetion</see> to thrown on failure</param>
        /// <returns>an instance of <see>XToken</see></returns>
        private async Task<XToken> ValidateAndRetieveTokenByUserAndType(
            string userSelectByParam,
            XAction type,
            Exception exception = null
        )
        {
            //
            ValidationProvider.NotEmpty(userSelectByParam);

            //
            // Prepare Default Exception ...
            if (exception == null)
            {
                exception = XException.InvalidData.ToException();
            }

            //
            var isExists = await IsTokenExistsByUserAndType(userSelectByParam, type);
            if (!isExists)
            {
                throw exception;
            }

            //
            var item = await GetTokenByUserAndType(userSelectByParam, type);
            if (item == null)
            {
                throw exception;
            }

            //
            return item;
        }

        /// <summary>
        /// Check Token Validation
        /// </summary>
        /// <param name="token">token string</param>
        /// <returns>a boolean value</returns>
        private bool IsValidToken(
            string token
        )
        {
            //
            ValidationProvider.NotEmpty(token);

            //
            var result = IdentityHelper.ValidateToken(token);

            //
            return result;
        }

        /// <summary>
        /// Retrieve Action Request Based on Action Token
        /// </summary>
        /// <param name="token">token string</param>
        /// <param name="exception">specify <see>Excetion</see> to thrown on failure</param>
        /// <returns>an instance of <see>XActionRequestToken</see></returns>
        private XActionRequestToken ValidateAndParseActionToken(
            string token,
            Exception exception = null
        )
        {
            //
            ValidationProvider.NotEmpty(token);

            //
            // Prepare Default Exception ...
            if (exception == null)
            {
                exception = XException.InvalidToken.ToException();
            }

            //
            ValidateToken(token);

            //
            var result = IdentityHelper.ParseActionRequestToken(token);
            if (result == null)
            {
                throw exception;
            }

            //
            ValidateActionRequest(result);

            //
            return result;
        }

        /// <summary>
        /// Parse Action Request from Token
        /// </summary>
        /// <param name="token">token string</param>
        /// <returns>an instance of <see>XActionRequestToken</see></returns>
        private XActionRequestToken ParseActionRequest(
            string token
        )
        {
            //
            // Validate Args ...
            ValidationProvider.NotEmpty(token);

            //
            var result = IdentityHelper
                .ParseActionRequestToken(token);

            //
            return result;
        }

        /// <summary>
        /// Parse Action Hash by Corresponding Token
        /// </summary>
        /// <param name="hash">token hash string</param>
        /// <returns>an instance of <see>XActionRequestToken</see></returns>
        private async Task<XActionRequestToken> ParseActionHash(
            string hash
        )
        {
            //
            ValidationProvider.NotEmpty(hash);

            //
            var isHashExists = await IsTokenExistsByHash(hash);
            if (!isHashExists)
            {
                return null;
            }

            //
            var xToken = await GetTokenByHash(hash);
            if (xToken == null)
            {
                return null;
            }

            //
            var isValidToken = IsValidToken(xToken.Token);
            if (!isValidToken)
            {
                return null;
            }

            //
            var result = ParseActionRequest(xToken.Token);

            //
            return result;
        }

        /// <summary>
        /// Validate and Parse Action Hash
        /// </summary>
        /// <param name="hash">token hash string</param>
        /// <param name="forceTokenValidation">specifies chack token Validation Parameter, default is true</param>
        /// <param name="forceActionValidation">specifies check action Validations, default is true</param>
        /// <param name="exception">specify <see>Excetion</see> to thrown on failure</param>
        /// <returns>an instance of <see>XActionRequestToken</see></returns>
        private async Task<XActionRequestToken> ValidateAndParseActionHash(
            string hash,
            bool forceTokenValidation = true,
            bool forceActionValidation = true,
            Exception exception = null
        )
        {
            //
            ValidationProvider.NotEmpty(hash);

            //
            // Prepare Default Exception ...
            if (exception == null)
            {
                exception = XException.InvalidToken.ToException();
            }

            //
            var token = await ValidateAndRetrieveRelatedToken(hash, forceTokenValidation);

            //
            var result = await ParseActionHash(hash);
            if (result == null)
            {
                throw exception;
            }

            //
            if (forceActionValidation)
            {
                ValidateActionRequest(result);
            }

            //
            return result;
        }

        /// <summary>
        /// Validate Action Request
        /// </summary>
        /// <param name="request">an instance of <see>XActionRequestToken</see></param>
        /// <param name="exception">specify <see>Excetion</see> to thrown on failure</param>
        private void ValidateActionRequest(
            XActionRequestToken request,
            Exception exception = null
        )
        {
            //
            ValidationProvider
                .NotNull(request);

            //
            // Prepare Default Exception ...
            if (exception == null)
            {
                exception = XException.InvalidData.ToException();
            }

            //
            var isValid = IsValidActionRequest(request);
            if (!isValid)
            {
                throw exception;
            }
        }

        /// <summary>
        /// Check Action Request Validation
        /// </summary>
        /// <param name="request">an instance of <see>XActionRequestToken</see></param>
        /// <returns>a boolean value</returns>
        private bool IsValidActionRequest(
            XActionRequestToken request
        )
        {
            //
            // Validate Args ...
            if (request == null ||
                Configuration.IdentitySecretKey.IsNullOrEmpty())
            {
                XException.InvalidArgs.Throw();
            }

            //
            var result = request.Validate(Configuration.IdentitySecretKey);

            //
            return result;
        }

        /// <summary>
        /// Check Token and Act Based on it
        /// </summary>
        /// <param name="token">token string</param>
        /// <param name="issueExcepion">specify <see>Excetion</see> to thrown on Issue failure</param>
        /// <param name="exception">specify <see>Excetion</see> to thrown on failure</param>
        /// <returns></returns>
        private async Task ValidateAndHandleToken(
            string token,
            bool issueExcepion = false,
            Exception exception = null
        )
        {
            //
            // Validate Args ...
            ValidationProvider.NotEmpty(token);

            //
            // Prepare Default Exception ...
            if (exception == null)
            {
                exception = XException.InvalidToken.ToException();
            }

            //
            var isValidToken = IsValidToken(token);

            //
            if (!isValidToken)
            {
                //
                await RemoveTokenByToken(token);

                //
                if (issueExcepion)
                {
                    throw exception;
                }
            }
        }

        /// <summary>
        /// Validate a Hash Exists or not 
        /// </summary>
        /// <param name="hash">token hash string</param>
        /// <param name="exception">specify <see>Excetion</see> to thrown on failure</param>
        /// <returns></returns>
        private async Task ValidateHashExists(
            string hash,
            Exception exception = null
        )
        {
            //
            // Validate Args ...
            ValidationProvider.NotEmpty(hash);

            //
            // Prepare Default Exception ...
            if (exception == null)
            {
                exception = XException.InvalidToken.ToException();
            }

            //
            var isExists = await IsTokenExistsByHash(hash);
            if (!isExists)
            {
                throw exception;
            }
        }

        /// <summary>
        /// Validate a Token Exists 
        /// </summary>
        /// <param name="token">token string</param>
        /// <param name="exception">specify <see>Excetion</see> to thrown on failure</param>
        /// <returns></returns>
        private async Task ValidateTokenExists(
            string token,
            Exception exception = null
        )
        {
            //
            // Validate Args ...
            ValidationProvider.NotEmpty(token);

            //
            // Prepare Default Exception ...
            if (exception == null)
            {
                exception = XException.InvalidToken.ToException();
            }

            //
            var isExists = await IsTokenExistsByToken(token);
            if (!isExists)
            {
                throw exception;
            }
        }

        /// <summary>
        /// Validate a Hash and Retrieve it's Corresponding Token
        /// </summary>
        /// <param name="hash">token hash string</param>
        /// <param name="forceTokenValidation">specifies chack token Validation Parameter, default is true</param>
        /// <param name="issueExcepion">specify <see>Excetion</see> to thrown on Issue failure</param>
        /// <param name="exception">specify <see>Excetion</see> to thrown on failure</param>
        /// <returns>token string</returns>
        private async Task<string> ValidateAndRetrieveRelatedToken(
            string hash,
            bool forceTokenValidation = true,
            bool issueExcepion = false,
            Exception exception = null
        )
        {
            //
            // Validate Args ...
            ValidationProvider.NotEmpty(hash);

            //
            // Prepare Default Exception ...
            if (exception == null)
            {
                exception = XException.InvalidToken.ToException();
            }

            //
            await ValidateHashExists(hash);

            //
            var token = await GetRelatedTokenByHash(hash);
            if (token.IsNullOrEmpty())
            {
                throw exception;
            }

            //
            if (forceTokenValidation)
            {
                await ValidateAndHandleToken(token, issueExcepion);
            }

            //
            return token;
        }

        /// <summary>
        /// Validate a Token and Retrieve it's Corresponding Hash
        /// </summary>
        /// <param name="token">token string</param>
        /// <param name="forceTokenValidation">specifies chack token Validation Parameter, default is true</param>
        /// <param name="exception">specify <see>Excetion</see> to thrown on failure</param>
        /// <returns>hash string</returns>
        private async Task<string> ValidateAndRetrieveRelatedHash(
            string token,
            bool forceTokenValidation = true,
            Exception exception = null
        )
        {
            //
            // Validate Args ...
            ValidationProvider.NotEmpty(token);

            //
            // Prepare Default Exception ...
            if (exception == null)
            {
                exception = XException.InvalidToken.ToException();
            }

            //
            if (forceTokenValidation)
            {
                await ValidateAndHandleToken(token);
            }

            //
            await ValidateTokenExists(token);

            //
            var hash = await GetRelatedHashByToken(token);
            if (hash.IsNullOrEmpty())
            {
                throw exception;
            }

            //
            return hash;
        }

        /// <summary>
        /// Validate Invitation Hash 
        /// </summary>
        /// <param name="invitationHash">registration invitation hash string</param>
        /// <param name="forceUserExists">thrown <see>Exception</see> if user Exists, default is true</param>
        /// <returns></returns>
        private async Task ValidateInvitationHash(
            string invitationHash,
            bool forceUserExists = true
        )
        {
            //
            // Validate Args ...
            ValidationProvider.NotNull(Configuration);

            //
            if (Configuration.RegistrationJustWithInvite &&
                invitationHash.IsNullOrEmpty())
            {
                XException.NotAllowed.Throw();
            }

            //
            // Validate Invitation Token if it isn't null ...
            if (!invitationHash.IsNullOrEmpty())
            {
                //
                await ValidateHashExists(invitationHash);

                //
                // Token Validation also done in this task ...
                var relatedToken = await ValidateAndRetrieveRelatedToken(invitationHash);

                //
                var inviteAction = ValidateAndParseActionToken(relatedToken);
                ValidationProvider.NotNull(inviteAction);

                //
                var inviteUerSelectByParam = GetUserSelectByParam(inviteAction);
                var inviteUserSelectBy = GetUserSelectByType(inviteUerSelectByParam);
                if (inviteUserSelectBy != XUserSelectBy.Email)
                {
                    XException.InvalidToken.Throw();
                }

                //
                if (forceUserExists)
                {
                    //
                    await ValidateUserNotExists(
                        inviteUerSelectByParam,
                        XException.EmailInUsed.ToException());
                }
            }
        }
        #endregion

        //
        #region Profile Validators ...
        /// <summary>
        /// Validate a Request is Corresponding to Specific Device
        /// </summary>
        /// <param name="device">an instance of <see>XDevice</see></param>
        /// <param name="requestDevice">specify requested device by an instance of <see>XDevice</see></param>
        /// <param name="exception">specify <see>Excetion</see> to thrown on failure</param>
        private void ValidateRequestAndGiveDevices(
            XDevice device,
            XDevice requestDevice,
            Exception exception = null
        )
        {
            //
            // Validate Args ...
            ValidationProvider.NotNull(device, requestDevice);

            //
            // Prepare Default Exception ...
            if (exception == null)
            {
                exception = XException.InvalidDevice.ToException();
            }

            //
            var isDevicesSame = device.IsSameAs(requestDevice);

            //
            if (!isDevicesSame)
            {
                throw exception;
            }
        }

        /// <summary>
        /// Check Validation of a User SelectBy Param and Password
        /// </summary>
        /// <param name="userSelectByParam">specifies user identifier</param>
        /// <param name="password">user's password</param>
        /// <param name="checkCanLoginPolicies">check a user can log in in system or not, default is true</param>
        /// <param name="exception">specify <see>Excetion</see> to thrown on failure</param>
        /// <returns></returns>
        private async Task ValidateUserAndPassword(
            string userSelectByParam,
            string password,
            bool checkCanLoginPolicies = true,
            Exception exception = null
        )
        {
            //
            // Validate Args ...
            ValidationProvider.NotEmpty(
                userSelectByParam,
                password
            );

            //
            // Prepare Default Exception ...
            if (exception == null)
            {
                exception = XException.LoginFailed.ToException();
            }

            //
            // Retrieve User and Validate User Exists ...
            var user = await ValidateUserExistsAndRetrieve(
                userSelectByParam,
                containDetails: false,
                checkCanLoginPolicies: checkCanLoginPolicies,
                ignoreDisabledUser: false,
                checkIsBanned: true,
                exception: exception);

            //
            // Check Given Password Follows Policies ...
            await ValidatePasswordPolicies(user, password, exception);

            //
            // Check Password for User ...
            var checkPasswordResult = await UserManager.CheckPasswordAsync(user, password);
            if (!checkPasswordResult)
            {
                throw exception;
            }
        }
        #endregion

        //
        #region Friendship Validators ...
        /// <summary>
        /// Validate Friendship Requested Before or not
        /// </summary>
        /// <param name="source">specifies a user to check as source by an instance of <see>XUser</see></param>
        /// <param name="dest">specifies a user to check as dest by an instance of <see>XUser</see></param>
        private void ValidateRequestBefore(
            XUser source,
            XUser dest
        )
        {
            //
            // Validate Args ...
            ValidationProvider.NotNull(source, dest);

            //
            var isRequested = IsFollowRequested(source, dest);
            if (!isRequested)
            {
                XException.NotFound.Throw();
            }
        }

        /// <summary>
        /// Validate a Friendship Not Requested Before 
        /// </summary>
        /// <param name="source">specifies a user to check as source by an instance of <see>XUser</see></param>
        /// <param name="dest">specifies a user to check as dest by an instance of <see>XUser</see></param>
        private void ValidateNotRequestBefore(
            XUser source,
            XUser dest
        )
        {
            //
            // Validate Args ...
            ValidationProvider.NotNull(source, dest);

            //
            var isRequested = IsFollowRequested(source, dest);
            if (isRequested)
            {
                XException.Duplicate.Throw();
            }
        }

        /// <summary>
        /// Validate User Can Send Following Request to Dest User
        /// </summary>
        /// <param name="accepterUser">specifies a user to check as dest by an instance of <see>XUser</see></param>
        /// <param name="requesterUser">specifies a user to check as source by an instance of <see>XUser</see></param>
        private void ValidateFollowingRequest(
            XUser accepterUser,
            XUser requesterUser
        )
        {
            //
            // Validate Args ...
            ValidationProvider.NotNull(accepterUser, requesterUser);

            //
            var isRequest = IsFollowRequested(requesterUser, accepterUser, XFriendshipState.Pending);
            if (!isRequest)
            {
                XException.NotFound.Throw();
            }
        }

        /// <summary>
        /// Validate a User can Accept a Following Request or Not
        /// </summary>
        /// <param name="accepterUser">specifies a user to check as dest by an instance of <see>XUser</see></param>
        /// <param name="requesterUser">specifies a user to check as source by an instance of <see>XUser</see></param>
        private void ValidateFollowingRequestForAccept(
            XUser accepterUser,
            XUser requesterUser
        )
        {
            //
            // Validate Args ...
            ValidationProvider.NotNull(accepterUser, requesterUser);

            //
            var isRequestPending = IsFollowRequested(requesterUser, accepterUser, XFriendshipState.Pending);
            var isRequestRejected = IsFollowRequested(requesterUser, accepterUser, XFriendshipState.Rejected);
            if (!isRequestPending &&
                !isRequestRejected)
            {
                XException.NotFound.Throw();
            }
        }

        /// <summary>
        /// Validate a Request is not Passed for Same Users 
        /// </summary>
        /// <param name="source">specifies a user to check as source by an instance of <see>XUser</see></param>
        /// <param name="dest">specifies a user to check as dest by an instance of <see>XUser</see></param>
        private void ValidateNotSameUsers(
            XUser source,
            XUser dest
        )
        {
            //
            // Validate ARgs ...
            ValidationProvider.NotNull(source, dest);

            //
            var isSame = source.Id == dest.Id;
            if (isSame)
            {
                XException.ActionFailed.Throw();
            }
        }

        /// <summary>
        /// Check a user is in Followers of another
        /// </summary>
        /// <param name="source">specifies a user to check as source by an instance of <see>XUser</see></param>
        /// <param name="dest">specifies a user to check as dest by an instance of <see>XUser</see></param>
        private void ValidateIsFollowers(
            XUser source,
            XUser dest
        )
        {
            //
            // Validate Args ...
            ValidationProvider.NotNull(source, dest);

            //
            ValidateNotSameUsers(source, dest);
            ValidateRequestBefore(dest, source);

            //
            var isFollower = IsFollowRequested(dest, source, XFriendshipState.Accepted) ||
                IsFollowRequested(dest, source, XFriendshipState.Blocked);
            if (!isFollower)
            {
                XException.NotFound.Throw();
            }
        }

        /// <summary>
        /// Check a user is in Followings of another
        /// </summary>
        /// <param name="source">specifies a user to check as source by an instance of <see>XUser</see></param>
        /// <param name="dest">specifies a user to check as dest by an instance of <see>XUser</see></param>
        private void ValidateIsFollowings(
            XUser source,
            XUser dest
        )
        {
            //
            // Validate Args ...
            ValidationProvider.NotNull(source, dest);

            //
            ValidateNotSameUsers(source, dest);
            ValidateRequestBefore(source, dest);

            //
            var isFollowing = IsFollowRequested(source, dest, XFriendshipState.Accepted);
            if (!isFollowing)
            {
                XException.NotFound.Throw();
            }
        }

        /// <summary>
        /// Validate a User Blocked another
        /// </summary>
        /// <param name="source">specifies a user to check as source by an instance of <see>XUser</see></param>
        /// <param name="dest">specifies a user to check as dest by an instance of <see>XUser</see></param>
        private void ValidateIsBlock(
            XUser source,
            XUser dest
        )
        {
            //
            // Validate Args ...
            ValidationProvider.NotNull(source, dest);

            //
            ValidateNotSameUsers(source, dest);
            ValidateRequestBefore(dest, source);

            //
            var isFollower = IsFollowRequested(dest, source, XFriendshipState.Blocked);
            if (!isFollower)
            {
                XException.NotFound.Throw();
            }
        }
        #endregion

        //
        #region XActionRequest Validators ...
        /// <summary>
        /// Validate a Device for Request
        /// </summary>
        /// <param name="device">an instance of <see>XDevice</see></param>
        /// <param name="requestDevice">specify requested device by an instance of <see>XDevice</see></param>
        /// <param name="exception">specify <see>Excetion</see> to thrown on failure</param>
        private void ValidateRequestAndGivenDevices(
            XDevice device,
            XDevice requestDevice,
            Exception exception = null
        )
        {
            //
            // Validate Args ...
            ValidationProvider.NotNull(device, requestDevice);

            //
            // Prepare Default Exception ...
            if (exception == null)
            {
                exception = XException.InvalidDevice.ToException();
            }

            //
            var isDevicesSame = device.IsSameAs(requestDevice);

            //
            if (!isDevicesSame)
            {
                throw exception;
            }
        }
        #endregion

        //
        #region XVerification Request ...
        /// <summary>
        /// Validate Verification Request Exists by Device
        /// </summary>
        /// <param name="device">an instance of <see>XDevice</see></param>
        /// <param name="exception">specify <see>Excetion</see> to thrown on failure</param>
        /// <returns></returns>
        private async Task ValidateVerificationRequestExists(
            XDevice device,
            Exception exception = null
        )
        {
            //
            ValidationProvider.NotNull(device);

            //
            if (exception == null)
            {
                exception = XException.InvalidDevice.ToException();
            }

            //
            var isExists = await IsDeviceRequestedForVerificationCodeBefor(device);
            if (!isExists)
            {
                throw exception;
            }
        }

        /// <summary>
        /// Validate Verification Request Exists by VerificationCode
        /// </summary>
        /// <param name="verificationCode">Confirm Verification Code</param>
        /// <param name="exception">specify <see>Excetion</see> to thrown on failure</param>
        /// <returns></returns>
        private async Task ValidateVerificationRequestExists(
            string verificationCode,
            Exception exception = null
        )
        {
            //
            ValidationProvider.NotEmpty(verificationCode);

            //
            if (exception == null)
            {
                exception = XException.InvalidVerificationCode.ToException();
            }

            //
            var isExists = await IsVerificationCodeRequested(verificationCode);
            if (!isExists)
            {
                throw exception;
            }
        }

        /// <summary>
        /// Validate and Retrive Verification Request for Given Device
        /// </summary>
        /// <param name="device">an instance of <see>XDevice</see></param>
        /// <param name="exception">specify <see>Excetion</see> to thrown on failure</param>
        /// <returns>an instance of <see>XVerificationRequest</see></returns>
        private async Task<XVerificationRequest> ValidateAndRetrieveVerificationRequest(
            XDevice device,
            Exception exception = null
        )
        {
            //
            ValidationProvider.NotNull(device);

            //
            if (exception == null)
            {
                exception = XException.InvalidDevice.ToException();
            }

            //
            await ValidateVerificationRequestExists(device);

            //
            var result = await GetVerificationRequest(device);
            if (result == null)
            {
                throw exception;
            }

            //
            return result;
        }

        /// <summary>
        /// Validate and Retrieve Verification Request for Given VerificationCode
        /// </summary>
        /// <param name="verificationCode">Confirm Verification Code</param>
        /// <param name="exception">specify <see>Excetion</see> to thrown on failure</param>
        /// <returns>an instance of <see>XVerificationRequest</see></returns>
        private async Task<XVerificationRequest> ValidateAndRetrieveVerificationRequest(
            string verificationCode,
            Exception exception = null
        )
        {
            //
            ValidationProvider.NotEmpty(verificationCode);

            //
            if (exception == null)
            {
                exception = XException.InvalidVerificationCode.ToException();
            }

            //
            await ValidateVerificationRequestExists(verificationCode);

            //
            var result = await GetVerificationRequest(verificationCode);
            if (result == null)
            {
                throw exception;
            }

            //
            return result;
        }

        /// <summary>
        /// Handle Prepare Verification Request
        /// </summary>
        /// <param name="verificationCode">Confirm Verification Code</param>
        /// <param name="request">an instance of <see>XActionRequestToken</see></param>
        /// <returns>an instance of <see>XVerificationRequest</see></returns>
        private async Task<XVerificationRequest> HandleVerificationRequestPreparation(
            string verificationCode,
            XActionRequestToken request
        )
        {
            //
            ValidationProvider
                .NotEmpty(verificationCode);

            //
            // Check Action Request Validation ...
            ValidateActionRequest(request);

            //
            var device = request.Context.Device;

            //
            // Check is Device Requested Before or not ...
            XVerificationRequest xVerificationRequest = null;
            var isDeviceRequested = await IsDeviceRequestedForVerificationCodeBefor(device);
            if (!isDeviceRequested)
            {
                //
                xVerificationRequest = new XVerificationRequest
                {
                    VerificationCode = verificationCode,
                    NumberOfTries = 1,
                    LastTryOn = DateTime.UtcNow,
                    Device = device,
                    Request = request
                };

                //
                await AddVerificationRequest(xVerificationRequest);
            }
            else
            {
                //
                // Get Verification Request ...
                xVerificationRequest = await ValidateAndRetrieveVerificationRequest(device);
            }

            //
            return xVerificationRequest;
        }
        #endregion        
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\xIds\Providers\XIdentityManager\XIdentityManager+VerificationCode.cs

using System.Threading.Tasks;
using xCommons.Extensions;
using xIdentityModels.Extensions;
using xIdentityModels.Models;
using xIdentityModels.Navigations;

namespace xIds.Providers
{
    public partial class XIdentityManager
    {
        //
        #region Verification Code Actions ...
        /// <summary>
        /// Check a Device Requeste for Verification Code before or not
        /// </summary>
        /// <param name="device">an instance of <see>XDevice</see></param>
        /// <returns>a boolean value</returns>
        private async Task<bool> IsDeviceRequestedForVerificationCodeBefor(
            XDevice device
        )
        {
            //
            var result = false;
            var enumerator = DbContext.VerificationRequests
                .AsAsyncEnumerable();
            await
            foreach (var entity in enumerator)
            {
                //
                if (entity.Device.IsSameAs(device))
                {
                    //
                    result = true;
                    break;
                }
            }

            //
            return result;
        }

        /// <summary>
        /// Check a Verification Code Requested before or not
        /// </summary>
        /// <param name="verificationCode">Confirm Verification Code</param>
        /// <returns>a boolean value</returns>
        private async Task<bool> IsVerificationCodeRequested(
            string verificationCode
        )
        {
            //
            // Validate Args ...
            if (verificationCode.IsNullOrEmpty())
            {
                return false;
            }

            //
            var result = false;
            var enumerator = DbContext.VerificationRequests
                .AsAsyncEnumerable();
            await
            foreach (var entity in enumerator)
            {
                //
                if (entity.VerificationCode == verificationCode)
                {
                    //
                    result = true;
                    break;
                }
            }

            //
            return result;
        }

        /// <summary>
        /// Retrieve Verification Request
        /// </summary>
        /// <param name="device">an instance of <see>XDevice</see></param>
        /// <returns>an instance of <see>XVerificationRequest</see></returns>
        private async Task<XVerificationRequest> GetVerificationRequest(
            XDevice device
        )
        {
            //
            XVerificationRequest result = null;
            var enumerator = DbContext.VerificationRequests
                .AsAsyncEnumerable();
            await
            foreach (var entity in enumerator)
            {
                //
                if (entity.Device.IsSameAs(device))
                {
                    //
                    result = entity;
                    break;
                }
            }

            //
            return result;
        }

        /// <summary>
        /// Retrieve Verification Request
        /// </summary>
        /// <param name="verificationCode">Confirm Verification Code</param>
        /// <returns>an instance of <see>XVerificationRequest</see></returns>
        private async Task<XVerificationRequest> GetVerificationRequest(
            string verificationCode
        )
        {
            //
            XVerificationRequest result = null;
            var enumerator = DbContext.VerificationRequests
                .AsAsyncEnumerable();
            await
            foreach (var entity in enumerator)
            {
                //
                if (entity.VerificationCode == verificationCode)
                {
                    //
                    result = entity;
                    break;
                }
            }

            //
            return result;
        }

        /// <summary>
        /// Remove Exists Verification Code Request
        /// </summary>
        /// <param name="device">an instance of <see>XDevice</see></param>
        /// <param name="saveChanges">save changes on DbContext, default is true</param>
        /// <returns></returns>
        private async Task RemoveVerificationCodeRequestByDevice(
            XDevice device,
            bool saveChanges = true
        )
        {
            //
            if (!await IsDeviceRequestedForVerificationCodeBefor(device))
            {
                return;
            }

            //
            var xvr = await GetVerificationRequest(device);
            DbContext.VerificationRequests.Remove(xvr);

            //
            if (saveChanges)
            {
                await DbContext.SaveChangesAsync();
            }
        }

        /// <summary>
        /// Remove Exists Verification Code Request
        /// </summary>
        /// <param name="verificationCode">Confirm Verification Code</param>
        /// <param name="saveChanges">save changes on DbContext, default is true</param>
        /// <returns></returns>
        private async Task RemoveVerificationRequest(
            string verificationCode,
            bool saveChanges = true
        )
        {
            //
            ValidationProvider.NotEmpty(verificationCode);

            //
            var request = await GetVerificationRequest(verificationCode);
            DbContext.VerificationRequests.Remove(request);

            //
            if (saveChanges)
            {
                await DbContext.SaveChangesAsync();
            }
        }

        /// <summary>
        /// Add Verification Code Request
        /// </summary>
        /// <param name="request">an instance of <see>XVerificationRequest</see></param>
        /// <param name="saveChanges">save changes on DbContext, default is true</param>
        /// <returns>an instance of <see>XVerificationRequest</see></returns>
        private async Task<XVerificationRequest> AddVerificationRequest(
            XVerificationRequest request,
            bool saveChanges = true
        )
        {
            //
            if (await IsDeviceRequestedForVerificationCodeBefor(request.Device))
            {
                await RemoveVerificationCodeRequestByDevice(request.Device);
            }

            //
            var entry = await DbContext.VerificationRequests.AddAsync(request);

            //
            if (saveChanges)
            {
                await DbContext.SaveChangesAsync();
            }

            //
            return entry.Entity;
        }
        #endregion        
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\xIds\Providers\XIdentityManager.cs

using System.Collections.Generic;
using System.Linq;
using Microsoft.AspNetCore.Identity;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Logging;
using Newtonsoft.Json;
using Newtonsoft.Json.Serialization;
using xCommons.Extensions;
using xCommons.Providers;
using xExceptions.Constants;
using xIdentityModels;
using xIdentityModels.Configurations;
using xIdentityModels.Constants;
using xIdentityModels.Models;
using xMessageService.Interfaces;
using xStorageService.Interfaces;
using xIds.Configurations;
using xIds.DbContext;
using xIds.Interfaces;

namespace xIds.Providers
{
    public partial class XIdentityManager : IXIdentityManager
    {
        //
        private JsonSerializerSettings jsonSerializerSettings;

        //
        public XIdentityDbContext DbContext { get; }
        public UserManager<XUser> UserManager { get; }
        public IXIdentityHelper IdentityHelper { get; }
        public ILogger<IXIdentityManager> Logger { get; }
        public IXMessageProvider MessageProvider { get; }
        public IXStorageProvider StorageProvider { get; }
        public SignInManager<XUser> SignInManager { get; }
        public IXSecurityProvider SecurityProvider { get; }
        public XIdentityConfiguration Configuration { get; }
        public RoleManager<IdentityRole> RoleManager { get; }
        public XValidationProvider ValidationProvider { get; }
        public XDataServiceConfiguration DataConfiguration { get; }
        public IXIdentityMessageProvider IdentityMessageProvider { get; }
        public XIdentityResourceConfiguration IdentityResourceConfiguration { get; }

        public XIdentityManager(
            XIdentityDbContext dbContext,
            UserManager<XUser> userManager,
            IXIdentityHelper identityHelper,
            ILogger<IXIdentityManager> logger,
            IXMessageProvider messageProvider,
            IXStorageProvider storageProvider,
            SignInManager<XUser> signInManager,
            IXSecurityProvider securityProvider,
            XIdentityConfiguration configuration,
            RoleManager<IdentityRole> roleManager,
            XValidationProvider validationProvider,
            XDataServiceConfiguration dataConfiguration,
            IXIdentityMessageProvider identityMessageProvider,
            XIdentityResourceConfiguration identityResourceConfiguration
        )
        {
            //
            Logger = logger;
            DbContext = dbContext;
            RoleManager = roleManager;
            UserManager = userManager;
            SignInManager = signInManager;
            SecurityProvider = securityProvider;
            Configuration = configuration;
            IdentityHelper = identityHelper;
            MessageProvider = messageProvider;
            StorageProvider = storageProvider;
            DataConfiguration = dataConfiguration;
            ValidationProvider = validationProvider;
            IdentityMessageProvider = identityMessageProvider;
            IdentityResourceConfiguration = identityResourceConfiguration;

            //
            this.jsonSerializerSettings = new JsonSerializerSettings
            {
                ContractResolver = new CamelCasePropertyNamesContractResolver()
            };
        }

        //
        #region Class Getter (s) Methods ...
        /// <summary>
        /// Retrieve User DB Set
        /// </summary>
        /// <param name="containDetails">specifies returned object contains all Navigation Properties or not, default is false</param>
        /// <returns></returns>
        public IQueryable<XUser> GetUsersDbSet(
            bool containDetails = false
        )
        {
            //
            var dbSet = containDetails ? GetUsersFullDbSet() :
                UserManager.Users;
            return dbSet;
        }

        /// <summary>
        /// Retrieve User Db Set Full Navigation Properties 
        /// </summary>
        /// <param name="enableTracking"></param>
        /// <returns></returns>
        public IQueryable<XUser> GetUsersFullDbSet(bool enableTracking = false)
        {
            //
            var dbSet = UserManager.Users
                .Include(u => u.Roles)
                .Include(u => u.Devices)
                .Include(u => u.Followers)
                .Include(u => u.Followings)
                .Include(u => u.Avatars);

            //
            return dbSet.AsSplitQuery();
        }
        #endregion

        //
        #region Tools ...
        /// <summary>
        /// Get User SelectBy Param 
        /// </summary>
        /// <param name="model"></param>
        /// <param name="forceNotNull"></param>
        /// <param name="excludes"></param>
        /// <returns></returns>
        public string GetUserSelectByParam(
            XActionRequest model,
            bool forceNotNull = true,
            ICollection<XUserSelectBy> excludes = null
        )
        {
            //
            // Validate Args ...
            ValidationProvider.NotNull(model);

            //
            var id = model.UserId;
            var userName = model.UserName;
            var email = model.Email;
            var phoneNumber = model.MobileNumber;

            //
            if (excludes != null)
            {
                //
                if (excludes.Contains(XUserSelectBy.ID))
                {
                    id = null;
                }
                if (excludes.Contains(XUserSelectBy.Email))
                {
                    email = null;
                }
                if (excludes.Contains(XUserSelectBy.MobileNumber))
                {
                    phoneNumber = null;
                }
                if (excludes.Contains(XUserSelectBy.Username))
                {
                    userName = null;
                }
            }

            var selectByParam =
                id.IsNullOrEmpty() ?
                userName.IsNullOrEmpty() ?
                email.IsNullOrEmpty() ?
                phoneNumber.IsNullOrEmpty() ? null : phoneNumber : email : userName : id;

            //
            // Check result ...
            if (forceNotNull &&
                selectByParam.IsNullOrEmpty())
            {
                XException.InvalidData.Throw();
            }

            //
            return selectByParam;
        }
        #endregion
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\xIds\Providers\XIdentityMessageProvider.cs

using System.Linq;
using Microsoft.Extensions.Logging;
using xCommons.Extensions;
using xExceptions.Constants;
using xIdentityModels.Configurations;
using xIds.Constants;
using xIds.Interfaces;

namespace xIds.Providers
{
    public class XIdentityMessageProvider : IXIdentityMessageProvider
    {
        //
        public string InviteMsg { get; set; }
        public string RegistrationApproveMsg { get; set; }
        public string RegisteredMsg { get; set; }
        public string VerificationCodeMsg { get; set; }
        public string ChangePasswordMsg { get; set; }
        public string PasswordChangedMsg { get; set; }
        public string NewDeviceLoggedInMsg { get; set; }

        private readonly ILogger<IXIdentityMessageProvider> logger;
        private readonly XIdentityConfiguration identityConfiguration;

        public XIdentityMessageProvider(
            ILogger<IXIdentityMessageProvider> logger,
            XIdentityConfiguration identityConfiguration
        )
        {
            this.logger = logger;
            this.identityConfiguration = identityConfiguration;
        }

        /// <summary>
        /// Determine All things is Ready or Not
        /// </summary>
        /// <returns></returns>
        public bool IsReady()
        {
            return !InviteMsg.IsNullOrEmpty() &&
                !RegistrationApproveMsg.IsNullOrEmpty() &&
                !RegisteredMsg.IsNullOrEmpty() &&
                !VerificationCodeMsg.IsNullOrEmpty() &&
                !ChangePasswordMsg.IsNullOrEmpty() &&
                !PasswordChangedMsg.IsNullOrEmpty() &&
                !NewDeviceLoggedInMsg.IsNullOrEmpty();
        }

        /// <summary>
        /// Retrieve a Translated Value Based on Given Lang
        /// </summary>
        /// <param name="resourceTitle"></param>
        /// <param name="lang"></param>
        /// <returns></returns>
        private string GetStringResource(string resourceTitle, string lang)
        {
            //
            var item = identityConfiguration.IdentityMessages
                .FirstOrDefault(sr =>
                    sr.Language.ToNormalString() == lang.ToNormalString() &&
                    sr.ResourceTitle.ToNormalString() == resourceTitle.ToNormalString());
            //
            if (item == null)
            {
                return null;
            }

            //     
            return item.TranslatedValue;
        }

        /// <summary>
        /// Prepare Helper Class and Fill Messages 
        /// with Specific Language
        /// </summary>
        /// <param name="lang"></param>
        public void PrepareMessages(string lang)
        {
            //
            InviteMsg = GetStringResource(IdentityMessagesKeys.InviteMsg, lang);
            RegisteredMsg = GetStringResource(IdentityMessagesKeys.RegisteredMsg, lang);
            ChangePasswordMsg = GetStringResource(IdentityMessagesKeys.ChangePasswordMsg, lang);
            PasswordChangedMsg = GetStringResource(IdentityMessagesKeys.PasswordChangedMsg, lang);
            VerificationCodeMsg = GetStringResource(IdentityMessagesKeys.VerificationCodeMsg, lang);
            NewDeviceLoggedInMsg = GetStringResource(IdentityMessagesKeys.NewDeviceLoggedInMsg, lang);
            RegistrationApproveMsg = GetStringResource(IdentityMessagesKeys.RegistrationApproveMsg, lang);

            //
            if (!IsReady())
            {
                XException.InvalidArgs.Throw();
            }
        }
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\xIds\Providers\XIdentityProfileService.cs

using System.Linq;
using System.Threading.Tasks;
using IdentityServer4.Extensions;
using IdentityServer4.Models;
using IdentityServer4.Services;
using Microsoft.AspNetCore.Identity;
using xCommons.Extensions;
using xIdentityModels;
using xIds.Interfaces;

namespace xIds.Providers
{
    public class XIdentityProfileService : IProfileService
    {
        private readonly IXIdentityManager identityManager;
        private readonly IUserClaimsPrincipalFactory<XUser> userClaimsPrincipalFacotry;

        public XIdentityProfileService(
            IXIdentityManager identityManager,
            IUserClaimsPrincipalFactory<XUser> userClaimsPrincipalFacotry
        )
        {
            this.identityManager = identityManager;
            this.userClaimsPrincipalFacotry = userClaimsPrincipalFacotry;
        }

        public async Task GetProfileDataAsync(ProfileDataRequestContext context)
        {
            //
            var sub = context.Subject.GetSubjectId();
            var user = await identityManager.GetUserAsync(sub, true);
            var principal = await userClaimsPrincipalFacotry.CreateAsync(user);

            //
            var claims = principal.Claims.ToList();

            //
            context.IssuedClaims = claims;
        }

        public async Task IsActiveAsync(IsActiveContext context)
        {
            //
            var sub = context.Subject.GetSubjectId();
            var user = await identityManager.GetUserAsync(sub);

            //
            context.IsActive = !user.IsNull() && user.IsEnable && !user.IsBanned;
        }
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\xIds\Providers\XSecurityProvider.cs

using System;
using System.IO;
using System.Security.Cryptography;
using System.Text;
using xCommons.Extensions;
using xCommons.Providers;
using xIds.Configurations;
using xIds.Interfaces;

namespace xIds.Providers
{
    public class XSecurityProvider : IXSecurityProvider
    {
        //
        #region Props ...
        private readonly string secretKey;
        private readonly byte[] iv;
        private readonly byte[] key;
        private readonly XValidationProvider validationProvider;
        #endregion

        //
        #region Constructor ...
        public XSecurityProvider(
            XIdentityResourceConfiguration identityConfiguration,
            XValidationProvider validationProvider
        )
        {
            //
            this.secretKey = identityConfiguration.XRevisionSecretKey.ToMd5String();
            this.validationProvider = validationProvider;

            //
            var ivBytes = new byte[16];
            var keyBytes = new byte[32];
            var secretBytes = Encoding.UTF8.GetBytes(this.secretKey);

            //
            Array.Copy(
                secretBytes,
                ivBytes,
                secretBytes.Length < ivBytes.Length ?
                secretBytes.Length :
                ivBytes.Length
            );
            this.iv = ivBytes;

            //
            Array.Copy(
                secretBytes,
                keyBytes,
                secretBytes.Length < keyBytes.Length ?
                secretBytes.Length :
                keyBytes.Length
            );
            this.key = keyBytes;

            // Encoding.UTF8.GetBytes (this.secretKey);
        }
        #endregion

        //
        #region Actions ...
        public string Encrypt(string plainText)
        {
            //
            validationProvider.NotEmpty(plainText);

            //
            var textBytes = Encoding.UTF8.GetBytes(plainText);
            var result = EncryptFromBytes(textBytes);

            //
            return result;
        }

        public string Decrypt(string cipherText)
        {
            //
            validationProvider.NotEmpty(cipherText);

            //
            var cipherBytes = Convert.FromBase64String(cipherText);
            var result = DecryptFromBytes(cipherBytes);

            //
            return result;
        }

        public string EncryptFromBytes(byte[] textBytes)
        {
            //
            // Validate Args ...
            validationProvider.NotNull(textBytes);

            // Declare the string used to hold
            // the decrypted text.
            byte[] encryptedBytes = null;

            // Create an RijndaelManaged object
            // with the specified key and IV.
            using (var rijAlg = new RijndaelManaged())
            {
                //Settings
                rijAlg.Mode = CipherMode.CBC;
                rijAlg.Padding = PaddingMode.PKCS7;
                // rijAlg.FeedbackSize = 128;

                rijAlg.Key = key;
                rijAlg.IV = iv;

                //
                using (var encryptor = rijAlg.CreateEncryptor(rijAlg.Key, rijAlg.IV))
                {
                    encryptedBytes = encryptor.TransformFinalBlock(textBytes, 0, textBytes.Length);
                }
            }

            //
            return Convert.ToBase64String(encryptedBytes);
        }

        public string DecryptFromBytes(byte[] cipherBytes)
        {
            //
            // Validate Args ...
            validationProvider.NotNull(cipherBytes);

            // Declare the string used to hold
            // the decrypted text.
            string plaintext = null;

            // Create an RijndaelManaged object
            // with the specified key and IV.
            using (var rijAlg = new RijndaelManaged())
            {
                //Settings
                rijAlg.Mode = CipherMode.CBC;
                rijAlg.Padding = PaddingMode.PKCS7;
                // rijAlg.FeedbackSize = 128;

                rijAlg.Key = key;
                rijAlg.IV = iv;

                // Create a decrytor to perform the stream transform.
                var decryptor = rijAlg.CreateDecryptor(rijAlg.Key, rijAlg.IV);

                // Create the streams used for decryption.
                using (var msDecrypt = new MemoryStream(cipherBytes))
                {
                    using (var csDecrypt = new CryptoStream(msDecrypt, decryptor, CryptoStreamMode.Read))
                    {
                        using (var srDecrypt = new StreamReader(csDecrypt))
                        {
                            // Read the decrypted bytes from the decrypting stream
                            // and place them in a string.
                            plaintext = srDecrypt.ReadToEnd();
                        }
                    }
                }
            }

            //
            return plaintext;
        }
        #endregion
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\xIds\Stores\XPersistedGrantStore.cs

using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using IdentityServer4.EntityFramework.DbContexts;
using IdentityServer4.EntityFramework.Mappers;
using IdentityServer4.Models;
using IdentityServer4.Stores;
using Microsoft.EntityFrameworkCore;

namespace xIds.Stores
{
    public class XPersistedGrantStore : IPersistedGrantStore
    {
        private readonly PersistedGrantDbContext dbContext;

        public XPersistedGrantStore(PersistedGrantDbContext dbContext)
        {
            this.dbContext = dbContext;
        }

        public async Task<IEnumerable<PersistedGrant>> GetAllAsync(string subjectId)
        {
            //
            var result = (await dbContext.PersistedGrants
                .Where(g => g.SubjectId == subjectId)
                .AsNoTracking()
                .Select(res => res.ToModel())
                .ToListAsync()).AsEnumerable();

            //
            return result;
        }

        public async Task<PersistedGrant> GetAsync(string key)
        {
            //
            var result = await dbContext.PersistedGrants
                .FirstOrDefaultAsync(g => g.Key == key);

            //
            return result.ToModel();
        }

        public async Task RemoveAllAsync(string subjectId, string clientId)
        {
            //
            var items = await dbContext.PersistedGrants
                .Where(g =>
                    g.SubjectId == subjectId &&
                    g.ClientId == clientId)
                .ToListAsync();

            //
            dbContext.PersistedGrants.RemoveRange(items);

            //
            await dbContext.SaveChangesAsync();
        }

        public async Task RemoveAllAsync(string subjectId, string clientId, string type)
        {
            //
            var items = await dbContext.PersistedGrants
                .Where(g =>
                    g.SubjectId == subjectId &&
                    g.ClientId == clientId &&
                    g.Type == type)
                .ToListAsync();

            //
            dbContext.PersistedGrants.RemoveRange(items);

            //
            await dbContext.SaveChangesAsync();
        }

        public async Task RemoveAsync(string key)
        {
            //
            var items = await dbContext.PersistedGrants
                .Where(g => g.Key == key)
                .ToListAsync();

            //
            dbContext.PersistedGrants.RemoveRange(items);

            //
            await dbContext.SaveChangesAsync();
        }

        public async Task<bool> IsExistsAsync(string key)
        {
            return await this.dbContext.PersistedGrants.AnyAsync(g => g.Key == key);
        }

        public async Task<bool> IsExistsAsync(PersistedGrant grant)
        {
            return await IsExistsAsync(grant.Key);
        }

        public async Task AddOrUpdateAsync(PersistedGrant grant)
        {
            //
            var isExists = await IsExistsAsync(grant);
            if (isExists)
            {
                await UpdateAsync(grant);
            }
            else
            {
                await AddAsync(grant);
            }
        }

        public async Task AddAsync(PersistedGrant grant)
        {
            //
            var item = grant.ToEntity();
            await dbContext.PersistedGrants.AddAsync(item);
            await dbContext.SaveChangesAsync();
        }

        public async Task UpdateAsync(PersistedGrant grant)
        {
            //
            var item = grant.ToEntity();
            var entity = dbContext.Attach(item);
            entity.State = EntityState.Modified;
            await dbContext.SaveChangesAsync();
        }

        public async Task StoreAsync(PersistedGrant grant)
        {
            await AddOrUpdateAsync(grant);
        }

        //
        // TODO: Complete this ...
        public Task<IEnumerable<PersistedGrant>> GetAllAsync(PersistedGrantFilter filter)
        {
            throw new System.NotImplementedException();
        }

        //
        // TODO: Complete this ...
        public Task RemoveAllAsync(PersistedGrantFilter filter)
        {
            throw new System.NotImplementedException();
        }
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\xIds\Validators\XResourceOwnerPasswordValidator.cs

using System;
using System.Threading.Tasks;
using IdentityServer4.Events;
using IdentityServer4.Models;
using IdentityServer4.Services;
using IdentityServer4.Validation;
using Microsoft.Extensions.Logging;
using xCommons.Extensions;
using xExceptions.Constants;
using xIdentityModels.Navigations;
using xIds.Interfaces;
using static IdentityModel.OidcConstants;

namespace xIds.Validators
{
    public class XResourceOwnerPasswordValidator : IResourceOwnerPasswordValidator
    {
        private readonly IXIdentityManager identityManager;
        private readonly IEventService events;
        private readonly ILogger<XResourceOwnerPasswordValidator> logger;

        public XResourceOwnerPasswordValidator(
            IXIdentityManager identityProvider,
            IEventService events,
            ILogger<XResourceOwnerPasswordValidator> logger
        )
        {
            this.identityManager = identityProvider;
            this.events = events;
            this.logger = logger;
        }

        /// <summary>
        /// Validates the resource owner password credential
        /// by providing UserName/Email or PhoneNumber
        /// </summary>
        /// <param name="context">The context.</param>
        /// <returns></returns>
        public virtual async Task ValidateAsync(ResourceOwnerPasswordValidationContext context)
        {
            //
            var clientId = context.Request?.Client?.ClientId;
            var xUser = await identityManager.GetUserAsync(context.UserName, true);

            //
            // Check Force Data ...
            var isForced = true;
            var isForcedStr = context.Request?.Raw["force"];
            if (!isForcedStr.IsNullOrEmpty())
            {
                isForced = isForcedStr.FromJSON<bool>();
            }

            //
            XDevice device = null;
            var language = context.Request?.Raw["language"];
            var deviceStr = context.Request?.Raw["device"];
            if (deviceStr.IsNullOrEmpty() && isForced)
            {
                //
                logger.LogError($"Device not Found ...");

                //
                await events
                    .RaiseAsync(
                        new UserLoginFailureEvent(
                            xUser.UserName,
                            XException.InvalidDevice.ToXError().Message,
                            false,
                            clientId
                        ));
                return;
            }
            device = isForced ? deviceStr.FromJSON<XDevice>() : null;

            //
            XException exception;
            if (!xUser.IsNull())
            {
                //
                var result = await identityManager
                    .CheckPasswordSignInAsync(
                        xUser,
                        context.Password,
                        device,
                        language,
                        true,
                        isForced
                    );
                if (result.Succeeded)
                {
                    //
                    logger.LogInformation("Credentials validated for username: {username}", xUser.UserName);

                    //
                    // Update User Last Login ...
                    xUser.LastLogin = DateTime.UtcNow;
                    await identityManager.UpdateUserAsync(xUser);

                    //
                    await events.RaiseAsync(
                        new UserLoginSuccessEvent(
                            xUser.UserName, xUser.Id, xUser.UserName, false, clientId
                        ));

                    //
                    context.Result = new GrantValidationResult(xUser.Id, AuthenticationMethods.Password);
                    return;
                }
                else if (result.IsLockedOut)
                {
                    //
                    logger.LogInformation("Authentication failed for username: {username}, reason: locked out", xUser.UserName);

                    //
                    exception = XException.AccountLockedOut;
                    await events
                        .RaiseAsync(
                            new UserLoginFailureEvent(
                                xUser.UserName,
                                exception.ToXError().Message,
                                false,
                                clientId
                            ));
                }
                else if (result.IsNotAllowed)
                {
                    //
                    logger.LogInformation("Authentication failed for username: {username}, reason: not allowed", xUser.UserName);

                    //
                    exception = XException.NotAllowed;
                    await events
                        .RaiseAsync(
                            new UserLoginFailureEvent(
                                xUser.UserName,
                                exception.ToXError().Message,
                                false,
                                clientId
                            ));
                }
                else
                {
                    //
                    logger.LogInformation("Authentication failed for username: {username}, reason: invalid credentials", xUser.UserName);

                    //
                    exception = XException.LoginFailed;
                    await events
                        .RaiseAsync(
                            new UserLoginFailureEvent(
                                xUser.UserName,
                                exception.ToXError().Message,
                                false,
                                clientId
                            ));

                    //

                }
            }
            else
            {
                //
                logger.LogInformation("No user found matching username: {username}", xUser.UserName);

                //
                exception = XException.InvalidUserName;
                await events
                    .RaiseAsync(
                        new UserLoginFailureEvent(
                            xUser.UserName,
                            exception.ToXError().Message,
                            false,
                            clientId
                        ));
            }

            //
            Exception ecs = exception.ToException();
            if (exception == XException.AccountLockedOut && xUser.LockoutEnd.HasValue)
            {
                //
                var passedTime = xUser.LockoutEnd.Value.UtcDateTime;
                ecs = XException.AccountLockedOut
                    .AddContentToException(passedTime.ToString());
            }

            //
            context.Result = new GrantValidationResult(TokenRequestErrors.InvalidGrant, ecs.Message);
        }
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\xIds\Program.cs

using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Hosting;

namespace xIds
{
    public class Program
    {
        public static void Main(string[] args)
        {
            CreateHostBuilder(args).Build().Run();
        }

        public static IHostBuilder CreateHostBuilder(string[] args) =>
            Host.CreateDefaultBuilder(args)
            .ConfigureWebHostDefaults(webBuilder =>
            {
                webBuilder.UseStartup<Startup>();
            });
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\xIds\Startup.cs

using System;
using System.IO;
using System.Reflection;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
using Newtonsoft.Json;
using xCommons.Configurations;
using xCommons.Extensions;
using xStorageService.DI;
using xIds.Constants;
using xIds.DI;
using xIds.Interfaces;
using xIds.Providers;

namespace xIds
{
    public class Startup
    {
        public IConfiguration Configuration { get; }

        public Startup(IConfiguration configuration)
        {
            Configuration = configuration;
        }

        public void ConfigureServices(IServiceCollection services)
        {
            //
            // Register Validation Provider and all XCommons Module Services ...
            services.AddXCommons();

            //
            // Register App Configuration ...
            services.AddXAppConfiguration(Configuration);
            var appConfiguration = services.GetRegisteredService<XAppConfiguration>();

            //
            // Register XDataService Configuration ...
            services.AddXDataServiceConfiguration(Configuration, ConnectionStringNames.IDENTITY_CONNECTION_NAME);

            //
            // Register Allowed Origins ...
            services.AddXCors(appConfiguration.AllowedOrigins);

            //
            // Register Swagger ...
            var xmlFile = $"{Assembly.GetExecutingAssembly().GetName().Name}.xml";
            var xmlPath = Path.Combine(AppContext.BaseDirectory, xmlFile);
            services.AddXSwagger(Configuration, xmlFilePath: xmlPath);

            //
            // Register IdentityServer to DI ...
            // services.AddInMemoryXIdentityServer (Configuration);
            services.AddEfSupportXIdentityServer(Configuration);

            //
            services.AddControllers()
                .AddNewtonsoftJson(x => x.SerializerSettings.ReferenceLoopHandling = ReferenceLoopHandling.Ignore);

            //
            // Register Authentication ...
            services.AddXIdentityServerAuthentication(Configuration);

            //
            // Register Authorization ...
            services.AddXAuthorization();

            //
            // Register Security Provider ...
            services.AddSingleton<IXSecurityProvider, XSecurityProvider>();
        }

        public void Configure(IApplicationBuilder app, IWebHostEnvironment env, ILogger<Startup> logger)
        {
            //
            if (env.IsDevelopment())
            {
                //
                app.UseDeveloperExceptionPage();

                //
                // app.UseXRequestLogger();
            }

            //
            // Use Swagger Middleware ...
            app.UseXSwagger();

            //
            app.UseHttpsRedirection();
            app.UseXForwardOptions();

            //
            // Using Cors ...
            app.UseXCors();

            //
            // Force App to Use IdentityServer ...
            app.UseXIdentityServer(logger);

            //
            // Force app to Use Storage Service ...
            app.UseXStorageService();

            //
            app.UseRouting();

            //
            app.UseAuthentication();
            app.UseAuthorization();

            //
            app.UseEndpoints(endpoints =>
            {
                endpoints.MapDefaultControllerRoute();
            });
        }
    }
}
