Funzionamento di SignalR ASP.NET Core

Completato

Server e classe Hub

La classe Hub è un concetto di server SignalR. Viene definita all'interno dello spazio dei nomi Microsoft.AspNetCore.SignalR e fa parte del pacchetto NuGet Microsoft.AspNetCore.SignalR. ASP.NET app Web core destinate a Microsoft.NET.Sdk.Web SDK non devono aggiungere un riferimento al pacchetto per SignalR, perché è già disponibile come parte del framework condiviso.

Un Hub oggetto viene esposto tramite una route. Ad esempio, si può usare la route https://www.contoso-pizza.com/hubs/orders per rappresentare un'implementazione OrdersHub. Tramite le varie API dell'hub, gli autori possono definire metodi ed eventi.

Per esporre i metodi in un hub sono disponibili due modalità. Creare una sottoclasse dei tipi e dei metodi di scrittura seguenti:

  • Hub: hub standard.
  • Hub<T>: hub generico fortemente tipizzato.

EsempioHub

Come punto di riferimento, considerare l'oggetto Notification seguente:

namespace RealTime.Models;

public record Notification(string Text, DateTime Date);

L'oggetto può essere condiviso quando si usa .NET client SDK, in modo che il server e il client abbiano esattamente lo stesso oggetto. Si immagini un hub di notifica:

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);
}

Per quanto riguarda la differenza tra metodi ed eventi, il metodo nell'implementazione dell'hub precedente è NotifyAlle l'evento è NotificationReceived. NotificationHub è una sottoclasse di Hub. Il NotifyAll metodo restituisce un Taskoggetto e accetta un singolo Notification parametro. Il metodo viene espresso come chiamata a SendAsync da Clients.All, che rappresenta tutti i client connessi. Viene generato l'evento NotificationReceived, a seconda dell'istanza di notification.

Istanza di IHubContext

Gli eventi vengono generati da un'istanza IHubContextHub di o . L'hub SignalR è il fulcro dell'astrazione per l'invio di messaggi ai client connessi al server SignalR. È anche possibile inviare messaggi da altre posizioni dell'app usando uno dei tipi seguenti:

  • IHubContext<THub>: contesto in cui THub rappresenta un hub standard.
  • IHubContext<THub,T>: contesto in cui THub rappresenta un hub generico fortemente tipizzato e T rappresenta il tipo di client corrispondente.

Importante

IHubContext è per l'invio di notifiche ai client. Non viene usato per chiamare i metodi in Hub.

Ad esempio, IHubContext

Considerando l'implementazione precedente dell'hub di notifica, è possibile usare IHubContext<NotificationHub> come segue:

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

Il codice C# precedente si basa su IHubContext<NotificationHub> per accedere all'elenco contestuale dei client, esponendo la possibilità di trasmettere le notifiche. Il parametro hubContext del costruttore primario acquisito nell'ambito viene usato per generare l'evento "NotificationReceived", ma non è destinato a essere usato per chiamare il metodo NotifyAll dell'hub.

Metodi

I metodi Hub o Hub<T> sono esattamente uguali a qualsiasi altro metodo C#. Definiscono un tipo restituito, un nome di metodo e parametri.

  • Il tipo restituito più comune per un metodo hub è Task o Task<TResult>, che rappresenta l'operazione asincrona dell'hub.
  • Il nome del metodo viene usato per chiamare il metodo dai client. Può essere personalizzato usando HubMethodNameAttribute.
  • I parametri sono facoltativi, ma se vengono definiti i client devono fornire argomenti corrispondenti.

I metodi non sono necessari per generare eventi, sebbene spesso lo facciano.

evento

Un evento può essere sottoscritto in base al nome da un client. Il server è responsabile della generazione di eventi. HubGli eventi , Hub<T>IHubContext<THub>, e IHubContext<THub, T> sono denominati e possono definire fino a 10 parametri. Gli eventi vengono generati nel server e sono gestiti dai client interessati. Un client è considerato interessato quando sottoscrive gli eventi sulla connessione dell'hub. I client possono attivare indirettamente gli eventi quando chiamano metodi hub che generano eventi risultanti dalla chiamata. Gli eventi non possono tuttavia essere attivati direttamente dai client, perché è responsabilità del server.

Ambiti client di eventi

Chiamare gli eventi da un'istanza di IClientProxy. Implementare le interfacce IHubClients e IHubCallerClients dal tipo Clients. Esistono molti modi per definire l'ambito di un'istanza di IClientProxy specifica. È possibile specificare come destinazione gli ambiti seguenti dalla proprietà Hub.Clients:

Membro Dettagli
All Tutti i client connessi, ad esempio una trasmissione.
AllExcept Tutti i client connessi, escluse le connessioni specificate, ad esempio una trasmissione filtrata.
Caller Il client connesso che ha attivato il metodo, ad esempio un echo.
Client La connessione client specificata (singola connessione).
Clients Le connessioni client specificate (più connessioni).
Group Tutti i client connessi all'interno del gruppo specificato.
GroupExcept Tutti i client connessi all'interno del gruppo specificato, escluse le connessioni specificate.
Groups Tutti i client connessi all'interno dei gruppi specificati (più gruppi).
Others Tutti i client connessi, escluso il client che ha attivato il metodo.
OthersInGroup Tutti i client connessi all'interno del gruppo specificato, escluso il client che ha attivato il metodo.
User Tutti i client connessi per l'utente specificato (un singolo utente può connettersi su più di un dispositivo).
Users Tutti i client connessi per gli utenti specificati.

