In uno script precedente (https://www.aspitalia.com/script/1459/Sfruttare-Streaming-Chiamata-HTTP-Blazor.aspx) ci siamo occupati del concetto di streaming tra Blazor e ASP.NET Core, e abbiamo visto come può essere una soluzione molto interessante quando si tratta di inviare corpose moli di dati dal server al client.
Tuttavia, in questi contesti, vogliamo anche supportare la cancellazione della richiesta. Immaginiamo per esempio, di trovarci sulla pagina che invia la richiesta HTTP in streaming. Nel momento in cui navighiamo via dalla pagina corrente, se proviamo a guardare il network inspector del browser, noteremo un comportamento inaspettato: la richiesta HTTP, non essendo ancora terminata, continuerà a funzionare in background, usando risorse sia sul server che sul client per un risultato che non verrà mai visualizzato all'utente.
Si tratta di un comportamento poco corretto, e il modo per evitarlo è quello di sfruttare un CancellationToken. Il primo passo è ovviamente quello di aggiungere questa funzionalità al nostro extension method GetAsyncEnumerable:
public static class HttpExtensions { public async static IAsyncEnumerable<T> GetAsyncEnumerable<T>(this HttpClient http, string url, CancellationToken token = default) // <-- cancellation token passato dall'esterno { using var request = new HttpRequestMessage(HttpMethod.Get, url); request.SetBrowserResponseStreamingEnabled(true); // passiamo il cancellation token alla richiesta... using var response = await http.SendAsync(request, HttpCompletionOption.ResponseHeadersRead, token)); response.EnsureSuccessStatusCode(); // ... alla lettura dello stream ... using var responseStream = await response.Content.ReadAsStreamAsync(token); // ... e alla sua deserializzazione ... IAsyncEnumerable<T> items = JsonSerializer.DeserializeAsyncEnumerable<T>(responseStream, new JsonSerializerOptions { PropertyNameCaseInsensitive = true, DefaultBufferSize = 128 }); await foreach (T item in items) { yield return item; } } }
Come possiamo notare, tutto ciò che dobbiamo fare è aggiungere un parametro di tipo CancellationToken e passarlo ai vari statement asincroni che dobbiamo eseguire.
A questo punto, dobbiamo fare in modo che venga invocato quando navighiamo via dalla pagina corrente. La soluzione è implementare l'interfaccia IDisposable come mostrato in basso:
@page "/fetchdata" @implements IDisposable ... altro codice qui ... @code { private CancellationTokenSource _cts = new(); // .. altro codice qui .. protected override async Task OnInitializedAsync() { var results = Http.GetAsyncEnumerable<WeatherForecast>("https://localhost...", _cts.Token); // ... altro codice qui ... } public void Dispose() { _cts.Cancel(); } }
La pagina contiene un field di tipo CancellationTokenSource, che usiamo per inviare il token alla chiamata GetAsyncEnumerable. Nel metodo Dispose, ne invochiamo il Cancel, così da segnalare che non è più necessario proseguire nella richiesta. Questo farà sì che la chiamata HTTP venga correttamente terminata, sia sul client, sia sul server, visto che ASP.NET Core gestisce automaticamente la cancellazione della richiesta terminandone l'esecuzione.
Commenti
Per inserire un commento, devi avere un account.
Fai il login e torna a questa pagina, oppure registrati alla nostra community.
Approfondimenti
Usare il colore CSS per migliorare lo stile della pagina
Filtering sulle colonne in una QuickGrid di Blazor
Aprire una finestra di dialogo per selezionare una directory in WPF e .NET 8
Sostituire la GitHub Action di login su private registry
Simulare Azure Cosmos DB in locale con Docker
Creare un webhook in Azure DevOps
Usare le navigation property in QuickGrid di Blazor
Introduzione alle Container Queries
Migliorare i tempi di risposta di GPT tramite lo streaming endpoint in ASP.NET Core
Persistere la ChatHistory di Semantic Kernel in ASP.NET Core Web API per GPT
La gestione della riconnessione al server di Blazor in .NET 9
Utilizzare una qualunque lista per i parametri di tipo params in C#