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.

Markdown is supported
Copy & paste or drag & drop images (max 30 MB per image)

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?

    Markdown is supported
    Copy & paste or drag & drop images (max 30 MB per image)
  • User Avatar
    0
    ismcagdas created
    Support Team

    Thanks @strix20 :)

    Markdown is supported
    Copy & paste or drag & drop images (max 30 MB per image)
  • 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?

    Markdown is supported
    Copy & paste or drag & drop images (max 30 MB per image)
  • User Avatar
    0
    aaron created
    Support Team

    Register it in the PreInitialize method.

    Markdown is supported
    Copy & paste or drag & drop images (max 30 MB per image)
  • 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.

    Markdown is supported
    Copy & paste or drag & drop images (max 30 MB per image)