ASP.NET Core SignalR è probabilmente una della librerie più popolari nell'ecosistema di ASP.NET Core, visto che consente con grande semplicità di rendere interattive le nostre applicazioni, permettendo al server di inviare messaggi ai client connessi grazie al protocollo WebSockets.
Blazor WebAssembly si integra pienamente con SignalR, così che possiamo connetterci al server e implementare le nostre logiche interamente in C#. Vediamo come.
Creazione dell'Hub lato server
Immaginiamo di avere un'applicazione ASP.NET Core che esponga un semplice Hub, come quello in basso, che permette di ricevere un messaggio e girarlo a tutti i client collegati:
internal class MyHub : Hub { public async Task SendMessageAsync(string message) { await this.Clients.All.SendAsync("messageReceived", message); } }
Un Hub del genere può essere associato a un URL nel metodo Configure della classe Startup:
public void Configure(IApplicationBuilder app, IWebHostEnvironment env) { // altro codice qui... app.UseEndpoints(endpoints => { ... endpoints.MapHub<MyHub>("/hubs/myhub"); }); }
Connessione lato client da Blazor WebAssembly
Per sfruttarlo il nuovo Hub da Blazor, come prima cosa dobbiamo aggiungere il package NuGet Microsoft.AspNetCore.SignalR.Client:
dotnet add package Microsoft.AspNetCore.SignalR.Client
A questo punto, possiamo creare una connessione direttamente da un nostro componente, come nell'esempio in basso:
@page "/" @inject NavigationManager Navigation @implements IAsyncDisposable @using Microsoft.AspNetCore.SignalR.Client @* .... altro codice qui .... *@ @code{ private HubConnection _hubConnection; private List<string> _receivedMessages = new List<string>(); protected override async Task OnInitializedAsync() { base.OnInitialized(); _hubConnection = new HubConnectionBuilder() .WithUrl($"{this.Navigation.BaseUri}hubs/myhub") .Build(); _hubConnection.On<string>("messageReceived", message => { _receivedMessages.Add(message); this.StateHasChanged(); }); await _hubConnection.StartAsync(); } public ValueTask DisposeAsync() { return _hubConnection.DisposeAsync(); } }
All'interno del metodo OnInitializedAsync, creiamo una HubConnection che punti all'URL dell'Hub sul server.
Nel nostro caso, stiamo utilizzando un'applicazione Blazor in hosting sullo stesso sito ASP.NET Core che espone l'Hub, per cui abbiamo recuperato l'indirizzo assoluto tramite il BaseUri di NavigationManager. Ovviamente i concetti rimangono assolutamente gli stessi anche nel caso in cui l'Hub risieda su una API esterna, a patto di avere la corretta configurazione di CORS.
Successivamente agganciamo un handler all'evento messageReceived, per aggiungere il nuovo messaggio ricevuto a una collection di _messages e invalidare lo stato del componente, forzandone un nuovo rendering, con una chiamata a StateHasChanged.
Come ultimo passo abbiamo poi, avviamo la connessione chiamando il metodo StartAsync. Un aspetto di cui dobbiamo tener conto è che essa rimarrà attiva per tutta la durata del ciclo di vita di HubConnection. Implementando l'interfaccia IDisposableAsync sul componente, però, possiamo effettuare il DisposeAsync, così da evitare connection leak.
Inviamo e visualizziamo i messaggi
Ora possiamo finalmente implementare la logica per visualizzare e inviare messaggi. Il markup può essere una semplice lista seguita da una InputBox e un Button:
<div> <ul> @foreach (var message in _receivedMessages) { <li> @message </li> } </ul> </div> <div> <input type="text" @bind="_newMessage" /> <button class="btn btn-primary" @onclick="SendMessageAsync">Send</button> </div>
Il metodo SendMessageAsync invocato al click del button, si occupa di inviare il messaggio all'Hub tramite il codice seguente:
private string _newMessage; private async Task SendMessageAsync() { if (!string.IsNullOrWhiteSpace(_newMessage)) { await _hubConnection.SendAsync("SendMessageAsync", _newMessage); _newMessage = string.Empty; } }
Per verificare se abbiamo svolto tutti i passaggi correttamente, ci basterà avviare l'applicazione in un paio di tab differenti: un messaggio inviato da uno dei due apparirà immediatamente su tutti i client connessi:
Commenti
Per inserire un commento, devi avere un account.
Fai il login e torna a questa pagina, oppure registrati alla nostra community.
Approfondimenti
Ottimizzare il mapping di liste di tipi semplici con Entity Framework Core
Disabilitare automaticamente un workflow di GitHub (parte 2)
Eseguire query manipolando liste di tipi semplici con Entity Framework Core
Effettuare il refresh dei dati di una QuickGrid di Blazor
Filtrare i dati di una QuickGrid in Blazor con una drop down list
Generare velocemente pagine CRUD in Blazor con QuickGrid
Usare un KeyedService di default in ASP.NET Core 8
Installare le Web App site extension tramite una pipeline di Azure DevOps
L'evoluzione di Blazor in .NET 8
Gestire i dati con Azure Cosmos DB Data Explorer
Utilizzare politiche di resiliency con Azure Container App
Sfruttare lo stream rendering per le pagine statiche di Blazor 8