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