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
Effettuare il refresh dei dati di una QuickGrid di Blazor
Inference di dati strutturati da testo con Semantic Kernel e ASP.NET Core Web API
Gestione dei nomi con le regole @layer in CSS
Utilizzare QuickGrid di Blazor con Entity Framework
Estrarre dati randomici da una lista di oggetti in C#
Applicare un filtro per recuperare alcune issue di GitHub
Aggiornare a .NET 9 su Azure App Service
Paginare i risultati con QuickGrid in Blazor
Triggerare una pipeline su un altro repository di Azure DevOps
Utilizzare il metodo ExceptBy per eseguire operazione di sottrazione tra liste
Gestire il colore CSS con HWB