Fonctionnement d’ASP.NET Core SignalR

Effectué

Serveurs et classe Hub

La classe Hub est un concept de serveur SignalR. Elle est définie dans l’espace de noms Microsoft.AspNetCore.SignalR et fait partie du package NuGet Microsoft.AspNetCore.SignalR. Les applications web ASP.NET Core qui ciblent le kit de développement logiciel (SDK) Microsoft.NET.Sdk.Web n’ont pas besoin d’ajouter une référence de package pour SignalR, car elle est déjà disponible comme faisant partie de l’infrastructure partagée.

Un Hub est exposé via un itinéraire. Par exemple, la route https://www.contoso-pizza.com/hubs/orders pourrait être utilisée pour représenter une implémentation OrdersHub. À travers les différentes API de hub, les auteurs peuvent définir des méthodes et des événements.

Il existe deux modalités pour exposer des méthodes sur un hub. Vous créez une sous-classe des types et des méthodes d’écriture qui suivent :

  • Hub : hub standard.
  • Hub<T> : hub générique fortement typé.

Exemple Hub

Prenons comme point de référence l’objet Notification suivant :

namespace RealTime.Models;

public record Notification(string Text, DateTime Date);

L’objet peut être partagé en cas d’utilisation du kit SDK du client .NET pour permettre au serveur et au client d’avoir exactement le même objet. Imaginez un hub de notification :

using Microsoft.AspNetCore.SignalR;
using System;
using System.Threading.Tasks;
using RealTime.Models;

namespace ExampleServer.Hubs;

public sealed class NotificationHub : Hub
{
    public Task NotifyAll(Notification notification) =>
        Clients.All.SendAsync("NotificationReceived", notification);
}

Quant à la différence entre les méthodes et les événements, la méthode utilisée dans la précédente implémentation du hub est NotifyAll, alors que l’événement est NotificationReceived. NotificationHub est une sous-classe de Hub. La méthode NotifyAll retourne Task et accepte un seul paramètre Notification. La méthode est exprimée sous la forme de l’appel de SendAsync à partir de Clients.All, qui représente tous les clients connectés. L’événement NotificationReceived est déclenché, en fonction de l’instance notification.

L’instance IHubContext

Vous déclenchez des événements à partir d’une instance de Hub ou IHubContext. 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 de l’un des types suivants :

  • IHubContext<THub> : contexte où THub représente un hub standard.
  • IHubContext<THub,T> : Contexte où THub représente un hub générique fortement typé, et où T représente le type de client correspondant.

Important

IHubContext permet d’envoyer des notifications aux clients. Il n’est pas utilisé pour appeler des méthodes sur le Hub.

Exemple : IHubContext

Compte tenu de la précédente implémentation du hub de notification, vous pouvez utiliser IHubContext<NotificationHub> de la manière suivante :

using Microsoft.AspNetCore.SignalR;
using System;
using System.Threading.Tasks;
using RealTime.Models;

namespace ExampleServer.Services;

public sealed class NotificationService(
    IHubContext<NotificationHub> hubContext)
{
    public Task SendNotificationAsync(Notification notification) =>
        notification is not null
            ? hubContext.Clients.All.SendAsync("NotificationReceived", notification)
            : Task.CompletedTask;
}

Le code C# précédent s’appuie sur IHubContext<NotificationHub> pour accéder à la liste contextuelle des clients, ce qui permet de diffuser des notifications. Le paramètre de constructeur principal hubContext qui est capturé dans l’étendue est utilisé pour déclencher l’événement "NotificationReceived", mais il n’est pas destiné à être utilisé pour appeler la méthode NotifyAll du hub.

Méthodes

Les méthodes Hub et Hub<T> sont comme n’importe quelle autre méthode C#. Elles définissent un type de retour, un nom de méthode et des paramètres.

  • Le type de retour le plus courant pour une méthode de hub est Task ou Task<TResult>, ce qui représente le fonctionnement asynchrone du hub.
  • Le nom de la méthode est utilisé pour appeler la méthode à partir des clients. Vous pouvez le personnaliser à l’aide de HubMethodNameAttribute.
  • Les paramètres sont facultatifs, mais quand ils sont définis, les clients sont censés fournir les arguments correspondants.

Les méthodes ne sont pas obligées de déclencher des événements, mais elles le font souvent.

Événements

