Migracja do .NET Standard 2.1
Przenieś istniejącą aplikację Doconut.NETStandard z wersji 26.7.0 do 26.8.0
Doconut ma dwie odrębne integracje .NET Standard. Używają tej samej nazwy pakietu Doconut.NETStandard, więc należy określić generację na podstawie wersji i API w aplikacji przed zmianą pakietów, uruchomieniem, licencjami lub zasobami przeglądarki.
Wersja jest rozdrożeniem
| Wersja | Docelowa | API |
|---|---|---|
| 26.7.0 i niższe | netstandard2.0 | poprzednie API |
| 26.8.0 i wyższe | netstandard2.1 | obecne API |
Zwiększenie numeru wersji jest aktualizacją. Nie ma osobnego pakietu do zainstalowania ani warstwy kompatybilności — 26.8.0 ma inną powierzchnię API. Oczekuj błędów kompilacji po podniesieniu wersji; reszta tego przewodnika to ich lista.
Którą integrację używasz?
| Jeżeli projekt zawiera… | Generacja |
|---|---|
new Viewer(_cache, _accessor, ...) | Poprzednia |
viewer.OpenDocument(...) (synchroniczna) | Poprzednia |
viewer.InitCache() | Poprzednia |
UseDoconut(new DoconutOptions { ... }) | Poprzednia |
UseDoconutWebFarm(...) / WebFarmOptions | Poprzednia |
Viewer.DoconutLicense(...) lub Viewer.SetLicensePlugin(...) | Poprzednia |
viewer.Converter.GetConverter() | Poprzednia |
using Doconut.Configs; / using Doconut.Models; | Poprzednia |
Ręcznie skopiowane docViewer.js, documentLinks.js, lub docViewer.UI.js | Poprzednia |
builder.Services.AddDoconut(...) | Obecna |
app.UseDoconutResources() plus app.UseDoconut() bez argumentów | Obecna |
Viewer dostarczany przez wstrzykiwanie zależności | Obecna |
await viewer.OpenDocumentAsync(...) | Obecna |
Jeśli obie kolumny pojawiają się w tej samej aplikacji, traktuj migrację jako niekompletną. Nie wysyłaj jednego tokenu dokumentu przez zasoby lub middleware z innej generacji.
Najpierw sprawdź framework hosta
To jest twarda bariera, a nie preferencja. Obecny pakiet celuje w netstandard2.1:
| Host | Czy może używać 26.8.0 |
|---|---|
| .NET Core 3.0 lub nowszy (w tym .NET 5/6/7/8) | Tak |
| .NET Framework, dowolna wersja | Nie |
.NET Framework nie może odwoływać się do biblioteki netstandard2.1. Jeśli aplikacja działa na .NET Framework, zatrzymaj się tutaj i użyj pakietu Doconut.NETFramework zamiast; od wersji 26.9.0 wymaga .NET Framework 4.7.2. Obie aplikacje referencyjne dla tego wydania celują w net8.0.
Przed migracją
- Utwórz gałąź i wdrażalną kopię zapasową istniejącej aplikacji.
- Zanotuj dokładne wersje pakietów core i plugin.
- Spisz wszystkie wywołania
new Viewer(...), wywołaniaInitCache(), wywołania ładowania licencji, mapowanieUseDoconutWebFarm, kontroler konwersji, skopiowany skrypt Doconut, niestandardową akcję paska narzędzi, wywołanie zwrotne viewer oraz punkt końcowy otwierania dokumentu. - Zachowaj bieżące pliki
.lici sekrety wdrożeniowe poza kontrolą wersji. - Zbierz reprezentatywny zestaw dokumentów PDF, Office, obrazów, CAD, e‑mail, DICOM, przeszukiwalnych, chronionych hasłem i anotowanych.
- Zanotuj istniejące ustawienia limitu czasu sesji, zachowanie bezpieczeństwa, czcionki i ustawienia platformy.
Migruj jedno środowisko przed zmianą produkcji. Obecna integracja zmienia czas życia usług, routowanie żądań, własność sesji, dostarczanie zasobów klienta oraz — jeśli prowadzisz farmę — sposób, w jaki strony docierają do przeglądarki.
1. Przestrzenie nazw: prawie wszystko przeniesiono do korzenia
Typy konfiguracyjne były rozproszone w czterech przestrzeniach nazw. Teraz wszystkie znajdują się w Doconut.
| Wcześniej | Teraz |
|---|---|
using Doconut.Configs.View; | using Doconut; |
using Doconut.Models; | using Doconut; |
using Doconut.Configs; | using Doconut; |
using Doconut.Configs.Cloud; | using Doconut.Clouds; |
using Doconut.Configs.Conversion; | bez zmian |
using Doconut.Middleware; | bez zmian |
Nazwy typów nie uległy zmianie: WordConfig, PdfConfig, ExcelConfig, CssConfig, ScriptConfig, CloudUploadConfig, AzureConfig, CDNConfig, FileShareConfig i reszta nadal istnieje. W większości plików cała edycja polega na usunięciu dwóch linii using.
Doconut.Configs.Editor (BaseConfigEditor, PdfConfigEditor) został usunięty i nie ma zamiennika w tym pakiecie. Jeśli Twoja aplikacja odwoływała się do tych typów, zaplanuj tę część osobno i nie traktuj jej jako części tej migracji.
2. Kompatybilność pakietu i licencji
Zamień lub zaktualizuj pakiet podstawowy celowo; nie polegaj na identycznym identyfikatorze pakietu, aby wybrać nowe API. Domyślne polecenie instaluję najnowsze stabilne wydanie:
dotnet add package Doconut.NETStandardAby uzyskać odtwarzalną migrację do wydania audytowanego w tym przewodniku, przekaż wersję jako oddzielną opcję:
dotnet add package Doconut.NETStandard --version 26.8.0Utrzymuj każdy wtyczkę Doconut w tej samej wersji co pakiet podstawowy — Doconut.NETStandard.Converter i Doconut.NETStandard.Dicom. Obecna integracja ładuje licencje raz podczas AddDoconut(), używając następującego priorytetu:
LicenseStream > LicenseContent > LicensePath > automatic discoveryAutomatyczne wykrywanie szuka Doconut.Viewer.lic oraz plików towarzyszących Doconut.Viewer.<Capability>.lic. Poprzednie wywołania statyczne Viewer.DoconutLicense(...) i Viewer.SetLicensePlugin(...) nie są już mechanizmem uruchamiania, podobnie jak List<string> ścieżek licencji, które akceptował stary konstruktor Viewer. Przenieś licencję do DoconutOptions, trzymaj pliki towarzyszące razem przy użyciu automatycznego wykrywania, uruchom ponownie po zmianie licencji i zweryfikuj możliwości przez IDoconutLicenseService.
Nie zakładaj, że obecność starej licencji wtyczki dowodzi uprawnienia do bieżącej kompilacji wtyczki. Testuj osobno Viewer, Search, Annotation, Converter i DICOM przy użyciu zatwierdzonych artefaktów wydania.
3. Uruchamianie i wstrzykiwanie zależności
Wcześniej przeglądarka była tworzona na żądanie, a opcje przekazywane do pośrednika:
// Poprzednia integracja — tylko kontrast; nie kompiluj tego z bieżącym SDK.
var viewer = new Viewer(_cache, _accessor);
// …
appBranch.UseDoconut(new DoconutOptions { UnSafeMode = false, ShowDoconutInfo = false });Obecna integracja rejestruje Doconut raz i otrzymuje Viewer z wstrzykiwania zależności:
builder.Services.AddDoconut(options =>
{
options.UnsafeMode = false; // uwaga na zmianę pisowni: UnSafeMode → UnsafeMode
options.ShowDoconutInfo = false;
options.LicensePath = "Doconut.Viewer.lic";
});
builder.Services.AddDistributedMemoryCache(); // stan sesji wymaga pamięci podręcznej (MVC/Razor Pages już dodają jedną)
builder.Services.AddSession();
app.UseSession();
app.UseDoconutResources();
app.UseDoconut();Viewer jest usługą przejściową. Menedżer sesji dokumentu i jego pamięć podręczna posiadają długotrwały stan dokumentu, a nie konkretną wstrzykniętą instancję Viewer.
Trzy rzeczy do przeniesienia:
new Viewer(cache, accessor)został usunięty. WstrzyknijDoconut.Viewerdo swojego kontrolera lub użyj@inject Doconut.Viewer Viewerw widoku Razor.UseDoconutResources()zastępuje ręczne wiązanieapp.UseMiddleware<EmbeddedResourceMiddleware>()i musi być uruchomione przed gałęzią dokumentu.UnSafeMode→UnsafeMode. Jednoznakowa zmiana nazwy, którą wykryje kompilator.
Kiedy UnsafeMode jest false, SDK weryfikuje token sesji względem pierwotnego żądania, więc AddSession() / UseSession() muszą nadal znajdować się w potoku, UseSession() przed gałęzią.
Metody, które już nie istnieją
| Przed | Teraz |
|---|---|
viewer.OpenDocument(path, config, options) | await viewer.OpenDocumentAsync(path, config, options) |
viewer.InitCache() | usunięto — nie ma nic do ręcznego podgrzewania; usuń wywołanie i wszelkie flagi „czy już zainicjowałem?” wokół niego |
viewer.ExportToPng(sharedPath) | zobacz §7 |
viewer.ExportToCloud(cloudConfig) | zobacz §7 |
using var v = new Viewer(...); v.CloseDocument(t) | viewer.CloseDocument(token) na wstrzykniętej instancji |
4. Środkowe oprogramowanie i routowanie zasobów
UseDoconut() teraz nie przyjmuje żadnych argumentów. Kształt gałęzi MapWhen nie musi się zmieniać — tylko pośrednik wewnątrz niej:
app.UseDoconutResources(); // PRZED gałęzią
app.MapWhen(
ctx => ctx.Request.Path.Value?.EndsWith("DocImage.axd", StringComparison.OrdinalIgnoreCase) == true,
branch => branch.UseDoconut());W bieżącym potoku:
- wywołaj
UseSession()przed Doconut, gdy zabezpieczenia sesji są włączone; - wywołaj
UseDoconutResources()przedUseDoconut(); - utrzymaj
ResourcesPath, wygenerowane adresy URL zasobów i klientaResPathw zgodzie; - utrzymaj mapowaną gałąź i klienta
BasePathw zgodzie.
MiddlewarePath jest zweryfikowaną konfiguracją; nie tworzy ona samodzielnie gałęzi ASP.NET Core.
5. Budowa i czas życia przeglądarki
Usuń pamięci podręczne własności aplikacji przechowujące obiekty Viewer. Nie pozostaje nic w Viewer
warto zachować: nie zawiera żadnego stanu dokumentu, a pamięć podręczna sesji posiada wszystko
co przetrwa żądanie. Wstrzyknij go do punktu końcowego, strony Razor, kontrolera lub scoped
usługi aplikacji:
app.MapPost("/api/open", async (Viewer viewer) =>
{
var token = await viewer.OpenDocumentAsync("wwwroot/files/Sample.pdf");
return Results.Ok(new { token });
});Zwrócony token identyfikuje sesję dokumentu po stronie serwera. Traktuj go jako poświadczenie nośnika poświadczenie: nie loguj go, nie przechowuj ani nie umieszczaj w analizach.
6. Otwieranie i zamykanie dokumentów
Zastąp synchroniczny OpenDocument(...) przez OpenDocumentAsync(...):
// Aktualna integracja: Viewer pochodzi z DI i otwieranie dokumentu jest asynchroniczne.
var token = await viewer.OpenDocumentAsync(path, new PdfConfig { AllowSearch = true });Obecne przeciążenia akceptują ścieżkę pliku lub strumień, opcjonalną konfigurację formatu, opcjonalny
DocOptions oraz token anulowania. Zamknij sesję serwera explicite, gdy
przeglądarka już go nie potrzebuje:
viewer.CloseDocument(token);Usuń każde wywołanie InitCache() oraz flagę go chroniącą — nie ma nic do ręcznego podgrzewania
ręcznie. Nie używaj ponownie tokenu wygenerowanego przez poprzednią bibliotekę po przejściu: otwórz każdy
dokument ponownie za pomocą bieżącego API.
7. Web farm → rozproszony: największa zmiana
UseDoconutWebFarm i WebFarmOptions nie istnieją już. Jeśli twoja aplikacja wywołuje je,
ta sekcja jest twoją aktualizacją; jeśli nie, przejdź do §8.
Wcześniej jedno pośrednictwo robiło wszystko: serwowało wstępnie wyrenderowane obrazy z udostępnionego folderu i odpytywało, gdy inny węzeł nadal je zapisywał.
// Poprzednia integracja — jedno wywołanie, niejawna koordynacja przez system plików.
appBranch.UseDoconutWebFarm(new WebFarmOptions
{
Path = Path.Combine(env.WebRootPath, "webfarm"),
PageWaitTimeSeconds = 180,
StartWaitFromPage = 5,
});To samo zadanie jest teraz podzielone na dwie wyraźne połówki. Strona zapisu — węzeł, który otwiera dokument, publikuje cały zestaw artefaktów (strony, informacje o dokumencie, indeks wyszukiwania, metadane) w udostępnionym miejscu:
var result = await _publisher.PublishAsync( // DistributedDocumentPublisher, wstrzyknięty z DI
pathToFile,
new FileShareConfig
{
Location = CloudLocation.FileShare,
RootPath = @"\\fileserver\doconut", // ten sam folder, którego używasz dzisiaj
UsePerTokenSubfolders = true,
},
config,
documentOptions,
new DistributedDocumentPublishOptions
{
CleanUpStagingDirectory = true,
FirstPagePriority = true,
});
return Content(result.Token);Strona odczytu — każdy węzeł serwuje z udostępnionego miejsca:
app.MapWhen(
ctx => ctx.Request.Path.Value?.EndsWith("DocImage.axd", StringComparison.OrdinalIgnoreCase) == true,
branch => branch.UseDoconutCloud<FileShareCloudHandler>(options =>
{
options.Location = CloudLocation.FileShare;
options.CloudUploadConfig = /* ten SAME FileShareConfig jak powyżej */;
}, "/"));| Przed | Teraz |
|---|---|
WebFarmOptions.Path | FileShareConfig.RootPath |
PageWaitTimeSeconds / StartWaitFromPage | usunięto — zastąpiono FirstPagePriority po stronie zapisu oraz FileShareConfig.ReadReadyPollMs po stronie odczytu |
viewer.OpenDocument(...) następnie viewer.ExportToPng(share) | jedno wywołanie PublishAsync(...) |
DocOptions.IsWebfarm / WebfarmPath | wciąż tam, zapisane jako IsWebFarm / WebFarmPath — ale nie potrzebne w ścieżce publikacji |
Twoja topologia nie zmienia się. Wskaż RootPath na ten sam udział UNC i każdy węzeł
działa tak, jak działa dzisiaj. Zmiana polega na tym, że publikowanie jest operacją, którą wywołujesz,
zamiast skutku ubocznego renderowania.
Obie połówki muszą się zgadzać. Jeśli
RootPathlubUsePerTokenSubfoldersróżnią się między wydawcą a obsługującym, drugi węzeł zwróci 404. Zbuduj konfigurację w jednym pomocniku i wywołaj ją z obu stron.
PageWaitTimeSeconds = 180 oznaczało „zablokuj do trzech minut, mając nadzieję, że strona się pojawi”.
Zastąpienie jest wyraźne: z FirstPagePriority = true, strona 1 jest dostępna od razu
a późniejsze strony odpowiadają HTTP 202 Accepted, dopóki nie zostaną zapisane. Wbudowana przeglądarka ponawia
automatycznie, gdy retryOn409 jest ustawione. Klient, który nie ponawia, pokaże uszkodzone
kafelki dla stron nadal renderowanych.
Pełna konfiguracja, w tym publikowanie w tle i bilety dostępu, znajduje się w Rozproszone wdrożenia.
8. Konwersja jest wtyczką i znacznie mniejsza
Zarejestruj wtyczkę, a następnie wstrzyknij fasadę DocumentConverter:
builder.Services.AddDoconut(o => o.AddPlugin<ConverterPlugin>());// Poprzednia integracja
var converter = viewer.Converter.GetConverter();
var config = new WordConfigConverter { TargetFormat = WordConfigConverter.EnTargetFormat.PDF };
var result = converter.Convert(stream, SourceFormatConverter.DOCX, config);
// Bieżąca integracja
var result = await _converter.ConvertAsync(stream, ".docx", ConversionTarget.Pdf, null, ct);Co to zastępuje:
SourceFormatConverter— usunięto. Przekaż rozszerzenie pliku jako ciąg znaków, z kropką.- Typy
*ConfigConverterdla każdej rodziny (WordConfigConverter,ExcelConfigConverter, …), każdy z zagnieżdżonym wyliczeniemEnTargetFormat— usunięto. Teraz istnieje jedno wyliczenieConversionTargetdla każdej rodziny. viewer.Converter.GetConverter()— usunięto. WstrzyknijDoconut.DocumentConverter.
ConvertAsync zwraca strumień z możliwością przewijania, więc return File(result, mime, name) działa
bezpośrednio — kopiowanie starego kodu MemoryStream nie jest potrzebne. W dostarczonym
przykładzie usunięto przełącznik rozszerzeń z 68 przypadkami oraz dziesięć prawie identycznych kontrolerów.
Zobacz Wtyczka konwertera dla pełnego zakresu.
9. Dostawcy chmury
UseDoconutCloud stał się generyczny. Dostawca jest argumentem typu zamiast wartości Location przełączanej wewnątrz middleware:
// Poprzednia integracja
appBranch.UseDoconutCloud(new CloudOptions { Location = CloudLocation.CDN, ... });
// Bieżąca integracja
branch.UseDoconutCloud<CDNCloudHandler>(options =>
{
options.Location = CloudLocation.CDN;
options.CloudUploadConfig = new CDNConfig { DoconutCdnUrl = "..." };
}, "/");Klasy konfiguracyjne są niezmienione, poza przestrzenią nazw (Doconut.Configs.Cloud → Doconut.Clouds): AzureConfig, AmazonConfig, GoogleCloudConfig, DropBoxConfig,
RedisConfig, CDNConfig, FTPConfig, plus nowy FileShareConfig. Obsługujące są nazwane <Provider>CloudHandler.
Obsługa CDN jest tylko do odczytu — serwuje to, co już znajduje się w CDN; nie dokonuje przesyłania.
10. Obiekty konfiguracyjne, które zmieniły nazwę
| Poprzednio | Teraz |
|---|---|
DoconutOptions.UnSafeMode | UnsafeMode |
DocOptions.IsWebfarm | IsWebFarm |
DocOptions.WebfarmPath | WebFarmPath |
DocOptions.ImageResolution | wciąż obecny, ale przestarzały — ustaw rozdzielczość w konfiguracji formatu zamiast tego |
DocOptions również zyskuje IsSecured.
Obecne API również rozdziela zagadnienia bardziej rygorystycznie niż poprzednie, więc sprawdź, czy każde ustawienie znajduje się w obiekcie, który teraz je posiada:
| Zagadnienie | Obecny typ |
|---|---|
| Ścieżki middleware, licencjonowanie, rejestracja wtyczki | DoconutOptions |
| Hasło, limit czasu, bezpieczeństwo, znak wodny | DocOptions |
| Renderowanie formatu i DPI | PdfConfig, WordConfig, ExcelConfig, i inne typy BaseConfig |
| Domyślne ustawienia widgetu przeglądarki | ViewerConfig lub równoważne opcje JavaScript |
| Wygenerowane CSS i skrypty | CssConfig i ScriptConfig |
| Współdzielona pamięć i dostawcy chmury | FileShareConfig i inne konfiguracje Doconut.Clouds |
Nie przenoś DocOptions.ImageResolution dalej jako kontrolki renderowania. Jest przestarzały; ustaw BaseConfig.ImageResolution w konfiguracji specyficznej dla formatu. Przejrzyj wszystkie domyślne ustawienia zamiast zakładać, że poprzednia konfiguracja zachowuje się tak samo.
11. Przeglądarka po stronie klienta — dwie zmiany, które zawodzą PO CICHU
Obie te zmiany pozostawiają serwer w pełni sprawnym. Twój dokument jest renderowany, strona wygląda poprawnie i nic nie pojawia się w konsoli przeglądarki. Przeczytaj tę sekcję, nawet jeśli Twój C# kompiluje się za pierwszym razem.
Wywołania zwrotne przeglądarki są teraz opcjami, a nie funkcjami globalnymi
Poprzednia przeglądarka wywoływała Twoje obsługi według nazwy, wyprowadzając nazwę funkcji globalnej z identyfikatora kontenera. Deklarowanie function ctlDoc_OnViewerReady() na stronie z <div id="div_ctlDoc"> było wystarczające. Obecna przeglądarka przyjmuje wyraźne wywołania zwrotne w obiekcie opcji i nie szuka już tych globalnych funkcji:
objctlDoc = $("#div_ctlDoc").docViewer({
// ... twoje istniejące opcje ...
onViewerBusy: ctlDoc_OnViewerBusy, // zostało znalezione po nazwie
onViewerReady: ctlDoc_OnViewerReady, // zostało znalezione po nazwie
onCopy: ctlDoc_Copy, // było ctlDoc_Copy(text)
onAutoLoadStatus: ctlDoc_AutoLoadStatus // było ctlDoc_AutoLoadStatus(page)
});Dlaczego to jest nieprzyjemne: stare wywołanie było opakowane w pusty catch, który pochłaniał wszystko. Teraz Twoje funkcje po prostu nigdy się nie uruchamiają i nic nie zgłasza błędu. Typowy objaw to nieustannie obracający się wskaźnik — ponieważ funkcja, która go ukrywała, była ctlDoc_OnViewerReady. Dokument za nim jest w porządku.
Pełna lista opcji to onPageLoading, onPageLoaded, onThumbnailClicked,
onPageClicked, onDoubleClick, onViewerBusy, onViewerReady, onViewerError,
onCopy, onAnnSaved, onAnnSaveError, onAnnLoaded, onAnnClosed,
onAutoLoadStatus, onThumbsShown i onError. Nie ma wywołania zwrotnego przy kliknięciu linku: obsługa hiperłączy jest wbudowana, sterowana przez showHyperlinks.
ResPath musi wskazywać na prefiks zasobu
ResPath: '', // WCZEJŚNIEJ — zasoby pochodziły z katalogu głównego aplikacji
ResPath: 'doconut-res/images', // TERAZ — prefiks UseDoconutResources() montujeJeśli zmieniłeś prefiks za pomocą DoconutOptions.ResourcesPath, użyj tej wartości zamiast tego.
12. Pasek narzędzi przeglądarki, wyszukiwanie i adnotacje
Nie migruj starych skryptów pojedynczo. Obecne aplikacje referencyjne tworzą jeden kompletny pakiet strony:
- wyemituj CSS przeglądarki i licencjonowany CSS wyszukiwania/adnotacji przy użyciu
ReferenceCss; - renderuj pasek narzędzi przeglądarki należący do aplikacji;
- renderuj
searchBarMount,annBarMounti wymagane zamontowanie przeglądarki; - wyemituj skrypty przeglądarki i licencjonowane moduły przy użyciu
ReferenceScripts; - załaduj własny skrypt pomocniczy paska narzędzi aplikacji;
- zainicjalizuj jeden
objViewer; - zainicjalizuj licencjonowane wstążki wyszukiwania i adnotacji;
- wywołaj
attach(objViewer)na każdej wstążce; - otwórz dokument i wywołaj
objViewer.View(token).
Wyszukiwanie i adnotacje są modułami podłączonymi do tej samej przeglądarki, a nie niezależnymi paskami narzędzi. Główny pasek narzędzi należy do aplikacji hosta; wstążki wyszukiwania i adnotacji są osadzone, zasoby z ograniczeniami funkcjonalności.
Usuń ręcznie skopiowane pliki, takie jak documentLinks.js i docViewer.UI.js, dopiero po tym, jak bieżąca strona będzie działać z zasobami wyemitowanymi przez ReferenceCss i ReferenceScripts.
13. Rejestracja wtyczek
Statyczne metody licencji wtyczek nie rejestrują bieżących wtyczek. Zainstaluj i zarejestruj każdy wydany pakiet explicite:
builder.Services.AddDoconut(options =>
{
options.AddPlugin<Doconut.Plugins.Converter.ConverterPlugin>();
options.AddPlugin<Doconut.Plugins.Dicom.DicomPlugin>();
});AddDoconut() waliduje zarejestrowane możliwości wtyczek przy uruchamianiu. Converter i DICOM są wydanymi wtyczkami .NET Standard. Normalne wyszukiwanie i adnotacje są wbudowanymi licencjonowanymi funkcjami, a nie pakietami AddPlugin<TPlugin>().
14. Sesja i bezpieczeństwo dokumentu
Obecna integracja wiąże dokumenty z nieprzezroczystymi tokenami i buforowanymi sesjami. Z domyślnym UnsafeMode = false, UseDoconut() dodaje bezpieczeństwo dostępu do dokumentu i host musi skonfigurować sesję ASP.NET:
builder.Services.AddDistributedMemoryCache(); // stan sesji wymaga pamięci podręcznej (MVC/Razor Pages już dodają jedną)
builder.Services.AddSession();
app.UseSession();Zachowaj DocOptions.IsSecured = true, chyba że przeglądany projekt wymaga inaczej. Nigdy nie używaj UnsafeMode = true jako skrótu migracji na pojedynczym węźle. Testuj żądania bez tokena, z uszkodzonym tokenem, z wygasłym tokenem oraz z tokenem z innej sesji przeglądarki.
W farmie żądanie strony może trafić na węzeł, który nigdy nie widział żądania otwierającego, więc sprawdzenie per-sesja odrzuci je. To jedyny przypadek, w którym UnsafeMode = true jest prawidłowy — i musi być połączony z podpisanymi biletami dostępu przez AddDoconutDistributedDocumentSecurity, a nie dostarczany samodzielnie. Zobacz Rozproszone wdrożenia.
Uwaga dotycząca nazewnictwa
We wszystkich frameworkach klasa to Viewer. Jeśli znajdziesz DocumentViewer w starych fragmentach kodu lub artykułach firm trzecich, ten typ nigdy nie istniał w SDK.
15. Sugerowana kolejność prac
- Potwierdź, że framework hosta może konsumować netstandard2.1. Jeśli nie, zatrzymaj się.
- Zaktualizuj pakiet do 26.8.0 i zbuduj. Przejdź przez błędy kompilacji — większość to linie
usingw §1. - Przenieś uruchamianie do
AddDoconut()i wywołania middleware do ich nowej kolejności (§3, §4). - Wstrzyknij
Viewertam, gdzie go konstruowałeś, uczynijOpenDocumentasynchronicznym i usuńInitCache()(§5, §6). - Jeśli używasz farmy webowej, wykonaj §7 — jedyną część, która jest przeprojektowaniem, a nie zmianą nazwy.
- Jeśli konwertujesz dokumenty, wykonaj §8.
- Wykonaj §11 — zmiany po stronie klienta. To one, które nie ogłoszą się same.
- Otwórz prawdziwy dokument w przeglądarce i obserwuj kręcący się wskaźnik. Zielona kompilacja nie dowodzi niczego: licencjonowanie, rejestracja wtyczek, ścieżka zasobu i wywołania zwrotne przeglądarki zawodzą dopiero w czasie wykonywania. Dla farmy, zweryfikuj, że dokument opublikowany przez jeden węzeł jest serwowany przez inny.
Testowanie migracji
W minimalnym zakresie, zweryfikuj:
- uruchomienie aplikacji z licencją produkcyjną i wszystkimi zarejestrowanymi wtyczkami;
- CSS/skrypty przeglądarki i wszystkie żądania obrazów stron w wybranych ścieżkach;
- otwieranie dokumentu, nawigację, przybliżanie, miniatury, drukowanie oraz wyraźne zamknięcie;
- wyszukiwanie w dokumencie zawierającym tekst oraz stan nie‑wyszukiwalności pliku zawierającego wyłącznie obrazy;
- ładowanie, zapisywanie, eksport adnotacji oraz kontrola możliwości;
- wykrywanie docelowego konwertera, wyjście, pobieranie i stan znaku wodnego;
- strony DICOM, klatki i animacje; metadane techniczne nie są dostępne w tym pakiecie;
- dokumenty chronione hasłem, niestandardowe czcionki, tekst niełaciński oraz skonfigurowane limity czasu;
- odrzucanie tokenów między sesjami oraz zachowanie przy wygasłej sesji;
- w przypadku farmy: publikacja na jednym węźle, żądanie późniejszej strony z innego i potwierdzenie,
że przeglądarka ponawia
202odpowiedzi zamiast wyświetlać uszkodzone kafelki; - tryb mobilny, tryb ciemny oraz ścieżka odwróconego proxy produkcji.
Plan przywracania
Zachowaj poprzedni artefakt wdrożeniowy, pasujące pakiety, pliki licencji oraz skopiowane zasoby przeglądarki razem. Bezpieczne przywrócenie przełącza całą generację aplikacji; nie miesza serwera poprzedniej generacji z bieżącymi skryptami ani bieżącego serwera z new Viewer(...) miejscami wywołań.
Przed przełączeniem, udokumentuj:
- slot wdrożeniowy lub artefakt używany do przywracania;
- wpływ współdzielonego magazynu, jeśli istnieje — artefakty opublikowane przez 26.8.0 nie są konsumowane przez poprzednie oprogramowanie pośredniczące farmy webowej;
- sposób unieważniania aktywnych sesji dokumentów;
- kontrola zdrowia i dokument testowy używany do podjęcia decyzji o przywróceniu;
- kto może przywrócić poprzedni zestaw pakietów i konfigurację.
Dokumentacja starsza
Przetłumana poprzednia instrukcja pozostaje dostępna pod adresem Starsza konfiguracja .NET Standard. Poprzednia brama integracyjna wyjaśnia te same sygnały identyfikacyjne i odsyła z powrotem do tego przewodnika migracji.
Zachowaj historyczny adres URL w zakładkach i zgłoszeniach wsparcia, dopóki instalacje netstandard2.0 nadal istnieją. Dokumentuje on inną generację i nie jest przekierowywany do bieżącego API.
Czy ta strona była pomocna?