From f929414b9f287a086918303c21127a2196fd6bfc Mon Sep 17 00:00:00 2001 From: Hadi Khazaee Asl Date: Fri, 15 May 2026 19:41:43 +0330 Subject: [PATCH] add some new features in data service ... --- Base/XBaseDtoHub.cs | 215 +++++++++++++ Base/XBaseDtoProvider.cs | 423 ++++++++++++++++++++++++++ Base/XBaseEntityHub.cs | 77 +++-- Base/XBaseEntityProvider.cs | 422 +++++++++++++++++++++++++ Base/XBaseHub.cs | 14 +- {Providers => Base}/XBaseProvider.cs | 3 +- Base/XBaseWebRTCHub.cs | 52 +++- Interfaces/IXBaseDtoHub.cs | 89 ++++++ Interfaces/IXBaseDtoProvider.cs | 205 +++++++++++++ Interfaces/IXBaseEntityHub.cs | 88 ++++++ Interfaces/IXBaseEntityProvider.cs | 210 +++++++++++++ Interfaces/IXBaseHub.cs | 11 +- Interfaces/IXBaseProvider.cs | 7 + Interfaces/IXBaseWebRTCHub.cs | 42 ++- {Base => Models}/XHubConnectionDto.cs | 2 +- 15 files changed, 1826 insertions(+), 34 deletions(-) create mode 100644 Base/XBaseDtoHub.cs create mode 100644 Base/XBaseDtoProvider.cs create mode 100644 Base/XBaseEntityProvider.cs rename {Providers => Base}/XBaseProvider.cs (99%) create mode 100644 Interfaces/IXBaseDtoHub.cs create mode 100644 Interfaces/IXBaseDtoProvider.cs create mode 100644 Interfaces/IXBaseEntityHub.cs create mode 100644 Interfaces/IXBaseEntityProvider.cs rename {Base => Models}/XHubConnectionDto.cs (87%) diff --git a/Base/XBaseDtoHub.cs b/Base/XBaseDtoHub.cs new file mode 100644 index 0000000..2c43ab9 --- /dev/null +++ b/Base/XBaseDtoHub.cs @@ -0,0 +1,215 @@ +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 : XBaseHub, IXBaseDtoHub + where TEntity : XBaseEntity + where TDto : XBaseEntityDto + { + // + #region Constructor ... + protected XBaseDtoHub(ILogger logger) : base(logger) + { } + #endregion + + // + #region Actions ... + /// + /// Notify a New Item added ... + /// + /// + /// + /// + 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 + ); + } + } + + /// + /// Notify a New Item added ... + /// + /// + /// + /// + 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 + ); + } + } + + /// + /// Notify Add Many Items ... + /// + /// + /// + /// + public async Task AddMany( + IEnumerable 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 + ); + } + } + + /// + /// Notify an Item Deleted ... + /// + /// + /// + /// + 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 + ); + } + } + + /// + /// Notify Delete Many Items ... + /// + /// + /// + /// + public async Task DeleteMany( + IEnumerable 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 + ); + } + } + + /// + /// Notify an Item Updated ... + /// + /// + /// + /// + 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 + ); + } + } + + /// + /// Notify Update Many Items ... + /// + /// + /// + /// + public async Task UpdateMany( + IEnumerable 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 + } +} \ No newline at end of file diff --git a/Base/XBaseDtoProvider.cs b/Base/XBaseDtoProvider.cs new file mode 100644 index 0000000..61175ae --- /dev/null +++ b/Base/XBaseDtoProvider.cs @@ -0,0 +1,423 @@ +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 XBaseDtoProvider : IXBaseDtoProvider + where TEntity : XBaseEntity + where TDto : XBaseEntityDto + { + // + #region Properties ... + public IXIdentityProvider IdentityProvider { get; } + public XDataServiceConfiguration DataConfiguration { get; } + public IHubContext> Hub { get; } + public IXBaseRepositoryService Service { get; } + #endregion + + // + #region Constructor ... + protected XBaseDtoProvider( + IXIdentityProvider identityProvider, + XDataServiceConfiguration dataConfiguration, + IHubContext> hub, + IXBaseRepositoryService service + ) + { + // + Hub = hub; + Service = service; + IdentityProvider = identityProvider; + DataConfiguration = dataConfiguration; + } + #endregion + + // + #region Actions ... + /// + /// add a new Item ... + /// + /// + /// + /// + /// + /// + public virtual async Task 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; + } + + /// + /// Update an Item values ... + /// + /// + /// + /// + /// + /// + /// + public virtual async Task 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; + } + + /// + /// remove an Item by it's Id ... + /// + /// + /// + /// + /// + /// + /// + public virtual async Task 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; + } + + /// + /// count all exists Items ... + /// + /// + /// + /// + public virtual async Task CountAsync( + bool ignoreSoftDeleteds = true, + CancellationToken cancellationToken = default + ) + { + // + var result = await Service.CountAsync( + cancellationToken: cancellationToken, + ignoreSoftDeleteds: ignoreSoftDeleteds + ); + + // + return result; + } + + /// + /// Check an Item exists or not ... + /// + /// + /// + /// + /// + public virtual async Task IsExistsAsync( + TKey id, + bool ignoreSoftDeleteds = true, + CancellationToken cancellationToken = default + ) + { + // + var result = await Service.IsExistsAsync( + id: id, + cancellationToken: cancellationToken, + ignoreSoftDeleteds: ignoreSoftDeleteds + ); + + // + return result; + } + + /// + /// retrieve an Item by it's Id ... + /// + /// + /// + /// + /// + /// + public virtual async Task GetAsync( + TKey id, + bool ignoreSoftDeleteds = true, + Func, IIncludableQueryable> includeBuilder = null, + CancellationToken cancellationToken = default + ) + { + // + var result = await Service.GetAsync( + id: id, + includeBuilder: includeBuilder, + cancellationToken: cancellationToken, + ignoreSoftDeleteds: ignoreSoftDeleteds + ); + + // + return result; + } + + /// + /// retrieve all exists Items ... + /// + /// + /// + /// + /// + /// + public virtual async Task> GetAllAsync( + bool ignoreSoftDeleteds = true, + Func, IOrderedQueryable> orderBuilder = null, + Func, IIncludableQueryable> includeBuilder = null, + CancellationToken cancellationToken = default + ) + { + // + var result = await Service.GetAllAsync( + orderBuilder: orderBuilder, + includeBuilder: includeBuilder, + cancellationToken: cancellationToken, + ignoreSoftDeleteds: ignoreSoftDeleteds + ); + + // + return result; + } + + /// + /// find an Item by providing a Conditional Expression ... + /// + /// + /// + /// + /// + /// + public virtual async Task FindOneAsync( + Expression> predicate, + bool ignoreSoftDeleteds = true, + Func, IIncludableQueryable> includeBuilder = null, + CancellationToken cancellationToken = default + ) + { + // + var result = await Service.FindOneAsync( + predicate: predicate, + includeBuilder: includeBuilder, + cancellationToken: cancellationToken, + ignoreSoftDeleteds: ignoreSoftDeleteds + ); + + // + return result; + } + + /// + /// find a collection of Items by proving a Conditional Expression ... + /// + /// + /// + /// + /// + /// + /// + public virtual async Task> FindManyAsync( + Expression> predicate, + bool ignoreSoftDeleteds = true, + Func, IOrderedQueryable> orderBuilder = null, + Func, IIncludableQueryable> includeBuilder = null, + CancellationToken cancellationToken = default + ) + { + // + var result = await Service.FindManyAsync( + predicate: predicate, + orderBuilder: orderBuilder, + includeBuilder: includeBuilder, + cancellationToken: cancellationToken, + ignoreSoftDeleteds: ignoreSoftDeleteds + ); + + // + return result; + } + + /// + /// retrieve Items based on XQuery Pagination structure ... + /// + /// + /// + /// + /// + /// + /// + /// + public virtual async Task> QueryAsync( + XQuery query, + bool ignoreSoftDeleteds = true, + Expression> predicate = null, + Func, IOrderedQueryable> orderBuilder = null, + Func, IIncludableQueryable> 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 ... + /// + /// Send Custom Push Message ... + /// + /// + /// + /// + /// + /// + public async Task SendPush( + string action, + string payLoad, + string connectionId = null, + CancellationToken cancellationToken = default + ) + { + // + var actions = new List + { + 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 + } +} \ No newline at end of file diff --git a/Base/XBaseEntityHub.cs b/Base/XBaseEntityHub.cs index 8376429..dec1fec 100644 --- a/Base/XBaseEntityHub.cs +++ b/Base/XBaseEntityHub.cs @@ -1,14 +1,16 @@ 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 : XBaseHub + public abstract class XBaseEntityHub : XBaseHub, IXBaseEntityHub where TEntity : XBaseEntity { // @@ -23,8 +25,12 @@ namespace xPushService.Base /// Notify a New Entity added ... /// /// + /// /// - public async Task Add(TEntity entity) + public async Task Add( + TEntity entity, + CancellationToken cancellationToken = default + ) { // var connectionId = Context.ConnectionId; @@ -36,7 +42,8 @@ namespace xPushService.Base .SendAsync( XBaseEntityHubAction.Add.GetStringValue(), entity.ToJSON(camelCase: true), - connectionId + connectionId, + cancellationToken ); } } @@ -45,8 +52,12 @@ namespace xPushService.Base /// Notify a New Entity added ... /// /// + /// /// - public async Task AddOrUpdate(TEntity entity) + public async Task AddOrUpdate( + TEntity entity, + CancellationToken cancellationToken = default + ) { // var connectionId = Context.ConnectionId; @@ -58,7 +69,8 @@ namespace xPushService.Base .SendAsync( XBaseEntityHubAction.AddOrUpdate.GetStringValue(), entity.ToJSON(camelCase: true), - connectionId + connectionId, + cancellationToken ); } } @@ -66,9 +78,13 @@ namespace xPushService.Base /// /// Notify Add Many Entities ... /// - /// + /// + /// /// - public async Task AddMany(IEnumerable entities) + public async Task AddMany( + IEnumerable entities, + CancellationToken cancellationToken = default + ) { // var connectionId = Context.ConnectionId; @@ -80,7 +96,8 @@ namespace xPushService.Base .SendAsync( XBaseEntityHubAction.AddOrUpdate.GetStringValue(), entities.ToJSON(camelCase: true), - connectionId + connectionId, + cancellationToken ); } } @@ -89,8 +106,12 @@ namespace xPushService.Base /// Notify an Entity Deleted ... /// /// + /// /// - public async Task Delete(TEntity entity) + public async Task Delete( + TEntity entity, + CancellationToken cancellationToken = default + ) { // var connectionId = Context.ConnectionId; @@ -102,7 +123,8 @@ namespace xPushService.Base .SendAsync( XBaseEntityHubAction.Delete.GetStringValue(), entity.ToJSON(camelCase: true), - connectionId + connectionId, + cancellationToken ); } } @@ -110,9 +132,13 @@ namespace xPushService.Base /// /// Notify Delete Many Entities ... /// - /// + /// + /// /// - public async Task DeleteMany(IEnumerable entities) + public async Task DeleteMany( + IEnumerable entities, + CancellationToken cancellationToken = default + ) { // var connectionId = Context.ConnectionId; @@ -124,7 +150,8 @@ namespace xPushService.Base .SendAsync( XBaseEntityHubAction.DeleteMany.GetStringValue(), entities.ToJSON(camelCase: true), - connectionId + connectionId, + cancellationToken ); } } @@ -133,8 +160,12 @@ namespace xPushService.Base /// Notify an Entity Updated ... /// /// + /// /// - public async Task Update(TEntity entity) + public async Task Update( + TEntity entity, + CancellationToken cancellationToken = default + ) { // var connectionId = Context.ConnectionId; @@ -146,7 +177,8 @@ namespace xPushService.Base .SendAsync( XBaseEntityHubAction.Update.GetStringValue(), entity.ToJSON(camelCase: true), - connectionId + connectionId, + cancellationToken ); } } @@ -154,9 +186,13 @@ namespace xPushService.Base /// /// Notify Update Many Entities ... /// - /// + /// + /// /// - public async Task UpdateMany(IEnumerable entities) + public async Task UpdateMany( + IEnumerable entities, + CancellationToken cancellationToken = default + ) { // var connectionId = Context.ConnectionId; @@ -166,9 +202,10 @@ namespace xPushService.Base await Clients .AllExcept(connectionId) .SendAsync( - XBaseEntityHubAction.UpdateMany.GetStringValue(), - entities.ToJSON(camelCase: true), - connectionId + XBaseEntityHubAction.UpdateMany.GetStringValue(), + entities.ToJSON(camelCase: true), + connectionId, + cancellationToken ); } } diff --git a/Base/XBaseEntityProvider.cs b/Base/XBaseEntityProvider.cs new file mode 100644 index 0000000..78f80f1 --- /dev/null +++ b/Base/XBaseEntityProvider.cs @@ -0,0 +1,422 @@ +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 : IXBaseEntityProviderr + where TEntity : XBaseEntity + { + // + #region Properties ... + public IXIdentityProvider IdentityProvider { get; } + public IXBaseRepository Repository { get; } + public XDataServiceConfiguration DataConfiguration { get; } + public IHubContext> Hub { get; } + #endregion + + // + #region Constructor ... + protected XBaseEntityProvider( + IXIdentityProvider identityProvider, + IXBaseRepository repository, + XDataServiceConfiguration dataConfiguration, + IHubContext> hub + ) + { + // + Hub = hub; + Repository = repository; + IdentityProvider = identityProvider; + DataConfiguration = dataConfiguration; + } + #endregion + + // + #region Actions ... + /// + /// add a new Item ... + /// + /// + /// + /// + /// + /// + public virtual async Task 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; + } + + /// + /// Update an Item values ... + /// + /// + /// + /// + /// + /// + /// + public virtual async Task 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; + } + + /// + /// remove an Item by it's Id ... + /// + /// + /// + /// + /// + /// + /// + public virtual async Task 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; + } + + /// + /// count all exists Items ... + /// + /// + /// + /// + public virtual async Task CountAsync( + bool ignoreSoftDeleteds = true, + CancellationToken cancellationToken = default + ) + { + // + var result = await Repository.CountAsync( + cancellationToken: cancellationToken, + ignoreSoftDeleteds: ignoreSoftDeleteds + ); + + // + return result; + } + + /// + /// Check an Item exists or not ... + /// + /// + /// + /// + /// + public virtual async Task IsExistsAsync( + TKey id, + bool ignoreSoftDeleteds = true, + CancellationToken cancellationToken = default + ) + { + // + var result = await Repository.IsExistsAsync( + id: id, + cancellationToken: cancellationToken, + ignoreSoftDeleteds: ignoreSoftDeleteds + ); + + // + return result; + } + + /// + /// retrieve an Item by it's Id ... + /// + /// + /// + /// + /// + /// + public virtual async Task GetAsync( + TKey id, + bool ignoreSoftDeleteds = true, + Func, IIncludableQueryable> includeBuilder = null, + CancellationToken cancellationToken = default + ) + { + // + var result = await Repository.GetAsync( + id: id, + includeBuilder: includeBuilder, + cancellationToken: cancellationToken, + ignoreSoftDeleteds: ignoreSoftDeleteds + ); + + // + return result; + } + + /// + /// retrieve all exists Items ... + /// + /// + /// + /// + /// + /// + public virtual async Task> GetAllAsync( + bool ignoreSoftDeleteds = true, + Func, IOrderedQueryable> orderBuilder = null, + Func, IIncludableQueryable> includeBuilder = null, + CancellationToken cancellationToken = default + ) + { + // + var result = await Repository.GetAllAsync( + orderBuilder: orderBuilder, + includeBuilder: includeBuilder, + cancellationToken: cancellationToken, + ignoreSoftDeleteds: ignoreSoftDeleteds + ); + + // + return result; + } + + /// + /// find an Item by providing a Conditional Expression ... + /// + /// + /// + /// + /// + /// + public virtual async Task FindOneAsync( + Expression> predicate, + bool ignoreSoftDeleteds = true, + Func, IIncludableQueryable> includeBuilder = null, + CancellationToken cancellationToken = default + ) + { + // + var result = await Repository.FindOneAsync( + predicate: predicate, + includeBuilder: includeBuilder, + cancellationToken: cancellationToken, + ignoreSoftDeleteds: ignoreSoftDeleteds + ); + + // + return result; + } + + /// + /// find a collection of Items by proving a Conditional Expression ... + /// + /// + /// + /// + /// + /// + /// + public virtual async Task> FindManyAsync( + Expression> predicate, + bool ignoreSoftDeleteds = true, + Func, IOrderedQueryable> orderBuilder = null, + Func, IIncludableQueryable> includeBuilder = null, + CancellationToken cancellationToken = default + ) + { + // + var result = await Repository.FindManyAsync( + predicate: predicate, + orderBuilder: orderBuilder, + includeBuilder: includeBuilder, + cancellationToken: cancellationToken, + ignoreSoftDeleteds: ignoreSoftDeleteds + ); + + // + return result; + } + + /// + /// retrieve Items based on XQuery Pagination structure ... + /// + /// + /// + /// + /// + /// + /// + /// + public virtual async Task> QueryAsync( + XQuery query, + bool ignoreSoftDeleteds = true, + Expression> predicate = null, + Func, IOrderedQueryable> orderBuilder = null, + Func, IIncludableQueryable> 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 ... + /// + /// Send Custom Push Message ... + /// + /// + /// + /// + /// + /// + public async Task SendPush( + string action, + string payLoad, + string connectionId = null, + CancellationToken cancellationToken = default + ) + { + // + var actions = new List + { + 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 + } +} \ No newline at end of file diff --git a/Base/XBaseHub.cs b/Base/XBaseHub.cs index 13fbf37..6ce026d 100644 --- a/Base/XBaseHub.cs +++ b/Base/XBaseHub.cs @@ -1,4 +1,5 @@ using System; +using System.Threading; using System.Threading.Tasks; using Microsoft.AspNetCore.SignalR; using Microsoft.Extensions.Logging; @@ -58,11 +59,20 @@ namespace xPushService.Base // #region Actions ... - public async Task SendCustomAction(string actionName, string payLoad) + public async Task SendCustomAction( + string actionName, + string payLoad, + CancellationToken cancellationToken = default + ) { // var connectionId = Context.ConnectionId; - await Clients.AllExcept(connectionId).SendAsync(actionName, payLoad, connectionId); + await Clients.AllExcept(connectionId).SendAsync( + actionName, + payLoad, + connectionId, + cancellationToken + ); } #endregion } diff --git a/Providers/XBaseProvider.cs b/Base/XBaseProvider.cs similarity index 99% rename from Providers/XBaseProvider.cs rename to Base/XBaseProvider.cs index 2b6973d..ab2cbae 100644 --- a/Providers/XBaseProvider.cs +++ b/Base/XBaseProvider.cs @@ -12,11 +12,10 @@ using xDataService.Interfaces; using xIdentityService.Interfaces; using xModels.Base; using xModels.Dtos; -using xPushService.Base; using xPushService.Constants; using xPushService.Interfaces; -namespace xPushService.Providers +namespace xPushService.Base { public abstract class XBaseProvider : IXBaseProvider where TEntity : XBaseEntity diff --git a/Base/XBaseWebRTCHub.cs b/Base/XBaseWebRTCHub.cs index c0e432f..0ce8900 100644 --- a/Base/XBaseWebRTCHub.cs +++ b/Base/XBaseWebRTCHub.cs @@ -4,6 +4,7 @@ using xPushService.Interfaces; using Microsoft.AspNetCore.SignalR; using xPushService.Constants; using xCommons.Extensions; +using System.Threading; namespace xPushService.Base { @@ -28,20 +29,40 @@ namespace xPushService.Base /// /// /// + /// /// - public async Task Offer(string offer, string to) + public async Task Offer( + string offer, + string to, + CancellationToken cancellationToken = default + ) { - await Clients.Client(to).SendAsync(XWebRTCAction.Offer.GetStringValue(), offer); + // + await Clients.Client(to).SendAsync( + XWebRTCAction.Offer.GetStringValue(), + offer, + cancellationToken + ); } /// /// Sending WebRTC Answer to Specified Connection ... /// /// + /// /// - public async Task Answer(string answer) + public async Task Answer( + string answer, + CancellationToken cancellationToken = default + ) { - await Clients.All.SendAsync(XWebRTCAction.Answer.GetStringValue(), answer, Context.ConnectionId); + // + await Clients.All.SendAsync( + XWebRTCAction.Answer.GetStringValue(), + answer, + Context.ConnectionId, + cancellationToken + ); } /// @@ -49,18 +70,35 @@ namespace xPushService.Base /// /// /// + /// /// - public async Task Candidate(string candidate, string to) + 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); + // + await Clients.Client(to).SendAsync( + actionName, + candidate, + Context.ConnectionId, + cancellationToken + ); } else { - await Clients.All.SendAsync(actionName, candidate, Context.ConnectionId); + // + await Clients.All.SendAsync( + actionName, + candidate, + Context.ConnectionId, + cancellationToken + ); } } #endregion diff --git a/Interfaces/IXBaseDtoHub.cs b/Interfaces/IXBaseDtoHub.cs new file mode 100644 index 0000000..1a34420 --- /dev/null +++ b/Interfaces/IXBaseDtoHub.cs @@ -0,0 +1,89 @@ +using System.Collections.Generic; +using System.Threading; +using System.Threading.Tasks; +using xModels.Base; + +namespace xPushService.Interfaces +{ + public interface IXBaseDtoHub + where TEntity : XBaseEntity + where TDto : XBaseEntityDto + { + /// + /// Notify a New Item added ... + /// + /// + /// + /// + Task Add( + TDto item, + CancellationToken cancellationToken = default + ); + + /// + /// Notify a New Item added ... + /// + /// + /// + /// + Task AddOrUpdate( + TDto item, + CancellationToken cancellationToken = default + ); + + /// + /// Notify Add Many Items ... + /// + /// + /// + /// + Task AddMany( + IEnumerable items, + CancellationToken cancellationToken = default + ); + + /// + /// Notify an Item Deleted ... + /// + /// + /// + /// + Task Delete( + TDto item, + CancellationToken cancellationToken = default + ); + + /// + /// Notify Delete Many Items ... + /// + /// + /// + /// + Task DeleteMany( + IEnumerable items, + CancellationToken cancellationToken = default + ); + + /// + /// Notify an Item Updated ... + /// + /// + /// + /// + Task Update( + TDto item, + CancellationToken cancellationToken = default + ); + + /// + /// Notify Update Many Items ... + /// + /// + /// + /// + Task UpdateMany( + IEnumerable items, + CancellationToken cancellationToken = default + ); + } +} \ No newline at end of file diff --git a/Interfaces/IXBaseDtoProvider.cs b/Interfaces/IXBaseDtoProvider.cs new file mode 100644 index 0000000..51fff89 --- /dev/null +++ b/Interfaces/IXBaseDtoProvider.cs @@ -0,0 +1,205 @@ +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 + where TEntity : XBaseEntity + where TDto : XBaseEntityDto + { + // + #region Props ... + IXIdentityProvider IdentityProvider { get; } + XDataServiceConfiguration DataConfiguration { get; } + IHubContext> Hub { get; } + IXBaseRepositoryService Service { get; } + #endregion + + // + #region Actions ... + /// + /// add a new Item ... + /// + /// + /// + /// + /// + /// + Task AddAsync( + TDto item, + bool saveChanges = true, + string connectionId = null, + CancellationToken cancellationToken = default + ); + + /// + /// Update an Item values ... + /// + /// + /// + /// + /// + /// + /// + Task UpdateAsync( + TKey id, + TDto item, + bool saveChanges = true, + string connectionId = null, + CancellationToken cancellationToken = default + ); + + /// + /// remove an Item by it's Id ... + /// + /// + /// + /// + /// + /// + /// + Task RemoveAsync( + TKey id, + bool softDelete = true, + bool saveChanges = true, + string connectionId = null, + CancellationToken cancellationToken = default + ); + + /// + /// count all exists Items ... + /// + /// + /// + /// + Task CountAsync( + bool ignoreSoftDeleteds = true, + CancellationToken cancellationToken = default + ); + + /// + /// Check an Item exists or not ... + /// + /// + /// + /// + /// + Task IsExistsAsync( + TKey id, + bool ignoreSoftDeleteds = true, + CancellationToken cancellationToken = default + ); + + /// + /// retrieve an Item by it's Id ... + /// + /// + /// + /// + /// + /// + Task GetAsync( + TKey id, + bool ignoreSoftDeleteds = true, + Func, IIncludableQueryable> includeBuilder = null, + CancellationToken cancellationToken = default + ); + + /// + /// retrieve all exists Items ... + /// + /// + /// + /// + /// + /// + Task> GetAllAsync( + bool ignoreSoftDeleteds = true, + Func, IOrderedQueryable> orderBuilder = null, + Func, IIncludableQueryable> includeBuilder = null, + CancellationToken cancellationToken = default + ); + + /// + /// find an Item by providing a Conditional Expression ... + /// + /// + /// + /// + /// + /// + Task FindOneAsync( + Expression> predicate, + bool ignoreSoftDeleteds = true, + Func, IIncludableQueryable> includeBuilder = null, + CancellationToken cancellationToken = default + ); + + /// + /// find a collection of Items by proving a Conditional Expression ... + /// + /// + /// + /// + /// + /// + /// + Task> FindManyAsync( + Expression> predicate, + bool ignoreSoftDeleteds = true, + Func, IOrderedQueryable> orderBuilder = null, + Func, IIncludableQueryable> includeBuilder = null, + CancellationToken cancellationToken = default + ); + + /// + /// retrieve Items based on XQuery Pagination structure ... + /// + /// + /// + /// + /// + /// + /// + /// + Task> QueryAsync( + XQuery query, + bool ignoreSoftDeleteds = true, + Expression> predicate = null, + Func, IOrderedQueryable> orderBuilder = null, + Func, IIncludableQueryable> includeBuilder = null, + CancellationToken cancellationToken = default + ); + #endregion + + // + #region Hub Actions ... + /// + /// Send Custom Push Message ... + /// + /// + /// + /// + /// + /// + Task SendPush( + string action, + string payLoad, + string connectionId = null, + CancellationToken cancellationToken = default + ); + #endregion + } +} \ No newline at end of file diff --git a/Interfaces/IXBaseEntityHub.cs b/Interfaces/IXBaseEntityHub.cs new file mode 100644 index 0000000..5abc701 --- /dev/null +++ b/Interfaces/IXBaseEntityHub.cs @@ -0,0 +1,88 @@ +using System.Collections.Generic; +using System.Threading; +using System.Threading.Tasks; +using xModels.Base; + +namespace xPushService.Interfaces +{ + public interface IXBaseEntityHub + where TEntity : XBaseEntity + { + /// + /// Notify a New Entity added ... + /// + /// + /// + /// + Task Add( + TEntity entity, + CancellationToken cancellationToken = default + ); + + /// + /// Notify a New Entity added ... + /// + /// + /// + /// + Task AddOrUpdate( + TEntity entity, + CancellationToken cancellationToken = default + ); + + /// + /// Notify Add Many Entities ... + /// + /// + /// + /// + Task AddMany( + IEnumerable entities, + CancellationToken cancellationToken = default + ); + + /// + /// Notify an Entity Deleted ... + /// + /// + /// + /// + Task Delete( + TEntity entity, + CancellationToken cancellationToken = default + ); + + /// + /// Notify Delete Many Entities ... + /// + /// + /// + /// + Task DeleteMany( + IEnumerable entities, + CancellationToken cancellationToken = default + ); + + /// + /// Notify an Entity Updated ... + /// + /// + /// + /// + Task Update( + TEntity entity, + CancellationToken cancellationToken = default + ); + + /// + /// Notify Update Many Entities ... + /// + /// + /// + /// + Task UpdateMany( + IEnumerable entities, + CancellationToken cancellationToken = default + ); + } +} \ No newline at end of file diff --git a/Interfaces/IXBaseEntityProvider.cs b/Interfaces/IXBaseEntityProvider.cs new file mode 100644 index 0000000..f538fe6 --- /dev/null +++ b/Interfaces/IXBaseEntityProvider.cs @@ -0,0 +1,210 @@ +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 +{ + /// + /// a Provider is a way to Manipulate Data using Repository or Services and Contains Push + /// notifications ability ... + /// + /// + /// + public interface IXBaseEntityProviderr + where TEntity : XBaseEntity + { + // + #region Props ... + IXIdentityProvider IdentityProvider { get; } + IXBaseRepository Repository { get; } + XDataServiceConfiguration DataConfiguration { get; } + IHubContext> Hub { get; } + #endregion + + // + #region Actions ... + /// + /// add a new Item ... + /// + /// + /// + /// + /// + /// + Task AddAsync( + TEntity item, + bool saveChanges = true, + string connectionId = null, + CancellationToken cancellationToken = default + ); + + /// + /// Update an Item values ... + /// + /// + /// + /// + /// + /// + /// + Task UpdateAsync( + TKey id, + TEntity item, + bool saveChanges = true, + string connectionId = null, + CancellationToken cancellationToken = default + ); + + /// + /// remove an Item by it's Id ... + /// + /// + /// + /// + /// + /// + /// + Task RemoveAsync( + TKey id, + bool softDelete = true, + bool saveChanges = true, + string connectionId = null, + CancellationToken cancellationToken = default + ); + + /// + /// count all exists Items ... + /// + /// + /// + /// + Task CountAsync( + bool ignoreSoftDeleteds = true, + CancellationToken cancellationToken = default + ); + + /// + /// Check an Item exists or not ... + /// + /// + /// + /// + /// + Task IsExistsAsync( + TKey id, + bool ignoreSoftDeleteds = true, + CancellationToken cancellationToken = default + ); + + /// + /// retrieve an Item by it's Id ... + /// + /// + /// + /// + /// + /// + Task GetAsync( + TKey id, + bool ignoreSoftDeleteds = true, + Func, IIncludableQueryable> includeBuilder = null, + CancellationToken cancellationToken = default + ); + + /// + /// retrieve all exists Items ... + /// + /// + /// + /// + /// + /// + Task> GetAllAsync( + bool ignoreSoftDeleteds = true, + Func, IOrderedQueryable> orderBuilder = null, + Func, IIncludableQueryable> includeBuilder = null, + CancellationToken cancellationToken = default + ); + + /// + /// find an Item by providing a Conditional Expression ... + /// + /// + /// + /// + /// + /// + Task FindOneAsync( + Expression> predicate, + bool ignoreSoftDeleteds = true, + Func, IIncludableQueryable> includeBuilder = null, + CancellationToken cancellationToken = default + ); + + /// + /// find a collection of Items by proving a Conditional Expression ... + /// + /// + /// + /// + /// + /// + /// + Task> FindManyAsync( + Expression> predicate, + bool ignoreSoftDeleteds = true, + Func, IOrderedQueryable> orderBuilder = null, + Func, IIncludableQueryable> includeBuilder = null, + CancellationToken cancellationToken = default + ); + + /// + /// retrieve Items based on XQuery Pagination structure ... + /// + /// + /// + /// + /// + /// + /// + /// + Task> QueryAsync( + XQuery query, + bool ignoreSoftDeleteds = true, + Expression> predicate = null, + Func, IOrderedQueryable> orderBuilder = null, + Func, IIncludableQueryable> includeBuilder = null, + CancellationToken cancellationToken = default + ); + #endregion + + // + #region Hub Actions ... + /// + /// Send Custom Push Message ... + /// + /// + /// + /// + /// + /// + Task SendPush( + string action, + string payLoad, + string connectionId = null, + CancellationToken cancellationToken = default + ); + #endregion + } +} \ No newline at end of file diff --git a/Interfaces/IXBaseHub.cs b/Interfaces/IXBaseHub.cs index 5b467ab..093b4e8 100644 --- a/Interfaces/IXBaseHub.cs +++ b/Interfaces/IXBaseHub.cs @@ -1,5 +1,14 @@ +using System.Threading; +using System.Threading.Tasks; + namespace xPushService.Interfaces { public interface IXBaseHub - { } + { + Task SendCustomAction( + string actionName, + string payLoad, + CancellationToken cancellationToken = default + ); + } } \ No newline at end of file diff --git a/Interfaces/IXBaseProvider.cs b/Interfaces/IXBaseProvider.cs index af0d690..103b046 100644 --- a/Interfaces/IXBaseProvider.cs +++ b/Interfaces/IXBaseProvider.cs @@ -15,6 +15,13 @@ using xPushService.Base; namespace xPushService.Interfaces { + /// + /// a Provider is a way to Manipulate Data using Repository or Services and Contains Push + /// notifications ability ... + /// + /// + /// + /// public interface IXBaseProvider where TEntity : XBaseEntity where TDto : XBaseEntityDto diff --git a/Interfaces/IXBaseWebRTCHub.cs b/Interfaces/IXBaseWebRTCHub.cs index 8213a9e..4c655b3 100644 --- a/Interfaces/IXBaseWebRTCHub.cs +++ b/Interfaces/IXBaseWebRTCHub.cs @@ -1,5 +1,45 @@ +using System.Threading; +using System.Threading.Tasks; + namespace xPushService.Interfaces { public interface IXBaseWebRTCHub : IXBaseHub - {} + { + /// + /// Sending WebRTC Offer To Specified Connection ... + /// + /// + /// + /// + /// + Task Offer( + string offer, + string to, + CancellationToken cancellationToken = default + ); + + /// + /// Sending WebRTC Answer to Specified Connection ... + /// + /// + /// + /// + Task Answer( + string answer, + CancellationToken cancellationToken = default + ); + + /// + /// Sending WebRTC Candidate to Specified Connecton ... + /// + /// + /// + /// + /// + Task Candidate( + string candidate, + string to, + CancellationToken cancellationToken = default + ); + } } \ No newline at end of file diff --git a/Base/XHubConnectionDto.cs b/Models/XHubConnectionDto.cs similarity index 87% rename from Base/XHubConnectionDto.cs rename to Models/XHubConnectionDto.cs index 3812ee3..6b903fd 100644 --- a/Base/XHubConnectionDto.cs +++ b/Models/XHubConnectionDto.cs @@ -1,6 +1,6 @@ using xModels.Base; -namespace xPushService.Base +namespace xPushService.Models { public class XHubConnectionDto : XBaseDto {