.NET pratique

Utilisation du stockage local dans une application Web progressive Blazor

Grâce à Chris Sainty et Remi Bourgarel, travailler avec le stockage local est relativement facile à partir d’une application Blazor, que ce soit dans le navigateur ou en dehors du navigateur. Tester votre code peut être tout aussi simple, mais uniquement si vous prenez en charge le monde réel des connexions réseau.

Dans une Article précédentJ’ai expliqué comment créer une application Blazor qui peut être installée sur l’ordinateur de l’utilisateur et accessible sans lancer de navigateur Web (une application Web progressive ou PWA). Étant donné que l’application est accessible sans démarrer le navigateur Web, vous pouvez également activer l’exécution de cette application sans connexion réseau. Dans ce cas, vous devrez utiliser le stockage local pour remplacer les données obtenues à partir des services Web.

Accès au stockage local
Heureusement, une fois que vous avez ajouté le package NuGet Blazored.LocalStorage de Chris Sainty à votre application (le projet et sa documentation peuvent être trouvés sur GitHub).

Avant de pouvoir utiliser le package Sainty, vous devez d’abord l’ajouter à la collection de services de votre projet. Je ferais normalement cela dans la classe Startup de mon projet, mais le modèle Visual Studio pour une PWA n’a pas de classe Startup. Ainsi, dans une PWA, vous devez ajouter le package Sainty à la collection de services dans le fichier Program.cs.

Le fichier Program.cs dans le modèle PWA contient déjà du code pour ajouter un HttpClient à la collection Services. Vous pouvez ajouter le package de Sainty en appelant la méthode d’extension AddBlazoredLocalStorage comme ceci:

builder.Services.AddTransient(sp => new HttpClient { 
                             BaseAddress = new Uri(builder.HostEnvironment.BaseAddress)})
                .AddBlazoredLocalStorage();

Vous en avez besoin pour prendre en charge cette méthode d’extension using Déclaration:

using Blazored.LocalStorage;

Après cela, vous devez ajouter l’objet de stockage local de Sainty à votre composant Razor en ajoutant ce code en haut de votre page Razor:

@inject Blazored.LocalStorage.ILocalStorageService ls

Ce code vous donne la version asynchrone de l’API Object. Lorsque vous utilisez ISyncLocalStorageService, vous obtenez une API synchrone. L’API pour les deux est étendue et comprend les méthodes suivantes (ce sont évidemment les méthodes pour l’interface asynchrone):

  • SetItemAsync ()
  • GetItemAsync ()
  • GetItemAsStringAsync
  • RemoveItemAsync ()
  • ClearAsync ()
  • LongueurAsync ()
  • KeyAsync ()
  • Contient KeyAsync ()

L’enregistrement et la récupération d’un objet avec un stockage local peuvent être aussi simples que ce code utilisé pour enregistrer et récupérer un objet client:

Customer cust;
await biStorage.SetItem(cust.CustomerId, cust);
cust = await biStorage.GetItem<Customer>("B456");

Il est facile de vérifier ce qui se trouve dans le stockage local: appuyez sur F12 pour afficher le panneau d’outils du développeur dans le navigateur ou la version PWA de votre application, cliquez sur l’onglet Application (qui peut être sous l’icône pour que le menu de débordement de l’outil soit masqué) et sélectionnez Stockage dans la liste de gauche.

Bien que le code soit simple, j’ai trouvé le débogage de l’application qui en résulte problématique. Si je viens de commencer le débogage de mon application en appuyant sur F5, mon navigateur se bloque sur une page vierge ou à l’invite « Chargement … » de la page Index.html sur laquelle mon application Blazor est activée. Cependant, l’utilisation de Start sans débogage fonctionnait à chaque fois (et de plus, ce n’est pas que le débogueur côté serveur de Visual Studio sera de toute façon d’une grande aide pour votre code).

Déterminez si vous êtes hors ligne (et testez)
Mon problème suivant était de déterminer si mon application était hors ligne et de tester son comportement lorsqu’elle n’était pas connectée. Dans le code JavaScript, je peux utiliser la propriété onLine de l’objet Navigator du navigateur pour déterminer l’état de ma connexion. Sauf, bien sûr, que je souhaite accéder à la propriété onLine via mon code Blazor.

Ma solution implémentée peut sembler trop compliquée, mais je vais vous expliquer pourquoi je l’ai adoptée au fil du temps. Tout d’abord, j’ai défini un champ booléen que j’ai défini pour refléter mon statut en ligne:

private bool onLine = true;

Pour faciliter l’accès à la propriété onLine, j’ai ajouté le package NuGet pour Remi Bourgarel Package BrowserInterop. BrowserInterop fournit un accès activé par Blazor à une variété d’options DOM, y compris l’objet window.Navigator et sa propriété onLine (le package prend également en charge LocalStorage, mais j’ai préféré le package de Chris Sainty).

