Envoyer des messages à partir de l’extérieur d’un hub

Le hub SignalR est l’abstraction principale pour l’envoi de messages aux clients connectés au serveur SignalR. Vous pouvez également envoyer des messages à partir d’autres emplacements de votre application à l’aide du service IHubContext. Cet article explique comment accéder à un SignalRIHubContext pour envoyer des notifications aux clients à partir de l’extérieur d’un hub.

Remarque

Le IHubContext permet d’envoyer des notifications aux clients ; il ne sert pas à appeler des méthodes sur le Hub.

Afficher ou télécharger l’exemple de code(procédure de téléchargement)

Obtenir une instance de IHubContext

Dans ASP.NET Core SignalR, vous pouvez accéder à une instance de IHubContext via l’injection de dépendances. Vous pouvez injecter un instance de IHubContext dans un contrôleur, un intergiciel ou un autre service d’injection de dépendances. Utilisez l’instance pour envoyer des messages aux clients.

Injecter une instance de IHubContext dans un contrôleur

Vous pouvez injecter une instance de IHubContext dans un contrôleur en l’ajoutant à votre constructeur :

public class HomeController : Controller
{
    private readonly IHubContext<NotificationHub> _hubContext;

    public HomeController(IHubContext<NotificationHub> hubContext)
    {
        _hubContext = hubContext;
    }
}

Avec l’accès à une instance de IHubContext, appelez les méthodes clientes comme si vous étiez dans le hub lui-même :

public async Task<IActionResult> Index()
{
    await _hubContext.Clients.All.SendAsync("Notify", $"Home page loaded at: {DateTime.Now}");
    return View();
}

Obtenir une instance de IHubContext dans l’intergiciel

Accédez au IHubContext dans le pipeline d’intergiciel comme suit :

app.Use(async (context, next) =>
{
    var hubContext = context.RequestServices
                            .GetRequiredService<IHubContext<ChatHub>>();
    //...
    
    if (next != null)
    {
        await next.Invoke();
    }
});

Remarque

Quand des méthodes clientes sont appelées de l’extérieur de la classe Hub, aucun appelant n’est associé à l’appel. Par conséquent, il n’y a aucun accès aux propriétés ConnectionId, Calleret Others.

Les applications qui doivent mapper un utilisateur à l’injection de dépendances de connexion et conserver ce mappage peuvent effectuer l’une des opérations suivantes :

  • Conserver le mappage d’une ou plusieurs connexions sous forme de groupes. Pour plus d’informations, consultez Groupes dans SignalR.
  • Conservez les informations de connexion et d’utilisateur via un service singleton. Pour plus d’informations, consultez Injecter des services dans un hub. Le service singleton peut utiliser n’importe quelle méthode de stockage, telle que :
    • Stockage en mémoire dans un dictionnaire.
    • Stockage externe permanent. Par exemple, une base de données ou un stockage de tables Azure utilisant le package NuGet Azure.Data.Tables.
  • Transmettez l’ID de connexion entre les clients.

Obtenir une instance de IHubContext à partir d’IHost

L’accès à un IHubContext à partir de l’hôte web est utile pour l’intégration à des zones en dehors de ASP.NET Core, par exemple, à l’aide d’infrastructures d’injection de dépendances tierces :

    public class Program
    {
        public static void Main(string[] args)
        {
            var host = CreateHostBuilder(args).Build();
            var hubContext = host.Services.GetService(typeof(IHubContext<ChatHub>));
            host.Run();
        }

        public static IHostBuilder CreateHostBuilder(string[] args) =>
            Host.CreateDefaultBuilder(args)
                .ConfigureWebHostDefaults(webBuilder => {
                    webBuilder.UseStartup<Startup>();
                });
    }

Injecter un HubContext fortement typé

Pour injecter un HubContext fortement typé, assurez-vous que votre hub hérite de Hub<T>. Injectez-le à l’aide de l’interface IHubContext<THub, T> plutôt que IHubContext<THub>.

public class ChatController : Controller
{
    public IHubContext<ChatHub, IChatClient> _strongChatHubContext { get; }

    public ChatController(IHubContext<ChatHub, IChatClient> chatHubContext)
    {
        _strongChatHubContext = chatHubContext;
    }

    public async Task SendMessage(string user, string message)
    {
        await _strongChatHubContext.Clients.All.ReceiveMessage(user, message);
    }
}

Pour plus d’informations, consultez Hubs fortement typés.

Utiliser IHubContext dans le code générique

Une instance injectée IHubContext<THub> peut être convertie en IHubContext sans type générique Hub spécifié.

class MyHub : Hub
{ }

class MyOtherHub : Hub
{ }

app.Use(async (context, next) =>
{
    var myHubContext = context.RequestServices
                            .GetRequiredService<IHubContext<MyHub>>();
    var myOtherHubContext = context.RequestServices
                            .GetRequiredService<IHubContext<MyOtherHub>>();
    await CommonHubContextMethod((IHubContext)myHubContext);
    await CommonHubContextMethod((IHubContext)myOtherHubContext);

    await next.Invoke();
}

async Task CommonHubContextMethod(IHubContext context)
{
    await context.Clients.All.SendAsync("clientMethod", new Args());
}

Cela est utile quand :

  • Écriture de bibliothèques qui n’ont pas de référence au type spécifique Hub utilisé par l’application.
  • Écriture de code générique qui peut s’appliquer à plusieurs implémentations Hub différentes

Ressources supplémentaires