
Viewer jest bezstanowy — Jak zbudować minimalny punkt otwarty w .NET 8
Viewer jest bezstanowy — z założenia
Viewer nie przechowuje żadnych danych dokumentu specyficznych dla żądania. Jest to klasa zamknięta, nigdy nie implementuje IDisposable, a każdy otwierany dokument istnieje w osobnej sesji zarządzanej przez pamięć podręczną frameworka. Dzięki temu możesz wstrzyknąć pojedynczą instancję Viewer w dowolnym miejscu aplikacji ASP.NET Core i bezpiecznie wywoływać ją z wielu równoczesnych żądań.
Konsekwencje usługi bezstanowej
- Brak ukrytych zasobów – usługa sama w sobie nigdy nie przydziela dużych buforów, które wymagają jawnego czyszczenia.
- Bezpieczna wątkowo domyślnie – ponieważ nie przechowywany jest stan specyficzny dla żądania, ta sama instancja
Viewermoże być używana przez wiele wątków bez blokad. - Skalowalne wdrożenia – skalowanie poziome działa od razu; nie potrzebujesz przywiązanych sesji ani afinitetu serwera, jedynie tokenu sesji, który trzyma klient.
Wszystkie informacje specyficzne dla dokumentu (strony, adnotacje, indeks wyszukiwania) są przechowywane w sesji tworzonej przez OpenDocumentAsync. Sesja jest zapisywana w IMemoryCache (lub dowolnym IDistributedCache, który skonfigurujesz) i wygasa automatycznie po okresie nieaktywności (domyślnie 60 minut). Gdy skończysz, możesz wywołać CloseDocument, aby wcześniej zwolnić wpis w pamięci podręcznej.
Rejestrowanie bezstanowego Viewera
Ponieważ Viewer nie ma zmiennego stanu, zarejestruj go raz podczas uruchamiania:
builder.Services.AddDoconut(); // rejestruje Viewer i wymaganą warstwę pośredniczącą
builder.Services.AddSession(); // wymagane dla bezpieczeństwa tokenu
builder.Services.AddDistributedMemoryCache(); // prosta pamięć podręczna dla demo
Wywołanie AddDoconut również podłącza middleware, które udostępnia statyczne zasoby Viewera. Po skonfigurowaniu usług możesz żądać Viewer w dowolnym sygnaturze punktu końcowego.
Minimalny punkt otwarcia dokumentu (przykład net‑8)
Poniższy kod jest dokładnym fragmentem z oficjalnej dokumentacji i działa od razu w projekcie .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");
});
Co robi kod
- Akceptuje nazwę pliku – klient informuje serwer, który plik pod
wwwroot/filesma zostać otwarty. - Wywołuje
OpenDocumentAsync– bezstanowyViewertworzy nową sesję, zapisuje ją w pamięci podręcznej i zwraca nieprzezroczysty token. - Zwraca token jako zwykły tekst – klient otrzymuje tylko token; serwer nigdy nie wysyła bajtów dokumentu w tej odpowiedzi.
Ponieważ Viewer nie przechowuje danych dokumentu, punkt końcowy nie potrzebuje bloków using, wywołań Dispose ani fabryk per‑żądanie. Token jest jedynym poświadczeniem, które klient kiedykolwiek wyśle z powrotem do widżetu Viewera (objViewer.View(token) po stronie front‑endu).
Używanie tokenu po stronie klienta
Po zwróceniu tokenu, widżet front‑endu wywołuje objViewer.View(token). Widżet dołącza ten sam token do każdego kolejnego żądania o obrazy stron, wyszukiwanie lub akcje adnotacji. Serwer weryfikuje token względem sesji, która pierwotnie otworzyła dokument. Jeśli token zostanie przedstawiony z innej sesji przeglądarki, Viewer zwraca błąd autoryzacji, co jest zamierzonym zachowaniem bezpieczeństwa.
Wczesne zamykanie sesji (opcjonalnie)
Jeśli Twój przepływ pracy wie, że dokument nie będzie już nigdy dostępny, możesz zwolnić wpis w pamięci podręcznej wywołując CloseDocument na Viewer. To usuwa sesję z pamięci podręcznej i zapobiega utrzymywaniu jej przy życiu przez timer wygasania przesuwnego.
Podsumowanie przepływu bezstanowego
| Krok | Co się dzieje | Gdzie przechowywany jest stan |
|---|---|---|
| Wstrzyknięcie Viewera | Pojedyncza instancja Viewer jest tworzona przy starcie. | W kontenerze DI (singleton). |
| OpenDocumentAsync | Sprawdzono licencję → utworzono sesję → zwrócono token. | Sesja przechowywana w IMemoryCache (lub rozproszona pamięć podręczna). |
| Klient renderuje | Widżet wysyła token z każdym żądaniem. | Token jest jedynymi danymi per‑dokumentu, które trzyma klient. |
| Wygaśnięcie sesji / CloseDocument | Wpis w pamięci podręcznej usuwany po upływie czasu lub wyraźnym zamknięciu. | Brak zalegających zasobów w usłudze Viewera. |
Ponieważ sama usługa nigdy nie przechowuje danych dokumentu, możesz bezpiecznie skalować swoją farmę serwerów, wymieniać węzły lub restartować aplikację bez utraty widocznego dla użytkownika stanu — jedynie token staje się nieważny, co powoduje, że klient musi ponownie otworzyć dokument.
Wdrażanie bezstanowego Viewera w aplikacji
- Dodaj
AddDoconut,AddSessioni dostawcę pamięci podręcznej doProgram.cs. - Wklej fragment otwartego punktu końcowego do konfiguracji minimal‑API.
- Przekaż zwrócony token do
objViewer.View(token)po stronie front‑endu.
Masz teraz w pełni bezstanowe, gotowe do produkcji API otwierania dokumentów, które wykorzystuje projekt Viewer firmy Doconut.