Pour pouvoir utiliser BrowserInterop, j’ai également dû ajouter cette balise de script à la page Index.html où se trouve mon application Blazor:

<script src="https://visualstudiomagazine.com/articles/2020/09/08/_content/BrowserInterop/scripts.js"></script>

BrowserInterop nécessite également le package d’exécution JavaScript Blazor. J’ai donc ajouté ceci en haut de la page Razor de mon application:

@inject IJSRuntime jsr;

Dans le constructeur de mon application, j’ai utilisé ce code pour obtenir l’objet Navigator et câbler une méthode (OnConnectionStateChanged) qui est appelée lorsque l’état de connexion de mon navigateur change. Après cela, j’ai appelé ma méthode OnConnectionStateChanged et passé l’objet Navigator pour initialiser mon statut en ligne:

WindowNavigator biNavigator;
protected async override Task OnAfterRenderAsync(bool firstRender)    
{
  if (firstRender)
  {
    WindowInterop biWindow = await jsr.Window();
    WindowNavigator biNavigator = await biWindow.Navigator();
    await biNavigator.Connection.OnChange(async () => 
      OnConnectionStateChanged(biNavigator.onLIne));
    OnConnectionStateChanged(biNavigator.Online);
  }
}

Dans ce code, la méthode Window appelée par l’objet JavaScriptRuntime est une autre méthode d’extension et la nécessite using Déclaration:

using BrowserInterop.Extensions;

Dans ma méthode OnConnectionStateChanged, j’ai défini mon champ interne onLine … ce qui conduit à l’une des raisons pour lesquelles j’ai choisi cette approche. Lorsque mon application est passée du mode en ligne au mode hors ligne, j’ai dû prendre des mesures pour prendre en charge le changement qui étaient indépendantes de toute méthode particulière dépendante du réseau. Ma méthode OnConnectionStateChange a fourni un bon endroit pour coller ce code, contrôlé par mon champ onLine. Cette modification peut déclencher des modifications de l’interface utilisateur, j’appelle donc également StateHasChanged dans cette méthode:

protected async ValueTask OnConnectionStateChanged(bool onlineState)
{
  
  if (onLine != onlineState && onLineState)
  {
    // ... code to support switching to online mode ... 
  }
  if (onLine != onlineState && !onLineState)
  {
    // ... code to support switching to offline mode ... 
  }
  if (onLine != onlineState)
  {
    StateHasChanged();
  }
  onLine = onlineState; 
  return await Task.CompletedTask;
}

Cette conception me donne également la possibilité de laisser l’utilisateur basculer entre le mode hors ligne et en ligne – il suffit de câbler un bouton ou un élément de menu en utilisant une méthode comme celle-ci:

protected async void ToggleState()
{
  await OnConnectionStateChanged(!onLine);   
}

Bien que je puisse utiliser les outils de développement pour tester (avec une option sur l’onglet Réseau pour mettre le navigateur en ligne ou hors ligne), un tel bouton est le moyen le plus simple de tester mon code en mode hors ligne.

La réalité s’introduit
Bien que cette conception facilite les tests, la vraie raison pour laquelle je l’ai implémentée est que, en production, je n’utilise pas la propriété onLine de l’objet Navigator pour prendre des décisions sur les appels réseau. La propriété onLine peut signaler correctement que vous êtes connecté. Cependant, vous pouvez avoir une connexion suffisamment mauvaise ou suffisamment lente pour vous mettre efficacement hors ligne.

En production, j’emballe tous mes appels HttpClient (c’est-à-dire tous les endroits où j’ai besoin d’une connexion réseau) dans un objet qui implémente cela Disjoncteur et Répéter Modèle. Cet objet Wrapper regarde ce qui est considéré comme « en ligne » beaucoup plus strictement que l’objet Navigator. En production, j’appelle ma méthode OnConnectionChanged à partir de cet objet pour gérer mon champ onLine.

Et maintenant, grâce à l’écosystème qui se développe autour de Blazor, vous pouvez envisager d’étendre votre PWA pour fournir certaines fonctionnalités si votre utilisateur échoue au lieu de ne pas se connecter.

A propos de l’auteur

Peter Vogel est architecte système et directeur chez PH & V Information Services. PH&V propose des services de conseil complets, de la conception UX à la modélisation d’objets et à la conception de bases de données. Peter tweete à travers ses colonnes VSM avec le hashtag #vogelarticles. Vous pouvez trouver ses articles de blog sur la conception de l’expérience utilisateur sur http://blog.learningtree.com/tag/ui/.



Source link

Recent Posts