从经典 .NET 6 集成迁移

将现有 Doconut.NET6 应用迁移到当前 DI 和异步 API

Doconut 有两种不同的 .NET 6 集成方式。它们可以使用相同的 Doconut.NET6 包名,因此在更改包、启动、许可证或浏览器资源之前,需要通过应用程序中的 API 来识别所属的代际版本。

您正在使用哪种 .NET 6 集成?

如果项目包含…代际
app.MapWhen(... "DocImage.axd" ...)传统/经典
new Viewer(_cache, _accessor, ...)传统/经典
Viewer.DoconutLicense(...) 或 Viewer.SetLicensePlugin(...)传统/经典
手动复制的 docViewer.js、documentLinks.js 或 docViewer.UI.js传统/经典
builder.Services.AddDoconut(...)当前集成
app.UseDoconutResources() plus app.UseDoconut()当前集成
通过依赖注入提供的 Viewer当前集成
await viewer.OpenDocumentAsync(...)当前集成

如果同一应用程序中出现了两个列的情况,则视迁移为不完整。不要在资源或中间件中使用来自另一代际的文档令牌。

为什么 NuGet 包名可能无法告诉您

这两个代际都使用 Doconut.NET6 包标识发布。因此,仅凭包引用、锁文件或缓存的 .nupkg 并不能确定所使用的 API。请记录确切的包版本,并一起检查 Program.cs、Viewer 的构造、文档打开方式以及浏览器脚本。

本指南审计的当前发布版本是 Doconut.NET6 26.7.0。其可选的公共包为 Doconut.NET6.Converter 和 Doconut.NET6.Dicom,与核心包锁定在相同的发布版本。

迁移前准备

  1. 创建一个分支并对现有应用进行可部署的备份。
  2. 记录核心包和插件包的确切版本。
  3. 清点每一个 DocImage.axd 映射、new Viewer(...) 调用、许可证加载调用、复制的 Doconut 脚本、自定义工具栏操作以及文档打开端点。
  4. 在源代码控制之外保存当前的 .lic 文件和部署机密。
  5. 获取一套具有代表性的 PDF、Office、图像、CAD、电子邮件、DICOM、可搜索、受密码保护和带批注的文档。
  6. 记录现有的会话超时、安全行为、字体和平台设置。

在更改生产环境之前,先在一个环境中进行迁移。当前的集成会改变服务生命周期、请求路由、会话所有权以及客户端资源交付方式。

包和许可证兼容性

请有意识地替换或更新核心包;不要依赖相同的包 ID 来选择新 API。默认命令会安装最新的稳定版本:

bash
dotnet add package Doconut.NET6

若要进行可复现的迁移,以匹配本指南审计的发布版本,请将版本作为单独的选项传入:

bash
dotnet add package Doconut.NET6 --version 26.7.0

保持每个 Doconut 插件与核心包版本一致。当前的集成在 AddDoconut() 时一次性加载许可证,遵循以下优先级:

text
LicenseStream > LicenseContent > LicensePath > automatic discovery

自动发现会查找 Doconut.Viewer.lic 以及配套的 Doconut.Viewer.<Capability>.lic 文件。传统的 Viewer.DoconutLicense(...) 或 Viewer.SetLicensePlugin(...) 调用已不再是当前的启动机制。请将许可证移动到 DoconutOptions,在使用自动发现时将配套文件放在一起,修改许可证后重新启动,并通过 IDoconutLicenseService 验证功能。

不要假设旧插件许可证的存在就意味着对当前插件构建的授权。请使用已批准的发布制品分别测试 Viewer、Search、Annotation、Converter 和 DICOM。

启动和依赖注入

传统应用程序使用 ASP.NET 缓存和请求访问器依赖项构造 Viewer:

csharp
// Classic integration — contrast only; do not compile this against the current SDK.
var viewer = new Viewer(_cache, _accessor, licenseFilePath);

当前集成只注册一次 Doconut,并通过依赖注入获取 Viewer:

csharp
builder.Services.AddDoconut(options =>
{
    options.LicensePath = "Doconut.Viewer.lic";
    options.UnsafeMode = false;
});
builder.Services.AddSession();

app.UseSession();
app.UseDoconutResources();
app.UseDoconut();

Viewer 是瞬态服务。文档会话管理器及其缓存拥有更长生命周期的文档状态,而不是特定注入的 Viewer 实例。

中间件和资源路由

移除检测 DocImage.axd 的传统 MapWhen 分支:

csharp
// Classic integration — remove during the cutover.
app.MapWhen(
    context => context.Request.Path.ToString().EndsWith("DocImage.axd"),
    branch => branch.UseDoconut(new DoconutOptions()));

在当前管道中:

  1. 在启用会话安全时,在 Doconut 之前调用 UseSession();
  2. 在 UseDoconut() 之前调用 UseDoconutResources();
  3. 保持 ResourcesPath、生成的资源 URL 与客户端 ResPath 对齐;
  4. 将 UseDoconut() 映射到分支时,保持该分支与客户端 BasePath 对齐。

MiddlewarePath 是已验证的配置;它本身不会创建 ASP.NET Core 分支。可以使用上面编译示例中的简单管道,或客户端始终使用的显式 app.Map("/doconut", branch => branch.UseDoconut()) 布局。

Viewer 构造和生命周期

移除应用程序拥有的 Viewer 对象缓存。将 Viewer 注入到端点、Razor 页面、控制器或作用域的应用服务中:

csharp
app.MapPost("/api/open", async (Viewer viewer) =>
{
    var token = await viewer.OpenDocumentAsync("wwwroot/files/Sample.pdf");
    return Results.Ok(new { token });
});

返回的 token 标识服务器端文档会话。将其视为持有者凭证:不要记录、持久化或用于分析。

打开和关闭文档

将同步的 OpenDocument(...) 替换为 OpenDocumentAsync(...):

csharp
// Current .NET 6 integration: Viewer comes from DI and document opening is asynchronous.
var token = await viewer.OpenDocumentAsync(path, new PdfConfig { AllowSearch = true });

当前的重载接受文件路径或流、可选的格式配置、可选的 DocOptions,以及取消令牌。当浏览器不再需要时,请显式关闭服务器会话:

csharp
viewer.CloseDocument(token);

切换后不要复用传统 token。请通过当前 API 重新打开每个文档。

配置类

当前 API 将关注点分离:

关注点当前类型
中间件路径、授权、插件注册DoconutOptions
密码、超时、安全性、水印DocOptions
格式渲染和 DPIPdfConfig、WordConfig、ExcelConfig 以及其他 BaseConfig 类型
浏览器小部件默认值ViewerConfig 或等效的 JavaScript 选项
生成的 CSS 和脚本CssConfig 与 ScriptConfig

不要将 DocOptions.ImageResolution 继续用作渲染控制。它已过时;请在特定格式的配置上设置 BaseConfig.ImageResolution。请检查所有默认值,而不要假设传统配置具有相同的行为。

Viewer 工具栏、搜索和批注

不要逐个迁移旧脚本。当前参考应用程序组合成一个完整的页面包:

  1. 使用 ReferenceCss 输出 Viewer CSS 和授权的 Search/Annotation CSS;
  2. 渲染应用拥有的 Viewer 工具栏;
  3. 渲染 searchBarMount、annBarMount 以及所需的 Viewer 挂载点;
  4. 使用 ReferenceScripts 输出 Viewer 和授权模块脚本;
  5. 加载应用自己的 viewerToolbar.js;
  6. 初始化一个 objViewer;
  7. 初始化授权的 Search 和 Annotation 功能区;
  8. 在每个功能区上调用 attach(objViewer);
  9. 打开文档并调用 objViewer.View(token)。

Search 和 Annotation 是附加到同一 Viewer 的模块,而不是独立的工具栏。主工具栏属于宿主应用程序;Search 和 Annotation 功能区是嵌入式、受功能限制的资源。

仅在当前页面能够使用 ReferenceCss 和 ReferenceScripts 输出的资源后,才移除手动复制的传统文件,如 documentLinks.js 和 docViewer.UI.js。

插件注册

传统的静态插件许可证方法不会注册当前插件。请显式安装并注册每个已发布的包:

csharp
builder.Services.AddDoconut(options =>
{
    options.AddPlugin<Doconut.Plugins.Converter.ConverterPlugin>();
    options.AddPlugin<Doconut.Plugins.Dicom.DicomPlugin>();
});

AddDoconut() 在启动时验证已注册插件的功能。Converter 和 DICOM 是已发布的 .NET 6 插件。普通搜索和注释是内置的许可功能,而不是 AddPlugin<TPlugin>() 包。

会话和文档安全

当前集成将文档绑定到不透明令牌和缓存会话。使用默认的 UnsafeMode = false,UseDoconut() 添加文档访问安全性,主机必须配置 ASP.NET 会话:

csharp
builder.Services.AddSession();
app.UseSession();

除非经审查的设计另有要求,否则保持 DocOptions.IsSecured = true。切勿将 UnsafeMode = true 用作迁移捷径。请测试没有令牌、令牌格式错误、令牌已过期以及来自不同浏览器会话的令牌的请求。

Distributed 参考应用程序添加了访问票据和传输细节。这些 API 对于普通单节点迁移不是必需的。

测试迁移

至少,需要验证:

  • 应用程序使用生产许可证和所有已注册插件启动;
  • Viewer 的 CSS/脚本以及所选路径下的所有页面图像请求;
  • 文档打开、导航、缩放、缩略图、打印以及显式关闭;
  • 在包含文本的文档上进行搜索,以及仅图像文件的不可搜索状态;
  • 注释的加载、保存、导出以及功能门控;
  • Converter 目标发现、输出、下载以及水印状态;
  • DICOM 页面、帧和动画;.NET 6 技术元数据不可用;
  • 带密码保护的文档、自定义字体、非拉丁文字以及配置的超时;
  • 跨会话令牌拒绝和会话过期行为;
  • 移动端、暗模式以及生产环境的反向代理路径。

回滚计划

保持经典部署产物、匹配的包、许可证文件和复制的浏览器资源在一起。安全的回滚会切换整个应用程序代代,而不会将经典服务器与当前脚本混合,也不会将当前服务器与经典的 DocImage.axd 调用混合。

在切换之前,记录:

  • 用于回滚的部署槽或产物;
  • 数据库/缓存的影响(如果有);
  • 活动文档会话将如何失效;
  • 用于决定回滚的健康检查和冒烟文档;
  • 谁可以恢复之前的包集合和配置。

旧版文档

已翻译的经典手册仍可在 Legacy .NET 6 setup 查看。新的 Classic integration gateway 解释相同的识别信号并链接回本迁移指南。

在经典安装仍然存在期间,请在书签和支持工单中保留该历史 URL。它记录了不同的代代,并未重定向到当前 API。

此页面对您有帮助吗?