Base solution for your next web application
Open Closed

broadcast information from application service layer #4555


User avatar
0
carelearning created

We want a way to broadcast a message from the application service layer. However, signalR Hubs are only available in the Web layer. Therefore, we cannot call from a service into the Web layer. Using [https://aspnetboilerplate.com/Pages/Documents/Notification-System]) as a guide we have:

//server
        public async Task PublishSaveAsync()
        {
            await _notificationPublisher.PublishAsync("message");
        }

//client
    function initializeHub() {
        abp.event.on('abp.notifications.received', processSaved);
    };

    function processSaved(saveNotification) {
            console.log('saveNotification', saveNotification);
    };

The server code is executed, but the log statement is never written. Are we doing something incorrectly or is there a better way to do this?

Thanks.


5 Answer(s)
  • User Avatar
    0
    strix20 created

    Why not create a generic hub interface in your app layer, implement it on your signalR hub, and then register that dependency in the web layer, and inject it in the app service?

  • User Avatar
    0
    ismcagdas created
    Support Team

    Thanks @strix20 :)

  • User Avatar
    0
    carelearning created

    @strix20 Thanks for the response. Here is our implementation below.

    Generic Interface

    public interface ISave<T>
    {
      void Save(T payload);
    }
    

    Signal R Hub

    [HubName("myHub")]
    public class MyHub: Hub, ITransientDependency, ISave<string>
    {   
       /* https://aspnetboilerplate.com/Pages/Documents/SignalR-Integration#your-signalr-code */
    
      public void Save(string payload)
      {
        Clients.Others.saved(payload);
       }
    }
    

    App Service

    public class MyAppService : AbpZeroTemplateAppServiceBase, IMyAppService 
    {
      private readonly ISave<string> _hub;
    
      public MyAppService(ISave<string> hub) 
      {
         _hub = hub;
      }
    
      public async Task<Result<Dictionary<long, long>>> SaveAsync(MasterCommandDto commands) 
      {
           /* elided */
    
          var payload = JsonConvert.SerializeObject(commands);
          _hub.Save(payload);
    
           // ..
      }
    }
    
    public class AbpZeroTemplateWebModule : AbpModule
    {
      public override void Initialize()
      {
         IocManager.Register<ISave<string>, MyHub>();
      }
    }
    

    When we register the component in the Web layer we get this server error: Component MyCompanyName.AbpZeroTemplate.Web.Hubs.MyHub could not be registered. There is already a component with that name. Did you want to modify the existing component instead? If not, make sure you specify a unique name.

    What is the appropriate way of adding this to the IOC container?

  • User Avatar
    0
    aaron created
    Support Team

    Register it in the PreInitialize method.

  • User Avatar
    0
    carelearning created

    Thank you @aaron and @strix20. This works; wWe have our server-side payload from the application service via the Web's SignalR.