Migration zu .NET Standard 2.1
Verschieben einer bestehenden Doconut.NETStandard-Anwendung von 26.7.0 auf 26.8.0
Doconut hat zwei unterschiedliche .NET Standard-Integrationen. Sie verwenden denselben Doconut.NETStandard Paketnamen, daher sollten Sie die Generation anhand der Version und der APIs in der Anwendung ermitteln, bevor Sie Pakete, Startup, Lizenzen oder Browser‑Ressourcen ändern.
Die Version ist die Gabelung
Beide Generationen veröffentlichen unter derselben Paket-ID. Nur die Version unterscheidet sie:
| Version | Ziel | API |
|---|---|---|
| 26.7.0 und darunter | netstandard2.0 | die vorherige API |
| 26.8.0 und darüber | netstandard2.1 | die aktuelle API |
Das Erhöhen der Versionsnummer ist das Upgrade. Es gibt kein separates Paket zu installieren und keinen Kompatibilitätsshim — 26.8.0 hat eine andere API‑Oberfläche. Erwarten Sie Kompilierfehler nach dem Upgrade; der Rest dieses Leitfadens ist die Liste dieser Fehler.
Welche Integration verwenden Sie?
| Wenn das Projekt enthält… | Generation |
|---|---|
new Viewer(_cache, _accessor, ...) | Vorherige |
viewer.OpenDocument(...) (synchronous) | Vorherige |
viewer.InitCache() | Vorherige |
UseDoconut(new DoconutOptions { ... }) | Vorherige |
UseDoconutWebFarm(...) / WebFarmOptions | Vorherige |
Viewer.DoconutLicense(...) oder Viewer.SetLicensePlugin(...) | Vorherige |
viewer.Converter.GetConverter() | Vorherige |
using Doconut.Configs; / using Doconut.Models; | Vorherige |
Manually copied docViewer.js, documentLinks.js, or docViewer.UI.js | Vorherige |
builder.Services.AddDoconut(...) | Aktuelle |
app.UseDoconutResources() plus app.UseDoconut() with no arguments | Aktuelle |
Viewer supplied by dependency injection | Aktuelle |
await viewer.OpenDocumentAsync(...) | Aktuelle |
Wenn beide Spalten in derselben Anwendung vorkommen, betrachten Sie die Migration als unvollständig. Senden Sie kein Dokument‑Token über Ressourcen oder Middleware der anderen Generation.
Prüfen Sie zuerst das Host‑Framework
Dies ist eine harte Hürde, keine Präferenz. Das aktuelle Paket zielt auf netstandard2.1:
| Host | Kann 26.8.0 verwenden |
|---|---|
| .NET Core 3.0 oder später (einschließlich .NET 5/6/7/8) | Ja |
| .NET Framework, jede Version | Nein |
.NET Framework kann keine netstandard2.1‑Bibliothek referenzieren. Wenn die Anwendung auf .NET Framework läuft, brechen Sie hier ab und verwenden Sie stattdessen das Doconut.NETFramework Paket; ab 26.9.0 erfordert es .NET Framework 4.7.2. Beide Referenzanwendungen für diese Version zielen auf net8.0.
Bevor Sie migrieren
- Erstellen Sie einen Branch und ein bereitstellbares Backup der bestehenden Anwendung.
- Protokollieren Sie die genauen Kern‑ und Plugin‑Paketversionen.
- Inventarisieren Sie jeden
new Viewer(...)Aufruf,InitCache()Aufruf, Lizenz‑Ladeaufruf,UseDoconutWebFarmZuordnung, Konvertierungscontroller, kopiertes Doconut‑Skript, benutzerdefinierte Symbolleistenaktion, Viewer‑Callback und Dokument‑Öffnen‑Endpunkt. - Bewahren Sie die aktuellen
.licDateien und Bereitstellungsgeheimnisse außerhalb der Versionskontrolle auf. - Erfassen Sie ein repräsentatives Set von PDF‑, Office‑, Bild‑, CAD‑, E‑Mail‑, DICOM‑, durchsuchbaren, passwortgeschützten und kommentierten Dokumenten.
- Protokollieren Sie das bestehende Sitzungs‑Timeout, das Sicherheitsverhalten, die Schriftarten und die Plattform‑Einstellungen.
Migrieren Sie zunächst eine Umgebung, bevor Sie die Produktion ändern. Die aktuelle Integration ändert die Service‑Lebensdauer, das Anforderungsrouting, den Sitzungsbesitz, die Bereitstellung von Client‑Ressourcen und — falls Sie einen Farmbetrieb haben — wie Seiten überhaupt den Browser erreichen.
1. Namespaces: Fast alles wurde in den Root verschoben
Die Konfigurationstypen waren auf vier Namespaces verteilt. Sie befinden sich jetzt alle in Doconut.
| Vorher | Jetzt |
|---|---|
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; | unverändert |
using Doconut.Middleware; | unverändert |
Die Typnamen haben sich nicht geändert: WordConfig, PdfConfig, ExcelConfig, CssConfig, ScriptConfig, CloudUploadConfig, AzureConfig, CDNConfig, FileShareConfig und der Rest ist weiterhin vorhanden. In den meisten Dateien besteht die gesamte Änderung darin, zwei using Zeilen zu löschen.
Doconut.Configs.Editor (BaseConfigEditor, PdfConfigEditor) wurde entfernt und hat keinen Ersatz in diesem Paket. Wenn Ihre Anwendung diese Typen referenziert hat, planen Sie diesen Teil separat und behandeln Sie ihn nicht als Teil dieser Migration.
2. Paket‑ und Lizenzkompatibilität
Ersetzen oder aktualisieren Sie das Kernpaket bewusst; verlassen Sie sich nicht auf die identische Paket‑ID, um die neue API auszuwählen. Der Standardbefehl installiert die neueste stabile Version:
dotnet add package Doconut.NETStandardFür eine reproduzierbare Migration zur in diesem Leitfaden geprüften Version übergeben Sie die Versionsnummer als separate Option:
dotnet add package Doconut.NETStandard --version 26.8.0Halten Sie jedes Doconut‑Plugin in derselben Version wie das Kernpaket — Doconut.NETStandard.Converter und Doconut.NETStandard.Dicom. Die aktuelle Integration lädt Lizenzen einmal während AddDoconut() und verwendet dabei diese Priorität:
LicenseStream > LicenseContent > LicensePath > automatic discoveryDie automatische Erkennung sucht nach Doconut.Viewer.lic und zugehörigen Doconut.Viewer.<Capability>.lic‑Dateien. Die früheren statischen Aufrufe Viewer.DoconutLicense(...) und Viewer.SetLicensePlugin(...) sind kein aktueller Startmechanismus, und auch das List<string> von Lizenzpfaden, das der alte Viewer‑Konstruktor akzeptierte, ist nicht mehr gültig. Verschieben Sie die Lizenz zu DoconutOptions, halten Sie zugehörige Dateien zusammen, wenn Sie die automatische Erkennung verwenden, starten Sie nach einer Lizenzänderung neu und prüfen Sie die Fähigkeiten über IDoconutLicenseService.
Gehen Sie nicht davon aus, dass das Vorhandensein einer alten Plugin‑Lizenz einen Anspruch auf einen aktuellen Plugin‑Build begründet. Testen Sie Viewer, Search, Annotation, Converter und DICOM separat mit den freigegebenen Release‑Artefakten.
3. Start und Abhängigkeitsinjektion
Früher wurde der Viewer pro Anfrage erstellt und Optionen wurden an die Middleware übergeben:
// Vorherige Integration — nur zum Vergleich; nicht gegen das aktuelle SDK kompilieren.
var viewer = new Viewer(_cache, _accessor);
// …
appBranch.UseDoconut(new DoconutOptions { UnSafeMode = false, ShowDoconutInfo = false });Die aktuelle Integration registriert Doconut einmal und erhält Viewer über Dependency Injection:
builder.Services.AddDoconut(options =>
{
options.UnsafeMode = false; // Hinweis auf die Rechtschreibänderung: UnSafeMode → UnsafeMode
options.ShowDoconutInfo = false;
options.LicensePath = "Doconut.Viewer.lic";
});
builder.Services.AddDistributedMemoryCache(); // Der Sitzungszustand benötigt einen Cache (MVC/Razor Pages fügt bereits einen hinzu)
builder.Services.AddSession();
app.UseSession();
app.UseDoconutResources();
app.UseDoconut();Viewer ist ein transientes Service. Der Dokument‑Sitzungs‑Manager und sein Cache besitzen den längerlebigen Dokumenten‑Zustand, nicht die speziell injizierte Viewer‑Instanz.
Drei Dinge, die übernommen werden sollten:
new Viewer(cache, accessor)ist weg. Injizieren SieDoconut.Viewerin Ihren Controller oder verwenden Sie@inject Doconut.Viewer Viewerin einer Razor‑View.UseDoconutResources()ersetzt das manuelle Verdrahten vonapp.UseMiddleware<EmbeddedResourceMiddleware>()und muss vor dem Dokument‑Zweig ausgeführt werden.UnSafeMode→UnsafeMode. Eine ein‑zeichenige Umbenennung, die der Compiler erkennt.
Wenn UnsafeMode false ist, prüft das SDK das Sitzungstoken gegen die ursprüngliche Anfrage, sodass AddSession() / UseSession() weiterhin in der Pipeline sein müssen, UseSession() vor dem Zweig.
Methoden, die nicht mehr existieren
| Vorher | Jetzt |
|---|---|
viewer.OpenDocument(path, config, options) | await viewer.OpenDocumentAsync(path, config, options) |
viewer.InitCache() | entfernt — es gibt nichts, was manuell vorgeheizt werden könnte; löschen Sie den Aufruf und jedes „habe ich bereits init?“‑Flag darum herum |
viewer.ExportToPng(sharedPath) | siehe §7 |
viewer.ExportToCloud(cloudConfig) | siehe §7 |
using var v = new Viewer(...); v.CloseDocument(t) | viewer.CloseDocument(token) auf der injizierten Instanz |
4. Middleware und Ressourcenrouting
UseDoconut() akzeptiert jetzt keine Argumente. Die Struktur des MapWhen‑Zweigs muss selbst nicht geändert werden — nur die Middleware darin:
app.UseDoconutResources(); // VOR dem Branch
app.MapWhen(
ctx => ctx.Request.Path.Value?.EndsWith("DocImage.axd", StringComparison.OrdinalIgnoreCase) == true,
branch => branch.UseDoconut());Im aktuellen Pipeline:
- Rufen Sie
UseSession()vor Doconut auf, während die Sitzungs‑Sicherheit aktiviert ist; - Rufen Sie
UseDoconutResources()vorUseDoconut()auf; - Behalten Sie
ResourcesPath, die generierten Ressourcen‑URLs und den ClientResPathausgerichtet bei; - Behalten Sie den Zweig, den Sie zuordnen, und den Client
BasePathausgerichtet bei.
MiddlewarePath ist eine validierte Konfiguration; sie erstellt nicht eigenständig einen ASP.NET Core‑Zweig.
5. Viewer-Konstruktion und Lebensdauer
Entfernen Sie von der Anwendung verwaltete Caches von Viewer-Objekten. In einem Viewer ist nichts mehr, das es wert wäre, beibehalten zu werden: Es enthält keinen Dokumentzustand, und der Sitzungs‑Cache besitzt alles, was eine Anforderung überdauert. Injizieren Sie es in einen Endpunkt, Razor‑Seite, Controller oder einen scoped Application‑Service:
app.MapPost("/api/open", async (Viewer viewer) =>
{
var token = await viewer.OpenDocumentAsync("wwwroot/files/Sample.pdf");
return Results.Ok(new { token });
});Das zurückgegebene Token identifiziert eine serverseitige Dokumentensitzung. Behandeln Sie es als Träger‑Anmeldeinformation: Loggen Sie es nicht, speichern Sie es nicht und platzieren Sie es nicht in Analysen.
6. Öffnen und Schließen von Dokumenten
Ersetzen Sie synchrones OpenDocument(...) durch OpenDocumentAsync(...):
// Aktuelle Integration: Viewer kommt aus DI und das Öffnen des Dokuments ist asynchron.
var token = await viewer.OpenDocumentAsync(path, new PdfConfig { AllowSearch = true });Aktuelle Überladungen akzeptieren einen Dateipfad oder Stream, eine optionale Formatkonfiguration, optionales DocOptions und ein Cancellation‑Token. Schließen Sie die Serversitzung explizit, wenn der Browser sie nicht mehr benötigt:
viewer.CloseDocument(token);Löschen Sie jeden InitCache()‑Aufruf und das dafür schützende Flag — es gibt nichts, das man manuell vorwärmen müsste. Verwenden Sie ein vom vorherigen Bibliothek erzeugtes Token nach der Umstellung nicht erneut: Öffnen Sie jedes Dokument erneut über die aktuelle API.
7. Webfarm → verteilt: die größte Änderung
UseDoconutWebFarm und WebFarmOptions existieren nicht mehr. Wenn Ihre App sie aufruft, ist dieser Abschnitt Ihr Upgrade; wenn nicht, springen Sie zu §8.
Früher erledigte eine Middleware alles: Sie diente vorgerenderte Bilder aus einem gemeinsamen Ordner aus und pollte, während ein anderer Knoten sie noch schrieb.
// Vorherige Integration — ein Aufruf, implizite Koordination über das Dateisystem.
appBranch.UseDoconutWebFarm(new WebFarmOptions
{
Path = Path.Combine(env.WebRootPath, "webfarm"),
PageWaitTimeSeconds = 180,
StartWaitFromPage = 5,
});Die gleiche Aufgabe ist jetzt in zwei explizite Hälften aufgeteilt. Schreibseite — der Knoten, der das Dokument öffnet, veröffentlicht das gesamte Artefakt‑Set (Seiten, Dokumentinformationen, Suchindex, Metadaten) im Share:
var result = await _publisher.PublishAsync( // DistributedDocumentPublisher, aus DI injiziert
pathToFile,
new FileShareConfig
{
Location = CloudLocation.FileShare,
RootPath = @"\\fileserver\doconut", // derselbe Ordner, den du heute benutzt
UsePerTokenSubfolders = true,
},
config,
documentOptions,
new DistributedDocumentPublishOptions
{
CleanUpStagingDirectory = true,
FirstPagePriority = true,
});
return Content(result.Token);Leseseite — jeder Knoten dient aus dem Share:
app.MapWhen(
ctx => ctx.Request.Path.Value?.EndsWith("DocImage.axd", StringComparison.OrdinalIgnoreCase) == true,
branch => branch.UseDoconutCloud<FileShareCloudHandler>(options =>
{
options.Location = CloudLocation.FileShare;
options.CloudUploadConfig = /* die GLEICHE FileShareConfig wie oben */;
}, "/"));| Before | Now |
|---|---|
WebFarmOptions.Path | FileShareConfig.RootPath |
PageWaitTimeSeconds / StartWaitFromPage | weg — ersetzt durch FirstPagePriority auf der Schreibseite plus FileShareConfig.ReadReadyPollMs auf der Leseseite |
viewer.OpenDocument(...) dann viewer.ExportToPng(share) | ein PublishAsync(...) Aufruf |
DocOptions.IsWebfarm / WebfarmPath | immer noch vorhanden, geschrieben als IsWebFarm / WebFarmPath — aber nicht nötig im Veröffentlichungs‑Pfad |
Ihre Topologie ändert sich nicht. Zeigen Sie RootPath auf denselben UNC‑Share und jeder Knoten funktioniert weiterhin wie heute. Was sich ändert, ist, dass das Veröffentlichen ein Aufruf ist, den Sie tätigen, anstatt einer Nebenwirkung des Renderns.
Beide Hälften müssen übereinstimmen.
WennRootPathoderUsePerTokenSubfolderszwischen dem Publisher und dem Handler unterschiedlich sind, antwortet der andere Knoten mit 404.
Erstellen Sie die Konfiguration in einem Helfer und rufen Sie sie von beiden Seiten auf.
PageWaitTimeSeconds = 180 bedeutete „blockiere bis zu drei Minuten in der Hoffnung, dass die Seite erscheint“. Die Ersetzung ist explizit: Mit FirstPagePriority = true ist Seite 1 sofort bereitgestellt und spätere Seiten antworten mit HTTP 202 Accepted, bis sie geschrieben wurden. Der mitgelieferte Viewer versucht automatisch erneut, wenn retryOn409 gesetzt ist. Ein Client, der nicht erneut versucht, zeigt fehlerhafte Kacheln für noch rendernde Seiten.
Die vollständige Anordnung, einschließlich Hintergrundveröffentlichung und Zugriffstickets, finden Sie unter Verteilte Bereitstellungen.
8. Konvertierung ist ein Plugin und viel kleiner
Registrieren Sie das Plugin und injizieren Sie dann die DocumentConverter Fassade:
builder.Services.AddDoconut(o => o.AddPlugin<ConverterPlugin>());// Vorherige Integration
var converter = viewer.Converter.GetConverter();
var config = new WordConfigConverter { TargetFormat = WordConfigConverter.EnTargetFormat.PDF };
var result = converter.Convert(stream, SourceFormatConverter.DOCX, config);
// Aktuelle Integration
var result = await _converter.ConvertAsync(stream, ".docx", ConversionTarget.Pdf, null, ct);Was das ersetzt:
SourceFormatConverter— entfernt. Übergeben Sie die Dateierweiterung als Zeichenkette, Punkt eingeschlossen.- Die pro‑Familie
*ConfigConverterTypen (WordConfigConverter,ExcelConfigConverter, …), jeder mit einem verschachteltenEnTargetFormatEnum — entfernt. Jetzt gibt es für jede Familie einConversionTargetEnum. viewer.Converter.GetConverter()— entfernt. Injizieren SieDoconut.DocumentConverter.
ConvertAsync gibt einen suchbaren Stream zurück, sodass return File(result, mime, name) direkt funktioniert — die MemoryStream Kopie des alten Codes ist nicht mehr nötig. Im ausgelieferten Beispiel wurde dadurch ein 68‑Fälle‑Erweiterungs‑Switch und zehn nahezu identische Controller entfernt.
Siehe Converter-Plugin für die vollständige Oberfläche.
9. Cloud‑Anbieter
UseDoconutCloud wurde generisch. Der Anbieter ist das Typ‑Argument anstelle eines Location‑Werts, der im Middleware‑Code umgeschaltet wird:
// Vorherige Integration
appBranch.UseDoconutCloud(new CloudOptions { Location = CloudLocation.CDN, ... });
// Aktuelle Integration
branch.UseDoconutCloud<CDNCloudHandler>(options =>
{
options.Location = CloudLocation.CDN;
options.CloudUploadConfig = new CDNConfig { DoconutCdnUrl = "..." };
}, "/");Die Konfigurationsklassen sind unverändert, abgesehen vom Namensraum (Doconut.Configs.Cloud → Doconut.Clouds): AzureConfig, AmazonConfig, GoogleCloudConfig, DropBoxConfig, RedisConfig, CDNConfig, FTPConfig, plus das neue FileShareConfig. Handler heißen <Provider>CloudHandler.
Der CDN‑Handler ist schreibgeschützt — er liefert, was bereits im CDN liegt; er lädt nichts hoch.
10. Konfigurationsobjekte, deren Namen sich geändert hat
| Vorher | Jetzt |
|---|---|
DoconutOptions.UnSafeMode | UnsafeMode |
DocOptions.IsWebfarm | IsWebFarm |
DocOptions.WebfarmPath | WebFarmPath |
DocOptions.ImageResolution | noch vorhanden, aber veraltet — setzen Sie die Auflösung stattdessen in der Format‑Konfiguration |
DocOptions erhält außerdem IsSecured.
Die aktuelle API trennt die Zuständigkeiten ebenfalls strenger als die vorherige, prüfen Sie also, dass jede Einstellung am Objekt liegt, das sie jetzt besitzt:
| Zuständigkeit | Aktueller Typ |
|---|---|
| Middleware‑Pfade, Lizenzierung, Plugin‑Registrierung | DoconutOptions |
| Passwort, Timeout, Sicherheit, Wasserzeichen | DocOptions |
| Format‑Rendering und DPI | PdfConfig, WordConfig, ExcelConfig, und andere BaseConfig Typen |
| Browser‑Widget‑Standardwerte | ViewerConfig oder die entsprechenden JavaScript‑Optionen |
| Generiertes CSS und Skripte | CssConfig und ScriptConfig |
| Gemeinsamer Speicher und Cloud‑Anbieter | FileShareConfig und die anderen Doconut.Clouds Konfigurationen |
Verwenden Sie DocOptions.ImageResolution nicht mehr als Rendering‑Steuerung. Es ist veraltet; setzen Sie BaseConfig.ImageResolution in der format‑spezifischen Konfiguration. Überprüfen Sie alle Vorgaben, anstatt anzunehmen, dass eine frühere Konfiguration dasselbe Verhalten hat.
11. Der clientseitige Viewer — zwei Änderungen, die STILL SCHWEIGEND fehlschlagen
Beide Änderungen lassen den Server einwandfrei funktionieren. Ihr Dokument wird gerendert, die Seite sieht korrekt aus und es erscheint nichts in der Browser‑Konsole. Lesen Sie diesen Abschnitt, selbst wenn Ihr C# beim ersten Versuch kompiliert.
Viewer‑Callbacks sind jetzt Optionen, nicht globale Funktionen
Der vorherige Viewer rief Ihre Handler nach Namen auf, indem er den globalen Funktionsnamen aus der Container‑ID ableitete. Das Deklarieren von function ctlDoc_OnViewerReady() auf einer Seite mit <div id="div_ctlDoc"> reichte aus. Der aktuelle Viewer nimmt explizite Callbacks im Options‑Objekt entgegen und sucht diese Globalen nicht mehr:
objctlDoc = $("#div_ctlDoc").docViewer({
// ... Ihre vorhandenen Optionen ...
onViewerBusy: ctlDoc_OnViewerBusy, // wurde nach Namen gefunden
onViewerReady: ctlDoc_OnViewerReady, // wurde nach Namen gefunden
onCopy: ctlDoc_Copy, // wurde ctlDoc_Copy(text)
onAutoLoadStatus: ctlDoc_AutoLoadStatus // wurde ctlDoc_AutoLoadStatus(page)
});Warum das problematisch ist: Der alte Aufruf war in ein leeres catch eingewickelt, das alles verschlang. Jetzt werden Ihre Funktionen einfach nie ausgeführt und es wird kein Fehler gemeldet. Das typische Symptom ist ein ständig drehender Spinner — weil die Funktion, die ihn versteckte, ctlDoc_OnViewerReady war. Das dahinterliegende Dokument ist in Ordnung.
Die vollständige Optionsliste lautet onPageLoading, onPageLoaded, onThumbnailClicked, onPageClicked, onDoubleClick, onViewerBusy, onViewerReady, onViewerError, onCopy, onAnnSaved, onAnnSaveError, onAnnLoaded, onAnnClosed, onAutoLoadStatus, onThumbsShown und onError. Es gibt keinen Callback für Link‑Klicks: Die Hyperlink‑Verarbeitung ist eingebaut und wird von showHyperlinks gesteuert.
ResPath muss auf das Ressourcenpräfix zeigen
ResPath: '', // VORHER — Ressourcen kamen aus dem Anwendungsstamm
ResPath: 'doconut-res/images', // JETZT — das Präfix UseDoconutResources() wird gemountetWenn Sie das Präfix über DoconutOptions.ResourcesPath geändert haben, verwenden Sie stattdessen diesen Wert.
12. Viewer‑Symbolleiste, Suche und Annotation
Migrieren Sie die alten Skripte nicht einzeln. Die aktuellen Referenzanwendungen erstellen ein komplettes Seitenpaket:
- Geben Sie Viewer‑CSS und lizenziertes Such‑/Annotations‑CSS mit
ReferenceCssaus; - Rendern Sie die von der Anwendung bereitgestellte Viewer‑Symbolleiste;
- Rendern Sie
searchBarMount,annBarMountund die erforderliche Viewer‑Einbindung; - Geben Sie Viewer‑ und lizenzierte Modulscripte mit
ReferenceScriptsaus; - Laden Sie das eigene Toolbar‑Hilfsskript der Anwendung;
- Initialisieren Sie ein
objViewer; - Initialisieren Sie die lizenzierten Such‑ und Annotations‑Ribbons;
- Rufen Sie
attach(objViewer)für jedes Ribbon auf; - Öffnen Sie das Dokument und rufen Sie
objViewer.View(token)auf.
Suche und Annotation sind Module, die an denselben Viewer angehängt sind, nicht unabhängige Symbolleisten. Die Hauptsymbolleiste gehört zur Host‑Anwendung; die Such‑ und Annotations‑Ribbons sind eingebettete, funktionsabhängige Ressourcen.
Entfernen Sie manuell kopierte Dateien wie documentLinks.js und docViewer.UI.js erst, nachdem die aktuelle Seite mit den von ReferenceCss und ReferenceScripts ausgegebenen Ressourcen funktioniert.
13. Plugin‑Registrierung
Statische plugin‑Lizenz‑Methoden registrieren keine aktuellen Plugins. Installieren und registrieren Sie jedes veröffentlichte Paket explizit:
builder.Services.AddDoconut(options =>
{
options.AddPlugin<Doconut.Plugins.Converter.ConverterPlugin>();
options.AddPlugin<Doconut.Plugins.Dicom.DicomPlugin>();
});AddDoconut() prüft registrierte Plugin‑Fähigkeiten beim Start. Converter und DICOM sind die veröffentlichten .NET‑Standard‑Plugins. Normale Suche und Annotation sind integrierte lizenzierte Funktionen, keine AddPlugin<TPlugin>()‑Pakete.
14. Sitzungs‑ und Dokumentensicherheit
Die aktuelle Integration bindet Dokumente an undurchsichtige Tokens und zwischengespeicherte Sitzungen. Mit dem Standard‑UnsafeMode = false fügt UseDoconut() Dokumentenzugriffssicherheit hinzu und der Host muss die ASP.NET‑Sitzung konfigurieren:
builder.Services.AddDistributedMemoryCache(); // Sitzungszustand benötigt einen Cache (MVC/Razor Pages fügt bereits einen hinzu)
builder.Services.AddSession();
app.UseSession();Behalten Sie DocOptions.IsSecured = true bei, es sei denn, ein geprüftes Design verlangt etwas anderes. Verwenden Sie UnsafeMode = true niemals als Migrationsabkürzung auf einem einzelnen Knoten. Testen Sie Anfragen ohne Token, mit einem fehlerhaften Token, einem abgelaufenen Token und einem Token aus einer anderen Browser‑Sitzung.
In einer Farm kann die Seitenanfrage auf einem Knoten landen, der die Eröffnungsanfrage nie gesehen hat, sodass die pro‑Sitzungs‑Prüfung sie ablehnen würde. Das ist der einzige Fall, in dem UnsafeMode = true korrekt ist — und es muss zusammen mit signierten Zugriffstickets über AddDoconutDistributedDocumentSecurity verwendet werden, nicht allein ausgeliefert. Siehe Verteilte Bereitstellungen.
Hinweis zur Namensgebung
In allen Frameworks ist die Klasse Viewer. Wenn Sie DocumentViewer in alten Code‑Snippets oder Drittanbieter‑Artikeln finden, hat dieser Typ im SDK nie existiert.
15. Vorgeschlagene Arbeitsreihenfolge
- Bestätigen Sie, dass das Host‑Framework netstandard2.1 konsumieren kann. Wenn nicht, stoppen Sie.
- Erhöhen Sie das Paket auf 26.8.0 und bauen Sie es. Arbeiten Sie die Kompilierfehler ab – die meisten sind die
using‑Zeilen in §1. - Verschieben Sie den Startvorgang zu
AddDoconut()und die Middleware‑Aufrufe in ihre neue Reihenfolge (§3, §4). - Injizieren Sie
Viewerdort, wo Sie es konstruiert haben, machen SieOpenDocumentasynchron und löschen SieInitCache()(§5, §6). - Wenn Sie die Web‑Farm verwenden, führen Sie §7 aus — der einzige Teil, der ein Redesign und keine Umbenennung ist.
- Wenn Sie Dokumente konvertieren, führen Sie §8 aus.
- Führen Sie §11 aus — die clientseitigen Änderungen. Diese werden sich nicht von selbst ankündigen.
- Öffnen Sie ein echtes Dokument in einem Browser und beobachten Sie den Lade‑Spinner. Ein grüner Build beweist hier nichts: Lizenzierung, Plugin‑Registrierung, der Ressourcenpfad und die Viewer‑Callbacks schlagen nur zur Laufzeit fehl. Für eine Farm verifizieren Sie, dass ein von einem Knoten veröffentlichtes Dokument von einem anderen Knoten bereitgestellt wird.
Testen der Migration
Auf das Minimum prüfen:
- Anwendungsstart mit der Produktionslizenz und allen registrierten Plugins;
- Viewer CSS/Skripte und alle Seitenbild-Anfragen unter den gewählten Pfaden;
- Dokument öffnen, Navigation, Zoom, Miniaturansichten, Drucken und explizites Schließen;
- Suche in einem texthaltigen Dokument und der nicht durchsuchbaren Zustand einer rein bildbasierten Datei;
- Laden, Speichern, Exportieren von Anmerkungen und Funktionsgating;
- Erkennung von Konverterzielen, Ausgabe, Download und Wasserzeichenstatus;
- DICOM-Seiten, -Frames und -Animation; technische Metadaten sind in diesem Paket nicht verfügbar;
- passwortgeschützte Dokumente, benutzerdefinierte Schriften, nicht-lateinischer Text und konfigurierte Zeitüberschreitungen;
- Ablehnung von Token über Sitzungen hinweg und Verhalten bei abgelaufenen Sitzungen;
- für einen Farm: auf einem Knoten veröffentlichen, von einem anderen eine späte Seite anfordern und bestätigen, dass der Viewer
202Antworten erneut versucht, anstatt fehlerhafte Kacheln anzuzeigen; - mobil, Dark Mode und den Produktions‑Reverse‑Proxy-Pfad.
Rollback-Plan
Behalte das vorherige Bereitstellungsartefakt, passende Pakete, Lizenzdateien und kopierte Browserressourcen zusammen. Ein sicherer Rollback wechselt die gesamte Anwendungsgeneration; er mischt nicht einen Server einer vorherigen Generation mit aktuellen Skripten oder einen aktuellen Server mit new Viewer(...) Aufrufstellen.
Vor dem Umschalten dokumentieren:
- den Bereitstellungs‑Slot oder das Artefakt, das für den Rollback verwendet wird;
- die Auswirkungen auf den Shared‑Storage, falls vorhanden — Artefakte, die von 26.8.0 veröffentlicht wurden, werden nicht von der vorherigen Web‑Farm‑Middleware verwendet;
- wie aktive Dokumentsitzungen ungültig gemacht werden;
- den Health‑Check und das Smoke‑Dokument, das zur Entscheidung über den Rollback verwendet wird;
- wer das vorherige Paketsatz und die Konfiguration wiederherstellen kann.
Legacy-Dokumentation
Das übersetzte frühere Handbuch ist weiterhin verfügbar unter Legacy .NET Standard Einrichtung. Das Vorheriges Integrationsgateway erklärt dieselben Identifikationssignale und verweist zurück auf diesen Migrationsleitfaden.
Behalte die historische URL in Lesezeichen und Support‑Tickets, solange netstandard2.0‑Installationen noch existieren. Sie dokumentiert eine andere Generation und wird nicht zur aktuellen API weitergeleitet.
War diese Seite hilfreich?