Le applicazioni web moderne, e soprattutto le Progressive Web Application, devono essere in grado di fornire un'esperienza utente di alto livello anche nel caso di rete instabile o addirittura offline. Pertanto avere a disposizione un componente che ci notifichi dello stato della connessione è indispensabile.
Purtroppo una funzionalità del genere è esclusivamente disponibile tramite la Network Information API dei browser, e pertanto non è presente nativamente in Blazor.
Tuttavia, possiamo sfruttare JavaScript interop per creare un componente wrapper, così che sia più semplice utilizzarlo nelle nostre applicazioni.
Innanzi tutto dobbiamo creare una funzione JavaScript che si agganci agli eventi di connessione online/offline del browser:
(function () { window.blazorNetwork = { init: (callback) => { // callback è un puntatore a una classe .NET Core const updateOnlineStatus = (e) => { // invochiamo il metodo UpdateOnlineStatus per segnalare il cambio // di stato della connessione callback.invokeMethodAsync('UpdateOnlineStatus', navigator.onLine); } window.addEventListener('online', updateOnlineStatus); window.addEventListener('offline', updateOnlineStatus); updateOnlineStatus(); } }; })();
L'idea è di inizializzare questa classe passando un parametro callback, che è un reference a un oggetto .NET Core, così che, al cambio dello stato della connnessione, ne possiamo invocare il metodo UpdateOnlineStatus.
L'oggetto invocato come callback sarà il nostro NetworkService, ossia il servizio che vogliamo consumare lato Blazor:
public class NetworkService { private readonly IJSRuntime _jsRuntime; private readonly DotNetObjectReference<NetworkService> _dotNetObjectReference; public NetworkService(IJSRuntime jsRuntime) { _dotNetObjectReference = DotNetObjectReference.Create(this); _jsRuntime = jsRuntime; } public event EventHandler OnlineChanged; public ValueTask InitAsync() { return _jsRuntime.InvokeVoidAsync("blazorNetwork.init", _dotNetObjectReference); } [JSInvokable] public void UpdateOnlineStatus(bool status) { OnOnlineChanged(status); } public bool IsOnline { get; private set; } protected void OnOnlineChanged(bool status) { IsOnline = status; OnlineChanged?.Invoke(this, EventArgs.Empty); } }
Come possiamo notare dal codice in alto, all'interno del costruttore abbiamo creato una DotNetObjectReference che passiamo alla funzione JavaScript init tramite il metodo InitAsync.
In questo modo, ogni volta che avviene un cambio di stato della connessione, il codice JavaScript invocherà il nostro metodo UpdateOnlineStatus, tramite il quale possiamo aggiornare la proprietà IsOnline e sollevare l'evento OnlineChanged.
Visto che è buona norma effettuare il Dispose di una DotNetObjectReference per evitare memory leak, possiamo completare l'implementazione di NetworkService aggiungendo l'interfaccia IDisposable:
public class NetworkService : IDisposable { // ... altro codice qui ... public void Dispose() { _dotNetObjectReference.Dispose(); } }
Per utilizzare quest'oggetto, dobbiamo innanzi tutto ricordarci di aggiungere la reference al file JavaScript in index.html:
<!DOCTYPE html> <html> ... <body> <app>Loading...</app> ... <script src="network.js"></script> </body> </html>
A questo punto possiamo registrare il servizio come Scoped nell'IoC container di Blazor e invocarne l'inizializzazione asincrona con la tecnica che abbiamo descritto in un precedente script (https://www.aspitalia.com/script/1373/Inizializzazione-Asincrona-Servizio-Startup-Applicazione-Blazor.aspx):
public static async Task Main(string[] args) { var builder = WebAssemblyHostBuilder.CreateDefault(args); builder.RootComponents.Add<App>("app"); ... builder.Services.AddScoped<NetworkService>(); var host = builder.Build(); var network = host.Services.GetRequiredService<NetworkService>(); await network.InitAsync(); await host.RunAsync(); }
Ora che tutto è configurato correttamente, possiamo facilmente sfruttare questo servizio all'interno dei nostri componenti, per esempio per mostrare lo stato online/offline dell'applicazione:
@inject NetworkService NetworkService @if (NetworkService.IsOnline) { <span style="color: green">Online</span> } else { <span style="color: red">Offline</span> } @code { protected override void OnInitialized() { base.OnInitialized(); NetworkService.OnlineChanged += (s, e) => InvokeAsync(StateHasChanged); } }
Commenti
Per inserire un commento, devi avere un account.
Fai il login e torna a questa pagina, oppure registrati alla nostra community.
Approfondimenti
Visualizzare le change sul plan di Terraform tramite le GitHub Actions
Cambiare la chiave di partizionamento di Azure Cosmos DB
Creare un'applicazione React e configurare Tailwind CSS
Configurare il nome della run di un workflow di GitHub in base al contesto di esecuzione
Personalizzare l'errore del rate limiting middleware in ASP.NET Core
Usare il colore CSS per migliorare lo stile della pagina
Utilizzare database e servizi con gli add-on di Container App
Hosting di componenti WebAssembly in un'applicazione Blazor static
Sostituire la GitHub Action di login su private registry
Load test di ASP.NET Core con k6
Accesso sicuro ai secrets attraverso i file in Azure Container Apps
Implementare l'infinite scroll con QuickGrid in Blazor Server
I più letti di oggi
- ASP.NET Core Identity 8: è rivoluzione?
- Migliorare i tempi di risposta di GPT tramite lo streaming endpoint in ASP.NET Core
- Migliorare la scalabilità delle Azure Function con il Flex Consumption
- Ordine e importanza per @layer in CSS
- Gestire i dati con Azure Cosmos DB Data Explorer
- .NET Conference Italia 2024 - Milano