
Le visualiseur est sans état — Comment créer un point d’accès ouvert minimal .NET 8
Le visualiseur est sans état — par conception
Viewer ne conserve aucune donnée de document par requête. C’est une classe scellée, elle n’implémente jamais IDisposable, et chaque document que vous ouvrez vit dans une session séparée que le cache du framework gère. À cause de cela, vous pouvez injecter une seule instance Viewer n’importe où dans votre application ASP.NET Core et l’appeler en toute sécurité depuis de nombreuses requêtes concurrentes.
Conséquences d’un service sans état
- Pas de ressources cachées – le service lui‑même n’alloue jamais de gros tampons qui nécessitent un nettoyage explicite.
- Thread‑safe par défaut – parce qu’aucun état spécifique à la requête n’est stocké, la même instance
Viewerpeut être utilisée par plusieurs threads sans verrouillage. - Déploiements évolutifs – la mise à l’échelle horizontale fonctionne immédiatement ; vous n’avez pas besoin de sessions persistantes ou d’affinité serveur, seulement le jeton de session que le client détient.
Toutes les informations spécifiques au document (pages, annotations, index de recherche) sont conservées dans une session créée par OpenDocumentAsync. La session est stockée dans IMemoryCache (ou tout IDistributedCache que vous configurez) et expire automatiquement après une période d’inactivité (60 minutes par défaut). Lorsque vous avez terminé, vous pouvez appeler CloseDocument pour libérer l’entrée du cache plus tôt.
Enregistrement du visualiseur sans état
Parce que Viewer n’a aucun état mutable, enregistrez‑le une fois au démarrage :
builder.Services.AddDoconut(); // enregistre Viewer et le middleware requis
builder.Services.AddSession(); // requis pour la sécurité du token
builder.Services.AddDistributedMemoryCache(); // cache simple pour la démo
L’appel AddDoconut connecte également le middleware qui sert les ressources statiques du visualiseur. Une fois les services en place, vous pouvez demander Viewer dans la signature de n’importe quel point d’accès.
Point d’accès minimal d’ouverture de document (exemple net‑8)
Le code suivant est le fragment exact de la documentation officielle et fonctionne immédiatement dans un projet .NET 8 minimal‑API :
app.MapPost("/api/open", async (string fileName, Viewer viewer) =>
{
var token = await viewer.OpenDocumentAsync($"files/{fileName}");
return Results.Content(token, "text/plain");
});
Ce que fait le code
- Accepte un nom de fichier – le client indique au serveur quel fichier sous
wwwroot/filesouvrir. - Appelle
OpenDocumentAsync– leViewersans état crée une nouvelle session, la stocke dans le cache et renvoie un jeton opaque. - Renvoie le jeton en texte brut – le client ne reçoit que le jeton ; le serveur n’envoie jamais les octets du document dans cette réponse.
Parce que Viewer ne conserve aucune donnée de document, le point d’accès n’a pas besoin de blocs using, d’appels Dispose, ou de fabriques par requête. Le jeton est la seule crédential que le client enverra jamais au widget du visualiseur (objViewer.View(token) sur le front‑end).
Utilisation du jeton côté client
Après que le jeton a été renvoyé, le widget du front‑end appelle objViewer.View(token). Le widget inclut alors le même jeton avec chaque requête ultérieure pour les images de pages, la recherche ou les actions d’annotation. Le serveur valide le jeton par rapport à la session qui a initialement ouvert le document. Si le jeton est présenté depuis une session de navigateur différente, le visualiseur renvoie une erreur d’autorisation, ce qui correspond au comportement de sécurité prévu.
Clôture d’une session tôt (optionnel)
Si votre flux de travail sait qu’un document ne sera plus jamais accédé, vous pouvez libérer l’entrée du cache en invoquant CloseDocument sur le Viewer. Cela supprime la session du cache et empêche le minuteur d’expiration glissante de la maintenir en vie.
Récapitulatif du flux sans état
| Étape | Ce qui se passe | Où l’état réside |
|---|---|---|
| Injecter le visualiseur | Une seule instance Viewer est créée au démarrage. | Dans le conteneur DI (singleton). |
| OpenDocumentAsync | Licence vérifiée → session créée → jeton renvoyé. | Session stockée dans IMemoryCache (ou cache distribué). |
| Le client rend | Le widget envoie le jeton avec chaque requête. | Le jeton est la seule donnée par document que le client détient. |
| Expiration de session / CloseDocument | Entrée du cache supprimée après expiration ou fermeture explicite. | Aucune ressource persistante dans le service du visualiseur. |
Parce que le service lui‑même ne stocke jamais de données de document, vous pouvez mettre à l’échelle votre ferme web en toute sécurité, remplacer des nœuds ou redémarrer l’application sans perdre d’état visible par l’utilisateur — seul le jeton devient invalide, incitant le client à rouvrir le document.
Déploiement du visualiseur sans état dans votre application
- Ajoutez
AddDoconut,AddSessionet un fournisseur de cache àProgram.cs. - Collez le fragment du point d’accès ouvert dans votre configuration minimal‑API.
- Transmettez le jeton renvoyé à
objViewer.View(token)sur le front‑end.
Vous disposez maintenant d’une API d’ouverture de document entièrement sans état, prête pour la production, qui exploite la conception Viewer de Doconut.