从经典 .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.jsdocumentLinks.jsdocViewer.UI.js传统 / 经典
builder.Services.AddDoconut(...)当前集成
app.UseDoconutResources()app.UseDoconut()当前集成
通过依赖注入提供的 Viewer当前集成
await viewer.OpenDocumentAsync(...)当前集成

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

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

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

当前本指南审计的发布版本是 Doconut.NET6 26.7.0。其可选的公共包为 Doconut.NET6.ConverterDoconut.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. 在启用会话安全的情况下,先调用 UseSession() 再使用 Doconut;
  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 });
});

返回的令牌标识服务器端的文档会话。将其视为持有者凭证:不要记录、持久化或放入分析系统。

打开和关闭文档

OpenDocumentAsync(...) 替代同步的 OpenDocument(...)

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);

切换后不要复用传统令牌。请通过当前 API 再次打开每个文档。

配置类

当前 API 将关注点分离:

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

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

Viewer 工具栏、搜索和注释

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

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

搜索和注释是附加到同一个 Viewer 的模块,而不是独立的工具栏。主工具栏属于宿主应用;搜索和注释功能区是嵌入式、受功能门控的资源。

仅在当前页面能够使用 ReferenceCssReferenceScripts 发出的资源后,才删除手动复制的传统文件(如 documentLinks.jsdocViewer.UI.js)。

插件注册

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

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

AddDoconut() 会在启动时验证已注册插件的功能。Converter 与 DICOM 是已发布的 .NET 6 插件。普通的 Search 与 Annotation 是内置的授权功能,而非 AddPlugin<TPlugin>() 包。

会话和文档安全

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

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

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

分布式参考应用会添加访问票据和传输细节。这些 API 对普通单节点迁移并非必需。

测试迁移

至少验证以下内容:

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

回滚计划

保留传统部署产物、匹配的包、许可证文件以及复制的浏览器资源。安全的回滚会切换整个应用代际,而不是将传统服务器与当前脚本混用,或将当前服务器与传统 DocImage.axd 调用混用。

在切换前,记录以下内容:

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

旧版文档

已翻译的传统手册仍可在 旧版 .NET 6 设置 查看。新的 经典集成网关 解释相同的识别信号并链接回本迁移指南。

请在仍有传统安装的情况下,将历史 URL 保存在书签和支持工单中。它记录的是不同的代际,不会重定向到当前 API。

此页面有帮助吗?