
Ο Viewer είναι χωρίς‑κατάσταση — Πώς να δημιουργήσετε ένα ελάχιστο .NET 8 Open Endpoint
Ο Viewer είναι χωρίς‑κατάσταση — από Σχεδίαση
Viewer δεν διατηρεί κανένα δεδομένο εγγράφου ανά αίτηση. Είναι μια κλειστή κλάση, δεν υλοποιεί ποτέ IDisposable, και κάθε έγγραφο που ανοίγετε ζει σε ξεχωριστή συνεδρία που διαχειρίζεται η κρυφή μνήμη του πλαισίου. Για αυτό μπορείτε να ενσωματώσετε ένα μόνο στιγμιότυπο του Viewer οπουδήποτε στην εφαρμογή ASP.NET Core και να το καλέσετε με ασφάλεια από πολλές ταυτόχρονες αιτήσεις.
Συνεπακόλουθα μιας υπηρεσίας χωρίς‑κατάσταση
- Καμία κρυφή πόροι – η υπηρεσία καθόλου δεν εκχωρεί μεγάλους buffer που χρειάζονται ρητή εκκαθάριση.
- Ασφαλές‑νήμα από προεπιλογή – επειδή δεν αποθηκεύεται κατάσταση ειδική για αίτηση, το ίδιο στιγμιότυπο του
Viewerμπορεί να χρησιμοποιηθεί από πολλαπλά νήματα χωρίς κλείδωμα. - Κλιμακώσιμες αναπτύξεις – η οριζόντια κλιμάκωση λειτουργεί αμέσως· δεν χρειάζεστε sticky sessions ή προτίμηση διακομιστή, μόνο το token συνεδρίας που κρατά ο πελάτης.
Όλες οι πληροφορίες ειδικές για το έγγραφο (σελίδες, σημειώσεις, ευρετήριο αναζήτησης) διατηρούνται σε μια συνεδρία που δημιουργείται από OpenDocumentAsync. Η συνεδρία αποθηκεύεται σε IMemoryCache (ή σε οποιοδήποτε IDistributedCache ρυθμίζετε) και λήγει αυτόματα μετά από μια περίοδο αδράνειας (προεπιλογή 60 λεπτά). Όταν τελειώσετε, μπορείτε να καλέσετε CloseDocument για να ελευθερώσετε νωρίς την καταχώρηση της κρυφής μνήμης.
Καταχώρηση του Viewer χωρίς‑κατάσταση
Επειδή το Viewer δεν έχει μεταβλητή κατάσταση, καταχωρήστε το μία φορά κατά την εκκίνηση:
builder.Services.AddDoconut(); // καταχωρεί το Viewer και το απαιτούμενο middleware
builder.Services.AddSession(); // απαιτείται για την ασφάλεια του token
builder.Services.AddDistributedMemoryCache(); // απλό cache για το demo
Η κλήση AddDoconut επίσης συνδέει το middleware που εξυπηρετεί τους στατικούς πόρους του viewer. Μετά την εγκατάσταση των υπηρεσιών, μπορείτε να ζητήσετε Viewer σε οποιαδήποτε υπογραφή endpoint.
Ελάχιστο endpoint ανοίγματος εγγράφου (παράδειγμα net‑8)
Ο παρακάτω κώδικας είναι το ακριβές απόσπασμα από την επίσημη τεκμηρίωση και λειτουργεί αμέσως σε ένα έργο .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");
});
Τι κάνει ο κώδικας
- Δέχεται ένα όνομα αρχείου – ο πελάτης λέει στον διακομιστή ποιο αρχείο κάτω από
wwwroot/filesνα ανοίξει. - Καλεί
OpenDocumentAsync– ο χωρίς‑κατάστασηViewerδημιουργεί μια νέα συνεδρία, την αποθηκεύει στην κρυφή μνήμη και επιστρέφει ένα αδιαφανές token. - Επιστρέφει το token ως απλό κείμενο – ο πελάτης λαμβάνει μόνο το token· ο διακομιστής ποτέ δεν στέλνει τα bytes του εγγράφου σε αυτήν την απάντηση.
Επειδή το Viewer δεν κρατά δεδομένα εγγράφου, το endpoint δεν χρειάζεται μπλοκ using, κλήσεις Dispose, ή εργοστάσια ανά αίτηση. Το token είναι το μοναδικό διαπιστευτήριο που ο πελάτης θα στείλει ποτέ πίσω στο widget του viewer (objViewer.View(token) στο front‑end).
Χρήση του token στην πλευρά του πελάτη
Αφού επιστραφεί το token, το widget του front‑end καλεί objViewer.View(token). Το widget στη συνέχεια περιλαμβάνει το ίδιο token σε κάθε επόμενη αίτηση για εικόνες σελίδων, αναζήτηση ή ενέργειες σημειώσεων. Ο διακομιστής επικυρώνει το token έναντι της συνεδρίας που αρχικά άνοιξε το έγγραφο. Εάν το token παρουσιαστεί από διαφορετική συνεδρία προγράμματος περιήγησης, ο viewer επιστρέφει σφάλμα εξουσιοδότησης, που είναι η προγραμματισμένη συμπεριφορά ασφαλείας.
Κλείσιμο μιας συνεδρίας νωρίς (προαιρετικό)
Εάν η ροή εργασίας σας γνωρίζει ότι ένα έγγραφο δεν θα προσπελαστεί ξανά, μπορείτε να ελευθερώσετε την καταχώρηση της κρυφής μνήμης καλώντας CloseDocument στο Viewer. Αυτό αφαιρεί τη συνεδρία από την κρυφή μνήμη και αποτρέπει το χρονόμετρο κυλιόμενης λήξης από το να τη διατηρεί ζωντανή.
Ανακεφαλαίωση της ροής χωρίς‑κατάσταση
| Βήμα | Τι συμβαίνει | Πού ζει η κατάσταση |
|---|---|---|
| Ενσωμάτωση Viewer | Ένα μόνο στιγμιότυπο του Viewer δημιουργείται κατά την εκκίνηση. | Στο DI container (singleton). |
| OpenDocumentAsync | Έλεγχος άδειας → δημιουργία συνεδρίας → επιστροφή token. | Η συνεδρία αποθηκεύεται σε IMemoryCache (ή κατανεμημένη κρυφή μνήμη). |
| Ο πελάτης αποδίδει | Το widget στέλνει το token με κάθε αίτηση. | Το token είναι το μοναδικό δεδομένο ανά έγγραφο που κρατά ο πελάτης. |
| Λήξη συνεδρίας / CloseDocument | Η καταχώρηση της κρυφής μνήμης αφαιρείται μετά από λήξη χρόνου ή ρητό κλείσιμο. | Καμία παραμένοσα πόροι στην υπηρεσία Viewer. |
Επειδή η υπηρεσία δεν αποθηκεύει δεδομένα εγγράφου, μπορείτε με ασφάλεια να κλιμακώσετε το web farm σας, να αντικαταστήσετε κόμβους ή να επανεκκινήσετε την εφαρμογή χωρίς να χάσετε καμία ορατή κατάσταση χρήστη—μόνο το token γίνεται άκυρο, προκαλώντας τον πελάτη να ανοίξει ξανά το έγγραφο.
Ανάπτυξη του Viewer χωρίς‑κατάσταση στην εφαρμογή σας
- Προσθέστε
AddDoconut,AddSession, και έναν πάροχο κρυφής μνήμης στοProgram.cs. - Επικολλήστε το απόσπασμα του open‑endpoint στη διαμόρφωση του minimal‑API.
- Μεταβιβάστε το επιστρεφόμενο token στο
objViewer.View(token)στο front‑end.
Τώρα έχετε ένα πλήρως χωρίς‑κατάσταση, έτοιμο για παραγωγή API ανοίγματος εγγράφου που αξιοποιεί το σχεδιασμό Viewer της Doconut.