Nello scorso script (https://www.aspitalia.com/script/1458/Effettuare-Stream-Risposta-ASP.NET-Core-Tramite-IAsyncEnumerable.aspx) abbiamo visto come, tramite IAsyncEnumerable, possiamo creare un endpoint con supporto allo streaming in ASP.NET Core.
Ma come sfruttare una simile funzionalità dal client, per esempio in Blazor, per rendere più veloce e "responsive" il caricamento dei dati?
Diamo un'occhiata alla classica pagina FetchData.razor, che invoca una chiamata in Get e visualizza il risultato in una tabella. Se provassimo a chiamare l'endpoint che abbiamo creato nello script precedente, vedremmo Blazor attendere il completamento dell'intera risposta prima di mostrare il risultato sullo schermo.
Per poter sfruttare lo streaming, possiamo però creare un extension method di HttpClient che effettui una richiesta in maniera leggermente differente:
public static class HttpExtensions { public async static IAsyncEnumerable<T> GetAsyncEnumerable<T>(this HttpClient http, string url) { using var request = new HttpRequestMessage(HttpMethod.Get, url); // abilitiamo lo streaming request.SetBrowserResponseStreamingEnabled(true); // configuriamo il completamento della risposta alla ricezione // dell'header using var response = await http.SendAsync(request, HttpCompletionOption.ResponseHeadersRead); response.EnsureSuccessStatusCode(); using var responseStream = await response.Content.ReadAsStreamAsync(); IAsyncEnumerable<T> items = JsonSerializer.DeserializeAsyncEnumerable<T>(responseStream, new JsonSerializerOptions { PropertyNameCaseInsensitive = true, DefaultBufferSize = 128 }); await foreach (T item in items) { yield return item; } } }
Il nostro metodo generico GetAsyncEnumerable<T> restituisce un IAsyncEnumerable del tipo specificato. Al suo interno, come prima cosa, dobbiamo configurare HttpClient per attivare lo streaming del browser. A questo punto possiamo inviare la richiesta, indicando che vogliamo ottenere la risposta immediatamente dopo aver letto l'header (per default il metodo aspetta la ricezione dell'intero content, che invece è proprio ciò che vogliamo evitare).
Una volta che abbiamo creato il ResponseStream, possiamo sfruttare una nuova funzionalità di JsonSerializer che permette di deserializzare "al volo" uno stream ancora incompleto in un IAsyncEnumerable.
In questo modo, non dobbiamo far altro che iterare su quest'ultimo, e restituire gli elementi man mano che diventano disponibili.
Grazie a questo metodo, possiamo modificare il codice in FetchData.razor in questo modo:
private List<WeatherForecast>? forecasts; protected override async Task OnInitializedAsync() { var results = Http.GetAsyncEnumerable<WeatherForecast>("https://localhost:7127/weatherforecast"); forecasts = new List<WeatherForecast>(); await foreach (WeatherForecast item in results) { forecasts.Add(item); this.StateHasChanged(); } }
Qui, come possiamo notare, non dobbiamo far altro che aggiornare la lista di WeatherForecast aggiungendo i nuovi elementi quando vengono letti, e invocare StateHasChanged per ognuno di essi così da rigenerare l'HTML della pagina, e vedere quindi la tabella popolarsi gradualmente man mano che il server ci invia i dati.
Commenti
Per inserire un commento, devi avere un account.
Fai il login e torna a questa pagina, oppure registrati alla nostra community.
Approfondimenti
Miglioramenti nelle performance di Angular 16
Proteggere le risorse Azure con private link e private endpoints
Effettuare il refresh dei dati di una QuickGrid di Blazor
Esporre i propri servizi applicativi con Semantic Kernel e ASP.NET Web API
Utilizzare un numero per gestire la concorrenza ottimistica con SQL Server ed Entity Framework
Bloccare l'esecuzione di un pod in mancanza di un'artifact attestation di GitHub
Gestire eccezioni nei plugin di Semantic Kernel in ASP.NET Core Web API
Gestione dei nomi con le regole @layer in CSS
Modificare i metadati nell'head dell'HTML di una Blazor Web App
Recuperare App Service cancellati su Azure
Gestione degli stili CSS con le regole @layer
Usare i servizi di Azure OpenAI e ChatGPT in ASP.NET Core con Semantic Kernel