Viewer è senza stato — Come creare un endpoint aperto minimale .NET 8
← Back to Blog••4 min read

Viewer è senza stato — Come creare un endpoint aperto minimale .NET 8

Viewer è senza stato — per design

Viewer non conserva alcun dato di documento per richiesta. È una classe sealed, non implementa mai IDisposable, e ogni documento che apri vive in una sessione separata gestita dalla cache del framework. Per questo puoi iniettare una singola istanza Viewer ovunque nella tua app ASP.NET Core e chiamarla in sicurezza da molte richieste concorrenti.


Conseguenze di un servizio senza stato

  • Nessuna risorsa nascosta – il servizio stesso non alloca mai grandi buffer che richiedono una pulizia esplicita.
  • Thread‑safe per impostazione predefinita – poiché non viene memorizzato alcuno stato specifico della richiesta, la stessa istanza Viewer può essere usata da più thread senza blocchi.
  • Distribuzioni scalabili – il ridimensionamento orizzontale funziona subito; non hai bisogno di sessioni sticky o affinità del server, solo del token di sessione che il client possiede.

Tutte le informazioni specifiche del documento (pagine, annotazioni, indice di ricerca) sono conservate in una sessione creata da OpenDocumentAsync. La sessione è memorizzata in IMemoryCache (o in qualsiasi IDistributedCache tu configuri) e scade automaticamente dopo un periodo di inattività (predefinito 60 minuti). Quando hai finito puoi chiamare CloseDocument per liberare l'entry della cache in anticipo.


Registrazione del Viewer senza stato

Poiché Viewer non ha stato mutabile, registralo una sola volta durante l'avvio:

builder.Services.AddDoconut();               // registra Viewer e il middleware richiesto
builder.Services.AddSession();               // necessario per la sicurezza del token
builder.Services.AddDistributedMemoryCache(); // cache semplice per la demo

La chiamata AddDoconut collega anche il middleware che serve le risorse statiche del viewer. Dopo che i servizi sono in posizione puoi richiedere Viewer in qualsiasi firma di endpoint.


Endpoint minimale di apertura documento (esempio net‑8)

Il codice seguente è lo snippet esatto dalla documentazione ufficiale e funziona subito in un progetto .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");
});

Cosa fa il codice

  1. Accetta un nome file – il client indica al server quale file sotto wwwroot/files aprire.
  2. Chiama OpenDocumentAsync – il Viewer senza stato crea una nuova sessione, la memorizza nella cache e restituisce un token opaco.
  3. Restituisce il token come testo semplice – il client riceve solo il token; il server non invia mai i byte del documento in questa risposta.

Poiché Viewer non contiene dati del documento, l'endpoint non ha bisogno di blocchi using, chiamate Dispose, o factory per‑richiesta. Il token è l'unica credenziale che il client invierà mai al widget del viewer (objViewer.View(token) sul front‑end).


Utilizzo del token sul lato client

Dopo che il token è stato restituito, il widget del front‑end chiama objViewer.View(token). Il widget include quindi lo stesso token in ogni richiesta successiva per immagini di pagina, ricerca o azioni di annotazione. Il server valida il token contro la sessione che ha originariamente aperto il documento. Se il token viene presentato da una sessione browser diversa, il viewer restituisce un errore di autorizzazione, che è il comportamento di sicurezza previsto.


Chiusura anticipata di una sessione (opzionale)

Se il tuo flusso di lavoro sa che un documento non sarà più accessibile, puoi liberare l'entry della cache invocando CloseDocument sul Viewer. Questo rimuove la sessione dalla cache e impedisce al timer di scadenza scorrevole di mantenerla attiva.


Riepilogo del flusso senza stato

PassoCosa succedeDove vive lo stato
Inietta ViewerUna singola istanza Viewer viene creata all'avvio.Nel contenitore DI (singleton).
OpenDocumentAsyncLicenza verificata → sessione creata → token restituito.Sessione memorizzata in IMemoryCache (o cache distribuita).
Il client rendeIl widget invia il token con ogni richiesta.Il token è l'unico dato per‑documento che il client possiede.
Scadenza sessione / CloseDocumentEntry della cache rimossa dopo timeout o chiusura esplicita.Nessuna risorsa residua nel servizio Viewer.

Poiché il servizio stesso non memorizza mai dati del documento, puoi scalare in sicurezza il tuo web farm, sostituire i nodi o riavviare l'applicazione senza perdere alcuno stato visibile all'utente — solo il token diventa invalido, spingendo il client a riaprire il documento.


Distribuzione del Viewer senza stato nella tua app

  1. Aggiungi AddDoconut, AddSession e un provider di cache a Program.cs.
  2. Incolla lo snippet dell'endpoint aperto nella tua configurazione minimal‑API.
  3. Passa il token restituito a objViewer.View(token) sul front‑end.

Ora hai un'API di apertura documento completamente senza stato, pronta per la produzione, che sfrutta il design Viewer di Doconut.

#dotnet8#viewer#stateless#api#doconut#visualizzatore#senza stato