Enviar mensajes a través de SignalR HubContext desde el método en el proyecto fuera de donde se encuentran los concentradores

Dec 08 2020

Tengo un proyecto WebAPI donde las capas de API, servicio y datos están todas en proyectos separados de la misma solución. Como parte de un método en mi proyecto de servicio, quiero enviar un mensaje a los clientes conectados de un centro en el proyecto de API. Hasta ahora, todos los ejemplos que he encontrado tienen todo en un solo proyecto y usan un controlador como ejemplo para enviar un mensaje a través de un concentrador.

Probé la inyección de dependencia (Autofac), sin embargo, no puedo obtener una referencia al MessageHub.

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

Mi intento de inyección se puede ver aquí: Inyectar SignalR IHubContext en la capa de servicio con Autofac

Respuestas

1 AlexanderI. Dec 08 2020 at 04:41

Revise esta opción:

  1. Defina una interfaz de concentrador genérica en su proyecto de capa de servicio (o mejor dominio). Algo como IMessageBroker.
  2. Dentro de su proyecto Presentation Layer (WebAPI), implemente esta interfaz y utilícela IConnectionManagerpara recuperar HubContext.
  3. Registre la interfaz en un contenedor IoC (Autofac) en la capa de presentación
  4. Inyectar la interfaz dentro de App Service

Pseudo código:

Capa de dominio:

public interface IMessageBroker
{
    void ShowNewMessage(string message)
}

Capa de servicio:

public class NotificationService: INotificationService
{
    private readonly IMessageBroker _messageBroker;

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

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

Capa de presentación:

[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
    }
}

Registro de Autofac (capa de presentación):

// 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>();

También hay un tema SO similar disponible aquí .