In un precedente articolo (https://www.aspitalia.com/articoli/asp.net-core/anteprima-aspnet-core-2-1-parte-2-p-2.aspx) abbiamo visto come usare ASP.NET Core SignalR per scambiare messaggi in tempo reale tra client e server.
Questa tecnologia, che sfrutta WebSockets per il trasporto dei dati, è ideale anche quando vogliamo monitorare da web lo stato di un sistema, come un macchinario industriale o un dispositivo IoT.
SignalR supporta lo scambio di messaggi sia testuali, come i parametri di funzionamento di una macchina, e sia binari, come le immagini catturate da una fotocamera.
In questo esempio vedremo appunto come usare ASP.NET Core SignalR per scambiare messaggi binari. Faremo in modo che l'applicazione, ad intervalli regolari, invii delle immagini ai client connessi. Il risultato che vogliamo ottenere è una pagina web che continui a visualizzare immagini, senza che debba essere ricaricata e senza inviare continue richieste ajax (polling).

Preparare il server
Iniziamo installando il seguente pacchetto NuGet che serve ad aggiungere il supporto a MessagePack.dotnet add package Microsoft.AspNetCore.SignalR.Protocols.MessagePack
MessagePack, documentato all'indirizzo https://msgpack.org/, è un formato di serializzazione dei dati che somiglia al JSON ma che, a differenza del JSON, è molto più compatto e supporta anche dati binari senza che debbano essere codificati in Base64.

Grazie al pacchetto che abbiamo installato, ASP.NET Core SignalR si arricchisce di un protocollo di comunicazione che sfrutta MessagePack per ottimizzare la quantità di dati trasferiti tra server e client.
Il prossimo passo consiste nel creare un hub di ASP.NET Core SignalR che useremo per inviare le immagini da server a client. Creiamo dunque un file di codice Hubs/ImageStreamHub.cs e inseriamo al suo interno questa classe.
public class ImageStreamHub : Hub<IImageStreamClient> { //Per questo esempio, qui non è necessario inserire nulla }
Come si vede, questo hub deriva dalla classe base Hub
public interface IImageStreamClient { Task ReceiveImage(byte[] image); }
Questa interfaccia definisce il metodo ReceiveImage che invocheremo lato server per inviare immagini al client. Come si nota, il suo paramento è di tipo byte[] che è idoneo per il contenuto binario di un'immagine.
Registrare i servizi di ASP.NET Core SignalR
A questo punto abbiamo preparato tutto il necessario e dobbiamo semplicemente registrare i servizi di ASP.NET Core SignalR. Quindi andiamo nel metodo ConfigureServices della classe Startup e aggiungiamo la seguente istruzione.//Mettiamo questa riga in un qualsiasi punto nel metodo ConfigureServices services.AddSignalR().AddMessagePackProtocol();
Come si vede, usando il metodo AddMessagePackProtocol abbiamo indicato di voler usare il protocollo di comunicazione basato su MessagePack.
Ora andiamo nel metodo Configure della classe Startup per usare il middleware di ASP.NET Core SignalR e indicare l'indirizzo a cui il client potrà collegarsi al nostro hub.
//Aggiungiamo questa riga prima di app.UseMvc app.UseSignalR((configure) => { configure.MapHub<ImageStreamHub>("/image-stream", options => { //Limite di peso dell'immagine da inviare al client options.ApplicationMaxBufferSize = 256 * 1024; //256KB }); });
In questo punto è anche importante valorizzare l'opzione ApplicationMaxBufferSize per indicare il peso massimo che un'immagine può assumere.
Inviare immagini al client
Gli hub di ASP.NET Core SignalR sono ben integrati con la dependency injection di ASP.NET Core e quindi, nei componenti della nostra applicazione, possiamo ricevere il servizio IHubContextpublic class ImageGenerator : BackgroundService { private readonly IHubContext<ImageStreamHub, IImageStreamClient> hubContext; //Riceviamo il servizio IHubContext<THub, T> nel costruttore public ImageGenerator(IHubContext<ImageStreamHub, IImageStreamClient> hubContext) { this.hubContext = hubContext; } protected override async Task ExecuteAsync(CancellationToken stoppingToken) { //Questo hosted service invia ai client un'immagine ogni secondo //finché l'applicazione non viene arrestata while(!stoppingToken.IsCancellationRequested) { byte[] imageData = GetImageData(); //Possiamo inviare un messaggio ai client in maniera fortemente tipizzata //invocando il metodo ReceiveImage che avevamo definito nell'interfaccia await hubContext.Clients.All.ReceiveImage(imageData); //Attendiamo un secondo e poi il ciclo ricomincia await Task.Delay(1000, stoppingToken); } } private byte[] GetImageData() { //TODO: Qui logica per leggere il contenuto dell'immagine //ad esempio da una cartella in cui la webcam la salva } }
Per chiarimenti sugli hosted service, si veda un precedente script all'indirizzo https://www.aspitalia.com/script/1276/Operazioni-Background-Hosted-Service-ASP.NET-Core.aspx
Se usiamo un hosted service, ricordiamoci di registrarlo dal metodo ConfigureServices della classe Startup.
services.AddHostedService<ImageGenerator>();
Nel prossimo script...
Per ora abbiamo solo visto come preparare la parte server dell'applicazione ASP.NET Core. Nel prossimo script vedremo quale codice JavaScript usare nella parte client per ricevere e visualizzare le immagini inviate dal server.Il codice dell'applicazione dimostrativa è già pubblicato nel repository GitHub https://github.com/aspitalia/aspnetcore-signalr-binary
Commenti
Per inserire un commento, devi avere un account.
Fai il login e torna a questa pagina, oppure registrati alla nostra community.
Approfondimenti
Potenziare la ricerca su Cosmos DB con Full Text Search
Utilizzare un numero per gestire la concorrenza ottimistica con SQL Server ed Entity Framework
Implementare l'infinite scroll con QuickGrid in Blazor Server
Utilizzare il metodo CountBy di LINQ per semplificare raggruppamenti e i conteggi
Generare velocemente pagine CRUD in Blazor con QuickGrid
Migliorare i tempi di risposta di GPT tramite lo streaming endpoint in ASP.NET Core
Inference di dati strutturati da testo con Semantic Kernel e ASP.NET Core Web API
Evitare (o ridurre) il repo-jacking sulle GitHub Actions
Applicare un filtro per recuperare alcune issue di GitHub
Combinare Container Queries e Media Queries
Creare una libreria CSS universale: Nav menu
Collegare applicazioni server e client con .NET Aspire