In un precedente script abbiamo visto come, usando Blazor Server, si possa aggiornare la UI a seguito di un evento di navigazione (https://www.aspitalia.com/script/1354/Paginare-Elenco-Blazor-Server.aspx). Questa tecnica può essere estesa a tutti i tipi di evento sollevati dai componenti della nostra applicazione, così che possiamo notificarli al client in tempo reale. Vediamo l'esempio di un servizio che solleva eventi ad intervalli regolari.
Creare un servizio di notifica messaggi
Iniziamo defininendo un'interfaccia IMessageNotifier che espone un evento MessageArrived.public interface IMessageNotifier { event EventHandler<string> MessageArrived; }
Creiamo una classe Worker che implementa l'interfaccia e solleva l'evento una volta al secondo. Questa classe è un Hosted Service, ovvero un servizio idoneo a eseguire delle operazioni in background, così come mostrato in un precedente script (https://www.aspitalia.com/script/1276/Operazioni-Background-Hosted-Service-ASP.NET-Core.aspx).
public class Worker : BackgroundService, IMessageNotifier { public event EventHandler<string> MessageArrived; protected override async Task ExecuteAsync(CancellationToken stoppingToken) { while (!stoppingToken.IsCancellationRequested) { //Questo worker genera un messaggio che riporta la data e l'ora corrente string message = $"Message sent at {DateTime.Now}"; //Solleviamo l'evento per notificare il messaggio ai sottoscrittori MessageArrived?.Invoke(this, message); //E infine attende un secondo prima di generare il successivo messaggio await Task.Delay(1000, stoppingToken); } } }
Adesso registriamo la classe Worker per la dependency injection: facciamo in modo che venga registrata sia come Hosted Service che come implementazione concreta del servizio IMessageNotifier. Inseriamo quanto segue nel metodo ConfigureServices della classe Startup.
services.AddSingleton<Worker>(); services.AddSingleton<IMessageNotifier>(serviceProvider => serviceProvider.GetService<Worker>()); services.AddHostedService(serviceProvider => serviceProvider.GetService<Worker>());
Ora è tutto pronto e possiamo passare alla realizzazione del Razor Component che sottoscrive l'evento.
Visualizzare gli eventi in un Razor Component
In un'applicazione Blazor Server, il client è sempre connesso all'applicazione grazie a una connessione persistente e bidirezionale basata su WebSockets, che può essere sfruttata dal server per inviare messaggi. Vediamo quindi l'esempio di un Razor Component che visualizza tali messaggi in tempo reale.@page "/messages" @inject IMessageNotifier notifier @implements IDisposable <h1>Messages</h1> <ul> @foreach (var message in messages) { <li>@message</li> } </ul> @code { //Questa lista contiene l'elenco dei messaggi ricevuti private List<string> messages = new List<string>(); protected override void OnInitialized() { //Ad inizializzazione avvenuta, sottoscriviamo la ricezione di eventi notifier.MessageArrived += DisplayMessage; } private void DisplayMessage(object sender, string message) { //Usiamo InvokeAsync per far eseguire questo codice //al thread del renderer, altrimenti avremmo un'eccezione InvokeAsync(() => { //Aggiungiamo il messaggio in cima alla lista messages.Insert(0, message); //E rimuoviamo quelli in eccesso, così da non visualizzarne troppi while (messages.Count > 50) { messages.RemoveAt(50); } //Segnaliamo che lo stato è cambiato StateHasChanged(); }); } public void Dispose() { //Rimuoviamo la sottoscrizione quando //il Razor Component non serve più notifier.MessageArrived -= DisplayMessage; } }
Come si vede nell'esempio, riceviamo un riferimento al servizio IMessageNotifier per mezzo della direttiva @inject. Inoltre, è importante aggiungere la direttiva @implements IDisposable e definire il metodo Dispose per rimuovere la sottoscrizione all'evento MessageArrived. In questo modo il Razor Component potrà essere deallocato correttamente dal Gargabe Collector quando non serve più.
Visualizzare i messaggi su richiesta dell'utente
Se vogliamo consentire all'utente di interrompere e riprendere la visualizzazione dei messaggi, possiamo aggiungere una checkbox come la seguente.<input type="checkbox" id="follow" @bind="followMessages"> <label for="follow">Follow messages</label>
Lo stato di selezione della checkbox verrà messo in binding su un campo privato followMessages di tipo booleano che definiamo nel Razor Component. Nel caso in cui il suo valore sia false, evitiamo che il messaggio venga visualizzato nella UI. Perciò modifichiamo il codice come segue.
//Definiamo il campo privato private bool followMessages = true; private void NotifyMessage(object sender, string message) { //Usciamo precocemente se il suo valore è false if (!followMessages) { return; } //Qui si trova il codice già visto nel precedente esempio }
Avviamo l'applicazione e verifichiamo che la checkbox ci permette, appunto, di interrompere e riprendere il flusso di messaggi che vengono visualizzati ogni secondo.
Commenti
Per inserire un commento, devi avere un account.
Fai il login e torna a questa pagina, oppure registrati alla nostra community.
Approfondimenti
Effettuare il binding di date in Blazor
Aggiungere interattività lato server in Blazor 8
Gestire domini wildcard in Azure Container Apps
Gestire i dati con Azure Cosmos DB Data Explorer
Gestione dei nomi con le regole @layer in CSS
Configurare il nome della run di un workflow di GitHub in base al contesto di esecuzione
Effettuare il log delle chiamate a function di GPT in ASP.NET Web API
Aggiornare a .NET 9 su Azure App Service
Eseguire query manipolando le liste contenute in un oggetto mappato verso una colonna JSON
Triggerare una pipeline su un altro repository di Azure DevOps
Gestire la cancellazione di una richiesta in streaming da Blazor
Gestire gli accessi con Token su Azure Container Registry