Vous pouvez vous abonner à un événement par son nom à partir d’un client. Le serveur est responsable du déclenchement des événements. Les événements Hub, Hub<T>, IHubContext<THub> et IHubContext<THub, T> sont nommés et définissent jusqu’à 10 paramètres. Les événements sont déclenchés sur le serveur et gérés par les clients intéressés. Un client est considéré comme intéressé quand il s’abonne aux événements de la connexion de son hub. Les clients peuvent déclencher indirectement des événements quand ils appellent des méthodes de hub qui déclenchent des événements à la suite de leur appel. Toutefois, les événements ne peuvent pas être déclenchés directement par les clients, car il s’agit de la responsabilité du serveur.

Étendues des clients des événements

Vous appelez les événements à partir d’une instance de IClientProxy. Vous implémentez les interfaces IHubClients et IHubCallerClients à partir du type Clients. Il existe de nombreuses façons de définir l’étendue à une instance IClientProxy spécifique. Vous pouvez cibler les étendues suivantes avec la propriété Hub.Clients :

Membre Détails
All Tous les clients connectés (par exemple une diffusion).
AllExcept Tous les clients connectés, à l’exception des connexions spécifiées (par exemple la diffusion filtrée).
Caller Client connecté qui a déclenché la méthode (par exemple un écho).
Client La connexion cliente spécifiée (connexion unique).
Clients Les connexions clientes spécifiées (connexions multiples).
Group Tous les clients connectés dans le groupe spécifié.
GroupExcept Tous les clients connectés dans le groupe spécifié, à l’exception des connexions spécifiées.
Groups Tous les clients connectés au sein des groupes spécifiés (plusieurs groupes).
Others Tous les clients connectés, à l’exception du client qui a déclenché la méthode.
OthersInGroup Tous les clients connectés dans le groupe spécifié, à l’exception du client qui a déclenché la méthode.
User Tous les clients connectés pour l’utilisateur spécifié (un seul utilisateur peut se connecter sur plusieurs appareils).
Users Tous les clients connectés pour les utilisateurs spécifiés.

Exemples d’étendues

Examinez les images suivantes, qui peuvent vous aider à visualiser la manière dont le hub envoie des messages aux clients ciblés. Vous pouvez agrandir les images pour améliorer la lisibilité.

  • Diffuser à tout le monde

    Hub ASP.NET Core SignalR envoyant un message avec la syntaxe Clients.All.

    Tous les clients connectés reçoivent ce message, quel que soit le groupe auquel ils appartiennent ou non.

  • Utilisateur isolé

    Hub ASP.NET Core SignalR envoyant un message avec la syntaxe Clients.User.

    Un seul utilisateur reçoit ce message, quel que soit le nombre d’appareils qu’il utilise.

  • Groupe isolé

    Hub ASP.NET Core SignalR envoyant un message avec la syntaxe Clients.Group.

    Seuls les clients qui appartiennent à un certain groupe reçoivent ce message.

Clients et classe HubConnection

La classe HubConnection est un concept de client SignalR, qui représente la connexion du client au serveur Hub. Elle est définie dans l’espace de noms Microsoft.AspNetCore.SignalR.Client et fait partie du package NuGet Microsoft.AspNetCore.SignalR.Client.

Vous créez un HubConnection à l’aide du modèle de générateur et du type HubConnectionBuilder correspondant. À partir de l’itinéraire du hub (ou System.Uri), vous pouvez créer un HubConnection. Le générateur peut également spécifier des options de configuration supplémentaires, qui comprennent entre autres la journalisation, le protocole souhaité, le transfert de jetons d’authentification et la reconnexion automatique.

L’API HubConnection expose les fonctions de démarrage et d’arrêt, utilisées pour démarrer et arrêter la connexion au serveur. De plus, il existe des fonctionnalités pour le streaming, l’appel de méthodes de hub et l’abonnement aux événements.

Exemple de création de HubConnection

Pour créer un objet HubConnection à partir du kit SDK du client .NET SignalR, utilisez le type HubConnectionBuilder :

using Microsoft.AspNetCore.SignalR.Client;
using System;
using System.Threading.Tasks;
using RealTime.Models;

namespace ExampleClient;

public sealed class Consumer : IAsyncDisposable
{
    private readonly string HostDomain =
        Environment.GetEnvironmentVariable("HOST_DOMAIN");
    
    private HubConnection _hubConnection;

    public Consumer()
    {
        _hubConnection = new HubConnectionBuilder()
            .WithUrl(new Uri($"{HostDomain}/hub/notifications"))
            .WithAutomaticReconnect()
            .Build();
    }

