Send messages via SignalR HubContext from method in project outside where Hubs are located

Viewed 481

I have a WebAPI project where the API, Service and Data layers are all in separate projects of the same solution. As part of a method in my Service project, I want to send a message to the connected clients of a hub in the API project. So far all of the examples I have found have everything in a single project and use a controller as the example sending a message via a hub.

I've tried dependency injection (Autofac) however I am unable to get a reference to the MessageHub.

enter image description here

[HubName("messages")]
public class MessageHub : Hub
{
    public void ShowNewMessage(string message)
    {
        Clients.All.showMessageOnPage(message);
    }
}

My attempt at Injecting can be seen here: Inject SignalR IHubContext into service layer with Autofac

1 Answers

Please review this option:

  1. Define generic hub interface in your Service (or better Domain) Layer project. Something like IMessageBroker.
  2. Inside your Presentation Layer (WebAPI) project implement this interface and use IConnectionManager for HubContext retrieving.
  3. Register the interface in an IoC Container (Autofac) in the Presentation Layer
  4. Inject the interface inside App Service

Pseudo Code:

Domain Layer:

public interface IMessageBroker
{
    void ShowNewMessage(string message)
}

Service Layer:

public class NotificationService: INotificationService
{
    private readonly IMessageBroker _messageBroker;

    public NotificationService(IMessageBroker messageBroker)
    {
        _messageBroker = messageBroker;
    }

    public void RunNotification(string message)
    {
        _messageBroker.ShowNewMessage(message);
    }
}

Presentation Layer:

[HubName("messages")]
public class MessageHub: Hub
{
    public void ShowNewMessage(string message)
    {
        Clients.All.showMessageOnPage(message);
    }
}


public class MessageBroker: IMessageBroker
{
    private readonly IConnectionManager _connectionManager;

    public MessageBroker(IConnectionManager connectionManager)
    {
        _connectionManager = connectionManager;
    }

    public void ShowNewMessage(string message)
    {
        var hub = _connectionManager.GetHubContext<MessageHub>();
        // Use Hub Context and send message
    }
}

Autofac Registration (Presentation Layer):

// Register Hubs
builder.RegisterHubs(Assembly.GetExecutingAssembly());

// Register Autofac resolver into container to be set into HubConfiguration later
builder.RegisterType<AutofacDependencyResolver>().As<IDependencyResolver>().SingleInstance();

// Register ConnectionManager as IConnectionManager so that you can get hub context via IConnectionManager injected to your service
builder.RegisterType<ConnectionManager>().As<IConnectionManager>().SingleInstance();

// Register interface
builder.RegisterType<MessageBroker>().As<IMessageBroker>();

Also similar SO topic is available here.

Related