diff --git a/DI/XDIHelperExtension.cs b/DI/XDIHelperExtension.cs index f3973c0..81789a9 100644 --- a/DI/XDIHelperExtension.cs +++ b/DI/XDIHelperExtension.cs @@ -65,7 +65,7 @@ namespace xPushService.DI public static void AddXPushService( this IServiceCollection services, IConfiguration config, - ServiceLifetime lifeTime = ServiceLifetime.Singleton + ServiceLifetime lifeTime = ServiceLifetime.Scoped ) { // @@ -84,7 +84,7 @@ namespace xPushService.DI public static void AddXPushService( this IServiceCollection services, XPushServiceConfiguration config, - ServiceLifetime lifeTime = ServiceLifetime.Singleton + ServiceLifetime lifeTime = ServiceLifetime.Scoped ) { // @@ -279,10 +279,6 @@ namespace xPushService.DI x.PayloadSerializerSettings.ContractResolver = new CamelCasePropertyNamesContractResolver(); }); - // - // Register HubContext Factory ... - services.AddSingleton(); - // // Register XPushServiceUserNameProvider ... services.AddSingleton(); diff --git a/README.md b/README.md index 92e01fd..679edf2 100644 --- a/README.md +++ b/README.md @@ -1,1115 +1,318 @@ # xPushService -it is a Part of xDashboard Projects on SaherElm IT Center which provides all required models and actions in related to handling SignalR Push Platforms. +it is a Part of xDashboard Projects on SaherElm IT Center which provides: -since this module used as a base infrastructure provider, you have to create a Helper Module based on it, for creating your projects requirements. we call it commonly **xPushHelper**. +- all requirements to Implement Realtime Communications in a **xDashboard** based Project. -## xPushHelper - -it is a simple **xDashboard** based module. which depends on these modules: +this module has following dependencies: +- xModels - xCommons -- xPushService +- xDataService +- xIdentityService -this is so important, if you protect your data using **xIdentityServer**. you need to add an additional refrence to your **xIdentityHelper** module. +all tools which provides realtime communications features in this module constructed based on SignalR library. -```c# - - - - - - - - - - +for configure and use this Module refer to DI.XDIHelperExtension.cs file. + +## Implementation + +### Hub + +it is a High Level Communication Endpoint which allow Bi-Directional Communications (Server => Client and Client => Server) using Realtime Connections. which introduced using **SignalR**. + +#### XBaseHub + +all Supported Hubs in **xDashboard** must inherit from this based abstract class, which provides base requirement which used in all Hubs. + +#### XBaseWebRTCHub + +a base abstract class which provides all requirements to establish WebRTC based Communications which called Signalling. + +if you want to Implement WebRTC based Hubs for Audio/Vide/... establish connections. you have to extens from this base abstraction class. + +#### XBaseEntityHub + +an abstract class which Provides all requirements to Implement Entity Manipulations Notifications in your Projects. + +```C# +public class XTestEntityHub : XBaseEntityHub, IXTestEntityHub +{ + public XTestEntityHub(ILogger logger) : base(logger) + { } +} ``` -after adding dependencies. you have to extends your PushHelper module. +#### XBaseDtoHub -by following **SignalR** rules, for each topics you have to add an specific **HUB** and register it in your **DI**. +an abstract class which Provides all requirements to Implement Dto Manipulations Notifications in your Projects. -since all important actions for handling communications between connected peers must be handled in Hubs. at the first step you have to create a Base Class for all of your Hubs. - -in this sample since we need to have Authorized HUB Actions, we add IdentityService as dependency to Helper Module, now next step is implement a BaseHub class which supports Authorized Actions based on our User Roles. - -## XPushBaseHub - -```c# - public abstract class XPushBaseHub : XBaseHub, IXAuthorizedPushActions, IXUserPushActions, IXGroupsPushActions { - // - #region Constructor ... - protected XPushBaseHub ( - IXPushGroupStore groupStore, - IXPushConnectionStore connectionStore - ) : base (groupStore, connectionStore) { } - #endregion - - // - #region Authorized Push Actions ... - /// - /// an authenticated user can push a message to others ... - /// - /// - /// - [Authorize (Policy = XPolicies.User)] - public Task UserMessageAsync (XPushMessage message) { - // - if (message.IsNull ()) { - message = GetPushMessage (); - } else { - message.TimeStamp = DateTime.UtcNow; - } - - // - return Clients.Others.SendAsync (XBasePushAction.UserMessage.GetStringValue (), message); - } - - /// - /// an admin user can push a message to others ... - /// - /// - /// - [Authorize (Policy = XPolicies.Admin)] - public Task AdminMessageAsync (XPushMessage message) { - // - if (message.IsNull ()) { - message = GetPushMessage (); - } else { - message.TimeStamp = DateTime.UtcNow; - } - - // - return Clients.Others.SendAsync (XBasePushAction.AdminMessage.GetStringValue (), message); - } - #endregion - - // - #region User Push Actions ... - [Authorize (Policy = XPolicies.Admin)] - [Authorize (Policy = XPolicies.EnabledAgent)] - public Task AddUserToGroup (string userName, string groupName) { - // - // Empty result ... - var result = Task.FromResult (false); - - // - var group = GetGroup (groupName) - .RunTask (); - - // - var connections = connectionStore - .GetByUserName (userName) - .RunTask (); - var mustAddConnections = connections - .Where (c => !group.Connections - .Any (gc => gc == c.Id)); - if (!mustAddConnections.HasChild ()) { - return result; - } - - // - // Add all new Connections to Group ... - var allUpdate = false; - mustAddConnections.ToList ().ForEach (c => { - // - try { - // - Groups - .AddToGroupAsync (c.Id, groupName) - .RunTask (); - - // - group.Connections.Add (c.Id); - - // - allUpdate = allUpdate || true; - } catch { - allUpdate = allUpdate || false; - } - }); - if (!allUpdate) { - return result; - } - - // - result = AddOrUpdateGroup (group); - - // - return result; - } - - [Authorize (Policy = XPolicies.Admin)] - [Authorize (Policy = XPolicies.EnabledAgent)] - public Task AddUserDeviceToGroup (string userName, string groupName, XDeviceDto device) { - // - // Temp result ... - var result = Task.FromResult (false); - - // - // Validate Args ... - if ( - device.IsNull () || - userName.IsNullOrEmpty () || - groupName.IsNullOrEmpty () - ) { - return result; - } - - // - // Find User Connection ... - var userConnection = connectionStore - .GetByUserDevice ( - device: device, - userName: userName - ) - .RunTask (); - if (userConnection.IsNull ()) { - return result; - } - - // - // Get Group ... - var group = GetGroup (groupName) - .RunTask (); - - // - // check if connection exists in group ... - if (group.Connections.Any (c => c == userConnection.Id)) { - return result; - } - - // - try { - // - Groups - .AddToGroupAsync ( - userConnection.Id, - groupName - ) - .RunTask (); - - // - group.Connections.Add (userConnection.Id); - } catch { - return result; - } - - // - result = AddOrUpdateGroup (group); - - // - return result; - } - - [Authorize (Policy = XPolicies.Admin)] - [Authorize (Policy = XPolicies.EnabledAgent)] - public Task RemoveUserFromGroup (string userName, string groupName) { - // - // Temp result ... - var result = Task.FromResult (false); - - // - // Validate Args ... - if ( - userName.IsNullOrEmpty () || - groupName.IsNullOrEmpty () - ) { - return result; - } - - // - // Check Group Exists or not ... - var isGroupExists = groupStore - .IsExistsByKey (groupName) - .RunTask (); - if (!isGroupExists) { - return result; - } - - // - // Retrieve User Connections ... - var userConnections = connectionStore - .GetByUserName (userName) - .RunTask (); - if (!userConnections.HasChild ()) { - return result; - } - - // - var group = GetGroup (groupName) - .RunTask (); - var mustRemoveConnections = userConnections - .Where (c => group.Connections - .Any (gcId => c.Id == gcId)); - if (!mustRemoveConnections.HasChild ()) { - return result; - } - - // - // try to remove connections from group ... - try { - // - mustRemoveConnections - .ToList () - .ForEach (c => { - // - var isRemoved = connectionStore - .RemoveByConnectionId (c.Id) - .RunTask (); - if (isRemoved) { - Groups.RemoveFromGroupAsync ( - c.Id, - groupName - ) - .RunTask (); - } - }); - - // - result = Task.FromResult (true); - } catch { } - - // - return result; - } - - [Authorize (Policy = XPolicies.Admin)] - [Authorize (Policy = XPolicies.EnabledAgent)] - public Task RemoveUserDeviceFromGroup (string userName, string groupName, XDeviceDto device) { - // - // Temp result ... - var result = Task.FromResult (false); - - // - // Validate Arg ... - if ( - device.IsNull () || - userName.IsNullOrEmpty () || - groupName.IsNullOrEmpty () - ) { - return result; - } - - // - // Check group exists ... - var isGroupExists = groupStore - .IsExistsByKey (groupName) - .RunTask (); - if (!isGroupExists) { - return result; - } - - // - var group = GetGroup (groupName) - .RunTask (); - if (!group.Connections.HasChild ()) { - return result; - } - - // - // retrieve user connection ... - var userDeviceConnection = connectionStore - .GetByUserDevice ( - device: device, - userName: userName - ) - .RunTask (); - if ( - userDeviceConnection.IsNull () || - !group.Connections.Any (gc => gc != userDeviceConnection.Id) - ) { - return result; - } - - // - try { - // - Groups.RemoveFromGroupAsync ( - groupName: groupName, - connectionId: userDeviceConnection.Id - ); - } catch { - return result; - } - group.Connections.Remove (userDeviceConnection.Id); - - // - result = AddOrUpdateGroup (group); - - // - return result; - } - - [Authorize (Policy = XPolicies.Admin)] - [Authorize (Policy = XPolicies.EnabledUser)] - [Authorize (Policy = XPolicies.EnabledAgent)] - public Task SendMessageToUser (string userName, XPushMessage message) { - // - // Temp result ... - var result = Task.FromResult (false); - - // - // Validate Args ... - if (userName.IsNullOrEmpty ()) { - return result; - } - - // - // Normalize Message ... - if (message.IsNull ()) { - message = GetPushMessage (); - } else { - message.TimeStamp = DateTime.UtcNow; - } - - // - // Check user exists ... - var userConnections = connectionStore - .GetByUserName (userName) - .RunTask (); - if (!userConnections.HasChild ()) { - return result; - } - - // - try { - // - Clients - .User (userName) - .SendAsync ( - XBasePushAction.PushMessage.GetStringValue (), - message - ) - .RunTask(); - - // - result = Task.FromResult (true); - } catch { } - - // - return result; - } - - [Authorize (Policy = XPolicies.Admin)] - [Authorize (Policy = XPolicies.EnabledUser)] - [Authorize (Policy = XPolicies.EnabledAgent)] - public Task SendMessageToUserDevice (string userName, XPushMessage message, XDeviceDto device) { - // - // Temp result ... - var result = Task.FromResult (false); - - // - // Validate Args ... - if ( - device.IsNull () || - userName.IsNullOrEmpty () - ) { - return result; - } - - // - // Normalize Message ... - if (message.IsNull ()) { - message = GetPushMessage (); - } else { - message.TimeStamp = DateTime.UtcNow; - } - - // - // Check user exists ... - var userDeviceConnection = connectionStore - .GetByUserDevice ( - device: device, - userName: userName - ) - .RunTask (); - if (userDeviceConnection.IsNull ()) { - return result; - } - - // - try { - // - Clients - .Client (userDeviceConnection.Id) - .SendAsync ( - XBasePushAction.PushMessage.GetStringValue (), - message - ) - .RunTask(); - - // - result = Task.FromResult (true); - } catch { } - - // - return result; - } - - [Authorize (Policy = XPolicies.Admin)] - [Authorize (Policy = XPolicies.EnabledUser)] - [Authorize (Policy = XPolicies.EnabledAgent)] - public Task SendMessageToUsers (IEnumerable userNames, XPushMessage message) { - // - // Temp result ... - var result = Task.FromResult (false); - - // - // Validate Args ... - if (!userNames.HasChild ()) { - return result; - } - - // - // Normalize Message ... - if (message.IsNull ()) { - message = GetPushMessage (); - } else { - message.TimeStamp = DateTime.UtcNow; - } - - // - // Check user exists ... - var usersConnections = connectionStore - .FindMany (c => userNames.Contains (c.User)) - .RunTask (); - if (!usersConnections.HasChild ()) { - return result; - } - - // - try { - // - Clients - .Users ( - userNames - .ToList () - .AsReadOnly () - ) - .SendAsync ( - XBasePushAction.PushMessage.GetStringValue (), - message - ) - .RunTask(); - - // - result = Task.FromResult (true); - } catch { } - - // - return result; - } - - [Authorize (Policy = XPolicies.Admin)] - [Authorize (Policy = XPolicies.EnabledUser)] - [Authorize (Policy = XPolicies.EnabledAgent)] - public Task> GetUserGroups (string userName) { - // - // Temp Result ... - var resultList = new List (); - - // - // Validate Args ... - if (userName.IsNullOrEmpty ()) { - return Task.FromResult ( - resultList - .AsEnumerable () - ); - } - - // - // Retrieve User Connections ... - var userConnections = connectionStore - .GetByUserName (userName) - .RunTask (); - if (!userConnections.HasChild ()) { - return Task.FromResult ( - resultList - .AsEnumerable () - ); - } - - // - // Retrieve user Groups ... - var userGroups = groupStore - .FindMany (pg => pg.Connections - .Any (pgCId => userConnections - .Any (uc => uc.Id == pgCId))) - .RunTask (); - if (!userGroups.HasChild ()) { - return Task.FromResult ( - resultList - .AsEnumerable () - ); - } - - // - // prepare result ... - resultList = userGroups - .Select (ug => ug.Id) - .ToList (); - return Task.FromResult ( - resultList - .AsEnumerable () - ); - } - - [Authorize (Policy = XPolicies.Admin)] - [Authorize (Policy = XPolicies.EnabledAgent)] - public Task> GetUserConnections (string userName) { - // - var resultList = new List (); - - // - // Validate Args ... - if (userName.IsNullOrEmpty ()) { - return Task.FromResult ( - resultList - .AsEnumerable () - ); - } - - // - // check current user is Admin or not ... - var connectedUser = GetUserName (); - var connectedUserRole = GetUserRole (); - var isAdminOrAgent = connectedUserRole.ToNormalString () == "admin" || - connectedUserRole.ToNormalString () == "agent"; - var isUserSame = connectedUser.ToNormalString () == userName.ToNormalString (); - - // - // check current user ... - if (!isAdminOrAgent && !isUserSame) { - return Task.FromResult ( - resultList - .AsEnumerable () - ); - } - - // - return connectionStore - .GetByUserName (userName); - } - #endregion - - // - #region Group Push Actions ... - [Authorize (Policy = XPolicies.Admin)] - [Authorize (Policy = XPolicies.EnabledAgent)] - public Task SendMessageToGroup (string groupName, XPushMessage message) { - // - // Empty result ... - var result = Task.FromResult (false); - - // - // Validate Args ... - if (groupName.IsNullOrEmpty ()) { - return result; - } - - // - // Normalize Message ... - if (message.IsNull ()) { - message = GetPushMessage (); - } else { - message.TimeStamp = DateTime.UtcNow; - } - - // - // Check Group Exists ... - var isGroupExists = groupStore - .IsExistsByKey (groupName) - .RunTask (); - if (!isGroupExists) { - return result; - } - - // - try { - // - Clients - .Group (groupName) - .SendAsync ( - XBasePushAction.PushMessage.GetStringValue (), - message - ) - .RunTask(); - - // - result = Task.FromResult (true); - } catch { } - - // - return result; - } - - [Authorize (Policy = XPolicies.Admin)] - [Authorize (Policy = XPolicies.EnabledAgent)] - public Task SendMessageToGroups (IEnumerable groupNames, XPushMessage message) { - // - // Empty result ... - var result = Task.FromResult (false); - - // - // Validate Args ... - if (!groupNames.HasChild ()) { - return result; - } - - // - // Normalize Message ... - if (message.IsNull ()) { - message = GetPushMessage (); - } else { - message.TimeStamp = DateTime.UtcNow; - } - - // - // Check Group Exists ... - var isGroupsExists = Task.WhenAll (groupNames - .Select (gName => groupStore - .IsExistsByKey (gName))) - .RunTask (); - if (!isGroupsExists.All (isExists => !!isExists)) { - return result; - } - - // - try { - // - Clients - .Groups ( - groupNames - .ToList () - .AsReadOnly () - ) - .SendAsync ( - XBasePushAction.PushMessage.GetStringValue (), - message - ) - .RunTask(); - - // - result = Task.FromResult (true); - } catch { } - - // - return result; - } - - [Authorize (Policy = XPolicies.Admin)] - [Authorize (Policy = XPolicies.EnabledAgent)] - public Task AddConnectionToGroup (string connectionId, string groupName) { - // - // Empty result ... - var result = Task.FromResult (false); - - // - // Validate Args ... - if ( - groupName.IsNullOrEmpty () || - connectionId.IsNullOrEmpty () - ) { - return result; - } - - // - // Check Connection Exists ... - var isConnectionExists = connectionStore - .IsExistsConnectionId (connectionId) - .RunTask (); - if (!isConnectionExists) { - return result; - } - - // - // Get Normalized Group ... - var group = GetGroup (groupName) - .RunTask (); - var isConnectionInGroup = group.Connections.Any (cId => cId == connectionId); - if (isConnectionInGroup) { - return result; - } - - // - // add connection to group ... - group.Connections.Add (connectionId); - - // - result = AddOrUpdateGroup (group); - - // - return result; - } - - [Authorize (Policy = XPolicies.Admin)] - [Authorize (Policy = XPolicies.EnabledAgent)] - public Task RemoveConnectionFromGroup (string connectionId, string groupName) { - // - // Empty result ... - var result = Task.FromResult (false); - - // - // Validate Args ... - if ( - groupName.IsNullOrEmpty () || - connectionId.IsNullOrEmpty () - ) { - return result; - } - - // - // Check Connection Exists ... - var isConnectionExists = connectionStore - .IsExistsConnectionId (connectionId) - .RunTask (); - if (!isConnectionExists) { - return result; - } - - // - // Check Group Exists ... - var isGroupExists = groupStore - .IsExistsByKey (groupName) - .RunTask (); - if (!isGroupExists) { - return result; - } - - // - // Get Normalized Group ... - var group = GetGroup (groupName) - .RunTask (); - var isConnectionInGroup = group.Connections.Any (cId => cId == connectionId); - if (!isConnectionInGroup) { - return result; - } - - // - // add connection to group ... - group.Connections.Remove (connectionId); - - // - result = AddOrUpdateGroup (group); - - // - return result; - } - - [Authorize (Policy = XPolicies.Admin)] - [Authorize (Policy = XPolicies.EnabledAgent)] - public Task> GetGroupNames () { - // - var groups = groupStore - .GetAll () - .RunTask (); - - // - var result = groups.Select (g => g.Id); - return Task.FromResult (result); - } - - [Authorize (Policy = XPolicies.Admin)] - [Authorize (Policy = XPolicies.EnabledAgent)] - public Task> GetGroups () { - return groupStore.GetAll (); - } - - [Authorize (Policy = XPolicies.Admin)] - [Authorize (Policy = XPolicies.EnabledAgent)] - public Task RemoveGroupConnections (string groupName) { - // - // Empty result ... - var result = Task.FromResult (false); - - // - // Validate Args ... - if (groupName.IsNullOrEmpty ()) { - return result; - } - - // - // retrieve normalized group ... - var group = GetGroup (groupName) - .RunTask (); - if (!group.Connections.HasChild ()) { - return result; - } - - // - var allResult = false; - group.Connections - .ToList () - .ForEach (cIde => { - // - var isRemoved = connectionStore - .RemoveByConnectionId (cIde) - .RunTask (); - - // - if (isRemoved) { - group.Connections.Remove (cIde); - } - - // - allResult = allResult || isRemoved; - }); - if (!allResult) { - return result; - } - - // - result = Task.FromResult (true); - return result; - } - - [Authorize (Policy = XPolicies.Admin)] - [Authorize (Policy = XPolicies.EnabledAgent)] - public Task> GetConnectionGroups (string connectionId) { - // - // Validate Args ... - if (connectionId.IsNullOrEmpty ()) { - return Task.FromResult ( - new List () - .AsEnumerable () - ); - } - - // - var connectionGroups = groupStore - .FindMany (group => group.Connections - .Contains (connectionId)) - .RunTask (); - - // - var resultList = connectionGroups - .Select (group => group.Id); - - // - return Task.FromResult (resultList); - } - - [Authorize (Policy = XPolicies.Admin)] - [Authorize (Policy = XPolicies.EnabledAgent)] - public Task> GetGroupConnections (string groupName) { - // - // Validate Args ... - if (groupName.IsNullOrEmpty ()) { - return Task.FromResult ( - new List () - .AsEnumerable () - ); - } - - // - var group = GetGroup (groupName) - .RunTask (); - - // - var resultList = connectionStore - .FindMany (c => group.Connections.Contains (c.Id)) - .RunTask (); - - // - return Task.FromResult (resultList); - } - #endregion - - // - #region Private ... - private Task GetGroup (string groupName) { - // - XPushGroupDto result = null; - // - // Validate Args ... - if (groupName.IsNullOrEmpty ()) { - return Task.FromResult (result); - } - - // - var isExistsGroup = groupStore - .IsExistsByKey (groupName) - .RunTask (); - - // - if (!isExistsGroup) { - result = new XPushGroupDto { - Id = groupName, - Connections = new List () - }; - } else { - result = groupStore - .Get (groupName) - .RunTask (); - } - - // - return Task.FromResult (result); - } - - private Task AddOrUpdateGroup (XPushGroupDto group) { - // - var result = false; - - // - // Validate Args ... - if (group.IsNull ()) { - return Task.FromResult (result); - } - - // - var isExistsGroup = groupStore - .IsExistsByKey (group.Id) - .RunTask (); - if (!isExistsGroup) { - result = groupStore - .Add (group) - .RunTask (); - } else { - // - var updatedGroup = groupStore - .Update (group) - .RunTask (); - result = !updatedGroup.IsNull (); - } - - // - return Task.FromResult (result); - } - #endregion - } +```C# +public class XTestDtoHub : XBaseDtoHub, IXTestDtoHub +{ + public XTestDtoHub(ILogger logger) : base(logger) + { } +} ``` -one of most important things which you had to do in **xPushHelper** is the implementation of your **HUB**(s). +### Provider -for this, you had to use **XBaseHub** class and extends your Hubs from it. here for example we create a ViewHub as follow: +a Provider is a Service which has access to Hub or Hubs for Realtime Communications in other words Push Notification Enabled Service. -## XViewHub +#### XBaseEntityProvider -```c# - public class XViewHub : XBaseHub { - // - #region Props ... - public static int Count = 0; - #endregion +an abstract class which has Repository based Data Manipulation Implemented actions, which used EntityHub for Notifying Entity Changes. - // - #region Constructor ... - public XViewHub ( - IXPushGroupStore groupStore, - IXPushConnectionStore connectionStore - ) : base (groupStore, connectionStore) { } - #endregion - - // - #region Actions ... - [Authorize] - public Task NotifyCount () { - return Clients.All.SendAsync ("NotifyCount", Count); - } - - public Task PublicNotifyCount () { - return Clients.All.SendAsync ("NotifyCount", Count); - } - - public int IncreaseCount () { - // - Count += 1; - return Count; - } - #endregion - } +```C# +public class XTestRepositoryProvider : XBaseEntityProvider, IXTestRepositoryProvider +{ + public XTestRepositoryProvider( + IXTestRepository repository, + IHubContext hub, + XDataServiceConfiguration dataConfiguration, + IXIdentityProvider identityProvider = null + ) : base( + hub: hub, + repository: repository, + identityProvider: identityProvider, + dataConfiguration: dataConfiguration + ) + { } +} ``` -## Handling WebRTC connections +#### XBaseDtoProvider -there is a Base Class **XBaseWebRTCHub** for enable WebRTC on your projects. all thing you had to do is to extends a class from it. +an abstract class which has Service based Data Manipulation Implemented actions, which used DtoHub for Notifying Dto Changes. -### XWebRTCHub - -as you can see below, there is not anything to add to this class, all things handled by Base Class by default. but if there is some custom actions you need, add them here ... - -```c# - public class XWebRTCHub : XBaseWebRTCHub { - // - #region Constructor ... - public XWebRTCHub ( - IXPushGroupStore groupStore, - IXPushConnectionStore connectionStore, - IXWebRTCConnectionStore webRTCConnectionStore - ) : base (groupStore, connectionStore, webRTCConnectionStore) { } - #endregion - } +```C# +public class XTestServiceProvider : XBaseDtoProvider, IXTestServiceProvider +{ + public XTestServiceProvider( + IHubContext hub, + IXTestRepositoryService service, + XDataServiceConfiguration dataConfiguration, + IXIdentityProvider identityProvider = null + ) : base( + hub: hub, + service: service, + identityProvider: identityProvider, + dataConfiguration: dataConfiguration + ) + { } +} ``` -after complete all requirements inside **xPushHelper** module, next step is to register **xPushService** in your application **DI**, which happens on **Startup.cs** file. +#### XBaseRepositoryProviderController -**NOTE:** if you want to use Authorization and Authentication inside your Hubs, you had to register xPushService after enabling Authorization. +an abstract Controller class which has Identity Enabled Services for Authorization and Authentication based Endpoint Providing and also has all default Entity based Provider Service Actions implementation for using in Projects. -before moving forward, please configure **xPushService** as follow, in your appSettings.json file: +```C# +public class XTestRepositoryProviderController : XBaseRepositoryProviderController, IXBaseRepositoryProviderController +{ + public XTestRepositoryProviderController( + ILogger logger, + XAppConfiguration appConfiguration, + IXIdentityProvider identityProvider, + XValidationProvider validationProvider, + IXTestRepositoryProvider provider, + Func, IOrderedQueryable> defaultOrderBuilder, + Func, IIncludableQueryable> defaultIncludeBuilder + ) : base( + logger, + appConfiguration, + identityProvider, + validationProvider, + provider, + defaultOrderBuilder, + defaultIncludeBuilder + ) + { } +} +``` + +#### XBaseServiceProviderController + +an abstract Controller class which has Identity Enabled Services for Authorization and Authentication based Endpoint Providing and also has all default Dto based Provider Service Actions implementation for using in Projects. + +```C# +public class XTestServiceProviderController : XBaseServiceProviderController, IXBaseServiceProviderController +{ + public XTestServiceProviderController( + ILogger logger, + XAppConfiguration appConfiguration, + IXIdentityProvider identityProvider, + XValidationProvider validationProvider, + IXTestServiceProvider provider, + Func, IOrderedQueryable> defaultOrderBuilder, + Func, IIncludableQueryable> defaultIncludeBuilder + ) : base( + logger, + appConfiguration, + identityProvider, + validationProvider, + provider, + defaultOrderBuilder, + defaultIncludeBuilder + ) + { } +} +``` + +### Register PushService + +after preparation of all requirements, final steps is Register DataService.there are two main step: + +- **DI Registration**: in this phase, all requirements for Enabling Push Notifications Registered in DI Container. +- **Middleware Usage**: in this phase, all registered Hubs enabled using it's Provided routes and then accessible through their Paths. + +#### Configure Service + +this service Configured using this Configuration Model: + +```C# +public partial class XPushServiceConfiguration { + /// + /// Base route of WebSocket Server ... + /// + /// string + public string BaseRoute { get; set; } + + /// + /// determines log level of signalR ... + /// + /// + public object ConnectionLogLevel { get; set; } + + /// + /// when client disconnected it's automatically try to reconnect, this + /// determines max number of try to connect ... + /// + /// + public int PushConnectionMaxRetry { get; set; } + + /// + /// add support for message protocol ... + /// + /// + public bool AddSupportMessageProtocol { get; set; } + + /// + /// the delay between two connection try .. + /// + /// + public int PushConnectionReconnectDelay { get; set; } +} +``` + +you can directly instanced this class and fill it and use it in Service Registration phase for Configuring Service. or Configure Service using App Setting Filling like this: ```json - - ... - - "PushServiceConfiguration": { +... +"PushServiceConfiguration": { "BaseRoute": "hubs", - "AddSupportMessageProtocol": false - }, - - ... - + "AddSupportMessageProtocol": true +}, +... ``` -this is a sample configuration. for more info you can review [xPushService Documentation](http://x-dashboard.saherelm.ir/modules/xPushService/index.html#File:Configurations/XPushServiceConfiguration.cs) +for Register Service and see different Methods: -then register **xPushService** in **Startup.cs**: +```C# +... +/// +/// Register Module Provided Service on DI +/// +/// +/// +public static void AddXPushService( + this IServiceCollection services, + IConfiguration config, + ServiceLifetime lifeTime = ServiceLifetime.Scoped +); -```c# - public class Startup { +/// +/// Register Module Provided Service on DI +/// +/// +/// +public static void AddXPushService( + this IServiceCollection services, + XPushServiceConfiguration config, + ServiceLifetime lifeTime = ServiceLifetime.Scoped +); +... +``` + +and for enable Hubs Middle wares you Have to Introduce your Hubs through an Instance of xPushServiceHelper class and provides it to Middleware Registrations: + +```C# +/// +/// Use Module Middlewares on Application Builder +/// +/// +/// +public static void UseXPushService( + this IApplicationBuilder app, + XPushServiceHelper helper +); +``` + +full Service Registration: + +```C# +public class Startup +{ + // + public IConfiguration Configuration { get; } + + public Startup(IConfiguration configuration) + { ... - public void ConfigureServices (IServiceCollection services) { - ... - // - // Register XPushService ... - services.AddXPushService (Configuration); - ... - } + Configuration = configuration; ... } -``` -next step is use **xPushService** middleware for declare and usage of your custom created **HUB**(s) in **xPushHelper** module. this must be done by an instance of **XPushServiceHelper** class which you have to use it for registering your hubs. then pass this to **xPushService** Middleware for configure them for working. - -```c# - public class Startup { + public void ConfigureServices(IServiceCollection services) + { ... - public void Configure (IApplicationBuilder app, IWebHostEnvironment env) { - ... - // - #region XPushService ... - // - var helper = new XPushServiceHelper (); + // + // Push Service ... + services.AddXPushService( + config: configuration, + lifeTime: ServiceLifetime.Scoped + ); - // - helper.AddHub ("view"); - helper.AddHub ("webrtc"); - - // - app.UseXPushService (helper); - #endregion - ... - } + // + // Register Provider Services ... + // since Hubs required Identity Provider, you Have to Register IdentityService as Requirements ... + // a Provider Service, Provides Repository (Entity) or Service (Dto) based + // Data Manipulation Actions by Supporting Hub Contexts Events ... + services.AddScoped(); + services.AddScoped(); ... } + + public void Configure(IApplicationBuilder app, IWebHostEnvironment env) + { + ... + // + // Instance Service Helper ... + var pushHelper = new XPushServiceHelper(); + + // + // Introduce Hubs and their Child paths ... + pushHelper.AddHub("testDto"); + pushHelper.AddHub("testEntity"); + + // + // Use Push Service Middlewares ... + app.UseXPushService(pushHelper); + ... + } +} ``` -for the moment **xPushService** configured successfully and activated in your application. - -for client side, you can follow it's related documentation. - ## Maintainer Hadi Khazaee asl diff --git a/xPushService.csproj b/xPushService.csproj index 0b46785..9f172a6 100644 --- a/xPushService.csproj +++ b/xPushService.csproj @@ -30,6 +30,7 @@ +