    public Task StartNotificationConnectionAsync() =>
        _hubConnection.StartAsync();

    public async ValueTask DisposeAsync()
    {
        if (_hubConnection is not null)
        {
            await _hubConnection.DisposeAsync();
            _hubConnection = null;
        }
    }
}

Appeler les méthodes d’un hub

Si un client reçoit une instance cliente de HubConnection a démarré correctement, ce client peut appeler des méthodes sur un hub à l’aide des extensions InvokeAsync ou SendAsync. Si la méthode du hub retourne Task<TResult>, le résultat de InvokeAsync<TResult> est de type TResult. Si la méthode du hub retourne Task, cela signifie qu’il n’existe aucun résultat. InvokeAsync et SendAsync exigent tous les deux le nom de la méthode du hub ainsi qu’un nombre de paramètres compris entre zéro et dix.

  • InvokeAsync : appelle une méthode de hub sur le serveur à l’aide du nom de méthode spécifié et d’arguments facultatifs.
  • SendAsync : appelle une méthode de hub sur le serveur à l’aide du nom de méthode spécifié et d’arguments facultatifs. Cette méthode n’attend pas de réponse du récepteur.

Exemple d’appel de méthode de hub

Quand SendNotificationAsync ajoute une méthode à la classe Consumer précédente, SendNotificationAsync délègue à _hubConnection et appelle la méthode NotifyAll sur le hub du serveur en fonction de l’instance de Notification.

public Task SendNotificationAsync(string text) =>
    _hubConnection.InvokeAsync(
        "NotifyAll", new Notification(text, DateTime.UtcNow));

Gérez les événements

Pour gérer les événements, vous devez inscrire un gestionnaire auprès de l’instance de HubConnection. Appelez l’une des surcharges de HubConnectionExtensions.On quand vous connaissez le nom de la méthode de hub et avez un nombre de paramètres compris entre zéro et huit. Le gestionnaire peut répondre à l’une des variantes suivantes de Action :

Vous pouvez également utiliser les API de gestionnaire asynchrone, qui sont des Func<TResult>TResult est une variante de Task :

Le résultat de l’inscription d’un gestionnaire d’événements est un IDisposable, qui sert d’abonnement. Pour désabonner le gestionnaire, appelez Dispose.

Exemple d’inscription à un événement

En mettant à jour la classe Consumer précédente, vous vous inscrivez à un événement en fournissant un gestionnaire et en appelant On :

using Microsoft.AspNetCore.SignalR.Client;
using System;
using System.Threading.Tasks;
using RealTime.Models;

namespace ExampleClient;

public sealed class Consumer : IAsyncDisposable
{
    private readonly string HostDomain =
        Environment.GetEnvironmentVariable("HOST_DOMAIN");
    
    private HubConnection _hubConnection;

    public Consumer()
    {
        _hubConnection = new HubConnectionBuilder()
            .WithUrl(new Uri($"{HostDomain}/hub/notifications"))
            .WithAutomaticReconnect()
            .Build();

        _hubConnection.On<Notification>(
            "NotificationReceived", OnNotificationReceivedAsync);
    }

    private async Task OnNotificationReceivedAsync(Notification notification)
    {
        // Do something meaningful with the notification.
        await Task.CompletedTask;
    }

    // Omitted for brevity.
}

La méthode OnNotificationReceivedAsync est appelée quand l’instance de hub du serveur déclenche l’événement "NotificationReceived".

Mises à jour des commandes en temps réel de Contoso Pizza

Le code serveur de l’application web doit avoir une implémentation de Hub et exposer une route aux clients. Le Hub peut utiliser l’identificateur unique de l’objet de commande pour créer un groupe de suivi. Toutes les mises à jour des changements d’état des commandes peuvent ensuite être communiquées à ce groupe.

Le code client doit également être mis à jour pour indiquer que l’application Contoso Pizza est une application Blazor WebAssembly. Vous pouvez utiliser le kit SDK JavaScript ou celui du client .NET. Remplacez ensuite la fonctionnalité d’interrogation côté client par du code qui génère un HubConnection, puis démarrez la connexion au serveur. Quand l’utilisateur accède à la page de suivi des commandes, le code doit joindre le groupe spécifique de la commande où les mises à jour des changements sont envoyées. Vous devez vous abonner à l’événement pour connaître les changements d’état de la commande, puis gérer la situation de manière appropriée.