Ambiti di esempio

Osservare le immagini seguenti, che consentono di visualizzare il modo in cui l'hub invia messaggi ai client di destinazione. È possibile espandere le immagini per migliorare la leggibilità.

  • Trasmettere a tutti

    ASP.NET Core SignalR hub sending message with Clients.All syntax.

    Tutti i client connessi ricevono questo messaggio, indipendentemente dal gruppo a cui potrebbero o meno appartenere.

  • Utente isolato

    ASP.NET Core SignalR hub sending message with Clients.User syntax.

    Un singolo utente riceve questo messaggio, indipendentemente dal numero di dispositivi attualmente in uso.

  • Gruppo isolato

    ASP.NET Core SignalR hub sending message with Clients.Group syntax.

    Solo i client che appartengono a un determinato gruppo ricevono questo messaggio.

Client e classe HubConnection

La classe HubConnection è un concetto di client SignalR, che rappresenta la connessione del client al server Hub. Viene definita all'interno dello spazio dei nomi Microsoft.AspNetCore.SignalR.Client e fa parte del pacchetto NuGet Microsoft.AspNetCore.SignalR.Client.

Si crea un HubConnection oggetto usando il modello di generatore e il tipo corrispondente HubConnectionBuilder . Data la route dell'hub (o System.Uri), è possibile creare un oggetto HubConnection. Il generatore può anche specificare opzioni di configurazione aggiuntive, tra cui la registrazione, il protocollo desiderato, l'inoltro dei token di autenticazione e la riconnessione automatica.

L'API HubConnection espone le funzioni di avvio e arresto, usate per avviare e arrestare la connessione al server. Sono anche disponibili funzionalità per lo streaming, la chiamata ai metodi dell'hub e la sottoscrizione agli eventi.

Esempio di creazione di un oggetto HubConnection

Per creare un oggetto HubConnection dall'SDK client .NET SignalR, usare il tipo 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;
        }
    }
}

Chiamare i metodi dell'hub

Se a un client viene assegnata un'istanza client HubConnection che è stata avviata correttamente, tale client può chiamare i metodi in un hub usando le InvokeAsync estensioni o SendAsync . Se il metodo hub restituisce un oggetto Task<TResult>, il risultato di InvokeAsync<TResult> è di tipo TResult. Se il metodo hub restituisce Task, non si ottiene alcun risultato. Sia InvokeAsync che SendAsync richiedono il nome del metodo hub e zero a 10 parametri.

  • InvokeAsync: chiama un metodo hub nel server usando il nome del metodo e gli argomenti facoltativi specificati.
  • SendAsync: chiama un metodo hub nel server usando il nome del metodo e gli argomenti facoltativi specificati. Questo metodo non attende una risposta dal destinatario.

Esempio di chiamata al metodo hub

Quando SendNotificationAsync aggiunge un metodo alla classe precedente Consumer , SendNotificationAsync delega all'oggetto _hubConnection e chiama il NotifyAll metodo nell'hub del server, a seconda dell'istanza Notification .

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

Gestire eventi

Per gestire gli eventi, registrare un gestore con l'istanza di HubConnection. Chiamare uno degli overload HubConnectionExtensions.On quando il nome del metodo hub è noto e si hanno da zero a otto parametri. Il gestore può soddisfare una delle varianti Action seguenti:

In alternativa, è possibile usare le API del gestore asincrono, che sono Func<TResult> dove è TResult una variante Task:

Il risultato della registrazione di un gestore eventi è un IDisposableoggetto , che funge da sottoscrizione. Per annullare la sottoscrizione del gestore, chiamare Dispose.

Esempio di registrazione di un evento

Aggiornando la classe Consumer precedente, si esegue la registrazione a un evento specificando un gestore e chiamando 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.
}

Il metodo OnNotificationReceivedAsync viene chiamato quando l'istanza dell'hub del server genera l'evento "NotificationReceived".

Aggiornamenti degli ordini live di Contoso Pizza

Il codice del server per l'applicazione Web deve avere un'implementazione Hub ed esporre una route ai client. Hub può usare l'identificatore univoco dell'oggetto ordine per creare un gruppo per il rilevamento. Tutti gli aggiornamenti delle modifiche dello stato dell'ordine possono quindi essere comunicati in questo gruppo.

Il codice client deve anche essere aggiornato per indicare che l'applicazione Contoso Pizza è un'app WebAssembly Blazor. È possibile usare JavaScript SDK o .NET Client SDK. Si sostituirà la funzionalità di polling sul lato client con il codice che compila un oggetto HubConnection e quindi si avvierà la connessione al server. Una volta passato alla pagina di monitoraggio dell'ordine, il codice dovrà unirsi al gruppo specifico dell'ordine a cui verranno inviati gli aggiornamenti delle modifiche. Si sottoscriverà l'evento per le modifiche dello stato dell'ordine e quindi gestirlo di conseguenza.