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:

VersionZielAPI
26.7.0 und darunternetstandard2.0die vorherige API
26.8.0 und darübernetstandard2.1die 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(...) / WebFarmOptionsVorherige
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.jsVorherige
builder.Services.AddDoconut(...)Aktuelle
app.UseDoconutResources() plus app.UseDoconut() with no argumentsAktuelle
Viewer supplied by dependency injectionAktuelle
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:

HostKann 26.8.0 verwenden
.NET Core 3.0 oder später (einschließlich .NET 5/6/7/8)Ja
.NET Framework, jede VersionNein

.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

  1. Erstellen Sie einen Branch und ein bereitstellbares Backup der bestehenden Anwendung.
  2. Protokollieren Sie die genauen Kern‑ und Plugin‑Paketversionen.
  3. Inventarisieren Sie jeden new Viewer(...) Aufruf, InitCache() Aufruf, Lizenz‑Ladeaufruf, UseDoconutWebFarm Zuordnung, Konvertierungscontroller, kopiertes Doconut‑Skript, benutzerdefinierte Symbolleistenaktion, Viewer‑Callback und Dokument‑Öffnen‑Endpunkt.
  4. Bewahren Sie die aktuellen .lic Dateien und Bereitstellungsgeheimnisse außerhalb der Versionskontrolle auf.
  5. Erfassen Sie ein repräsentatives Set von PDF‑, Office‑, Bild‑, CAD‑, E‑Mail‑, DICOM‑, durchsuchbaren, passwortgeschützten und kommentierten Dokumenten.
  6. 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.

VorherJetzt
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:

bash
dotnet add package Doconut.NETStandard

Für eine reproduzierbare Migration zur in diesem Leitfaden geprüften Version übergeben Sie die Versionsnummer als separate Option:

bash
dotnet add package Doconut.NETStandard --version 26.8.0

Halten 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:

text
LicenseStream > LicenseContent > LicensePath > automatic discovery

Die 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:

csharp
// 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:

csharp
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 Sie Doconut.Viewer in Ihren Controller oder verwenden Sie @inject Doconut.Viewer Viewer in einer Razor‑View.
  • UseDoconutResources() ersetzt das manuelle Verdrahten von app.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

VorherJetzt
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:

csharp
app.UseDoconutResources();   // VOR dem Branch

app.MapWhen(
    ctx => ctx.Request.Path.Value?.EndsWith("DocImage.axd", StringComparison.OrdinalIgnoreCase) == true,
    branch => branch.UseDoconut());

Im aktuellen Pipeline:

  1. Rufen Sie UseSession() vor Doconut auf, während die Sitzungs‑Sicherheit aktiviert ist;
  2. Rufen Sie UseDoconutResources() vor UseDoconut() auf;
  3. Behalten Sie ResourcesPath, die generierten Ressourcen‑URLs und den Client ResPath ausgerichtet bei;
  4. Behalten Sie den Zweig, den Sie zuordnen, und den Client BasePath ausgerichtet 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:

csharp
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(...):

csharp
// 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:

csharp
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.

csharp
// 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:

csharp
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:

csharp
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 */;
    }, "/"));
BeforeNow
WebFarmOptions.PathFileShareConfig.RootPath
PageWaitTimeSeconds / StartWaitFromPageweg — ersetzt durch FirstPagePriority auf der Schreibseite plus FileShareConfig.ReadReadyPollMs auf der Leseseite
viewer.OpenDocument(...) dann viewer.ExportToPng(share)ein PublishAsync(...) Aufruf
DocOptions.IsWebfarm / WebfarmPathimmer 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.
Wenn RootPath oder UsePerTokenSubfolders zwischen 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:

csharp
builder.Services.AddDoconut(o => o.AddPlugin<ConverterPlugin>());
csharp
// 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 *ConfigConverter Typen (WordConfigConverter, ExcelConfigConverter, …), jeder mit einem verschachtelten EnTargetFormat Enum — entfernt. Jetzt gibt es für jede Familie ein ConversionTarget Enum.
  • viewer.Converter.GetConverter() — entfernt. Injizieren Sie Doconut.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:

csharp
// 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

VorherJetzt
DoconutOptions.UnSafeModeUnsafeMode
DocOptions.IsWebfarmIsWebFarm
DocOptions.WebfarmPathWebFarmPath
DocOptions.ImageResolutionnoch 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ändigkeitAktueller Typ
Middleware‑Pfade, Lizenzierung, Plugin‑RegistrierungDoconutOptions
Passwort, Timeout, Sicherheit, WasserzeichenDocOptions
Format‑Rendering und DPIPdfConfig, WordConfig, ExcelConfig, und andere BaseConfig Typen
Browser‑Widget‑StandardwerteViewerConfig oder die entsprechenden JavaScript‑Optionen
Generiertes CSS und SkripteCssConfig und ScriptConfig
Gemeinsamer Speicher und Cloud‑AnbieterFileShareConfig 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:

javascript
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

javascript
ResPath: '',                      // VORHER — Ressourcen kamen aus dem Anwendungsstamm
ResPath: 'doconut-res/images',    // JETZT    — das Präfix UseDoconutResources() wird gemountet

Wenn 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:

  1. Geben Sie Viewer‑CSS und lizenziertes Such‑/Annotations‑CSS mit ReferenceCss aus;
  2. Rendern Sie die von der Anwendung bereitgestellte Viewer‑Symbolleiste;
  3. Rendern Sie searchBarMount, annBarMount und die erforderliche Viewer‑Einbindung;
  4. Geben Sie Viewer‑ und lizenzierte Modulscripte mit ReferenceScripts aus;
  5. Laden Sie das eigene Toolbar‑Hilfsskript der Anwendung;
  6. Initialisieren Sie ein objViewer;
  7. Initialisieren Sie die lizenzierten Such‑ und Annotations‑Ribbons;
  8. Rufen Sie attach(objViewer) für jedes Ribbon auf;
  9. Ö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:

csharp
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:

csharp
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

  1. Bestätigen Sie, dass das Host‑Framework netstandard2.1 konsumieren kann. Wenn nicht, stoppen Sie.
  2. 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.
  3. Verschieben Sie den Startvorgang zu AddDoconut() und die Middleware‑Aufrufe in ihre neue Reihenfolge (§3, §4).
  4. Injizieren Sie Viewer dort, wo Sie es konstruiert haben, machen Sie OpenDocument asynchron und löschen Sie InitCache() (§5, §6).
  5. Wenn Sie die Web‑Farm verwenden, führen Sie §7 aus — der einzige Teil, der ein Redesign und keine Umbenennung ist.
  6. Wenn Sie Dokumente konvertieren, führen Sie §8 aus.
  7. Führen Sie §11 aus — die clientseitigen Änderungen. Diese werden sich nicht von selbst ankündigen.
  8. Ö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 202 Antworten 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?