Миграция на .NET Standard 2.1

Перенос существующего приложения Doconut.NETStandard с версии 26.7.0 на 26.8.0

Doconut имеет два разных интеграционных решения для .NET Standard. Они используют одно и то же имя пакета Doconut.NETStandard, поэтому определите поколение по версии и API в приложении перед изменением пакетов, настроек запуска, лицензий или ресурсов браузера.

Версия — это развилочка

Оба поколения публикуются под одним и тем же идентификатором пакета. Только версия различает их:

ВерсияЦельAPI
26.7.0 и нижеnetstandard2.0предыдущий API
26.8.0 и вышеnetstandard2.1текущий API

Повышение номера версии — это обновление. Нет отдельного пакета для установки и нет совместимого shim — 26.8.0 имеет иной набор API. Ожидайте ошибок компиляции после повышения версии; остальная часть руководства — это их список.

Какую интеграцию вы используете?

Если проект содержит…Поколение
new Viewer(_cache, _accessor, ...)Предыдущее
viewer.OpenDocument(...) (синхронный)Предыдущее
viewer.InitCache()Предыдущее
UseDoconut(new DoconutOptions { ... })Предыдущее
UseDoconutWebFarm(...) / WebFarmOptionsПредыдущее
Viewer.DoconutLicense(...) или Viewer.SetLicensePlugin(...)Предыдущее
viewer.Converter.GetConverter()Предыдущее
using Doconut.Configs; / using Doconut.Models;Предыдущее
Вручную скопированный docViewer.js, documentLinks.js или docViewer.UI.jsПредыдущее
builder.Services.AddDoconut(...)Текущее
app.UseDoconutResources() и app.UseDoconut() без аргументовТекущее
Viewer, предоставляемый внедрением зависимостейТекущее
await viewer.OpenDocumentAsync(...)Текущее

Если обе колонки встречаются в одном приложении, рассматривайте миграцию как незавершённую. Не отправляйте токен документа через ресурсы или middleware из другого поколения.

Сначала проверьте целевую платформу

Это жёсткое ограничение, а не предпочтение. Текущий пакет нацелен на netstandard2.1:

ХостМожет использовать 26.8.0
.NET Core 3.0 или позже (включая .NET 5/6/7/8)Да
.NET Framework, любой версииНет

.NET Framework не может ссылаться на библиотеку netstandard2.1. Если приложение работает на .NET Framework, остановитесь здесь и используйте пакет Doconut.NETFramework; начиная с версии 26.9.0 он требует .NET Framework 4.7.2. Оба референсных приложения для этого релиза нацелены на net8.0.

Перед миграцией

  1. Создайте ветку и развертываемую резервную копию существующего приложения.
  2. Запишите точные версии основных и плагин‑пакетов.
  3. Составьте инвентарь всех вызовов new Viewer(...), вызовов InitCache(), загрузки лицензий, сопоставлений UseDoconutWebFarm, контроллеров конверсии, скопированных скриптов Doconut, пользовательских действий панели инструментов, обратных вызовов viewer и конечных точек открытия документов.
  4. Сохраните текущие файлы .lic и секреты развертывания вне системы контроля версий.
  5. Соберите репрезентативный набор PDF, Office, изображений, CAD, email, DICOM, документов с возможностью поиска, защищённых паролем и аннотированных.
  6. Запишите текущие параметры таймаута сессии, поведения безопасности, шрифтов и настроек платформы.

Перенесите одну среду перед изменением продакшна. Текущая интеграция меняет время жизни сервисов, маршрутизацию запросов, владение сессией, доставку клиентских ресурсов и — если вы используете ферму — способ доставки страниц в браузер.

1. Пространства имён: почти всё перенесено в корень

Типы конфигурации были распределены по четырём пространствам имён. Теперь они все находятся в Doconut.

ДоСейчас
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;не изменено
using Doconut.Middleware;не изменено

Имена типов не изменились: WordConfig, PdfConfig, ExcelConfig, CssConfig, ScriptConfig, CloudUploadConfig, AzureConfig, CDNConfig, FileShareConfig и остальные по‑прежнему доступны. В большинстве файлов единственное изменение — удаление двух строк using.

Doconut.Configs.Editor (BaseConfigEditor, PdfConfigEditor) был удалён и не имеет замены в этом пакете. Если ваше приложение ссылалось на эти типы, планируйте эту часть отдельно и не рассматривайте её как часть миграции.

2. Совместимость пакетов и лицензий

Заменяйте или обновляйте основной пакет осознанно; не полагайтесь на идентичный ID пакета для выбора нового API. Команда по умолчанию устанавливает последнюю стабильную версию:

bash
dotnet add package Doconut.NETStandard

Для воспроизводимой миграции к выпуску, проверенному в этом руководстве, укажите версию как отдельный параметр:

bash
dotnet add package Doconut.NETStandard --version 26.8.0

Держите каждый плагин Doconut на той же версии, что и основной пакет — Doconut.NETStandard.Converter и Doconut.NETStandard.Dicom. Текущая интеграция загружает лицензии один раз во время AddDoconut(), используя следующий приоритет:

text
LicenseStream > LicenseContent > LicensePath > automatic discovery

Автоматическое обнаружение ищет файлы Doconut.Viewer.lic и сопутствующие Doconut.Viewer.<Capability>.lic. Предыдущие статические вызовы Viewer.DoconutLicense(...) и Viewer.SetLicensePlugin(...) больше не являются механизмом запуска, как и List<string> путей лицензий, которые принимал старый конструктор Viewer. Переместите лицензию в DoconutOptions, храните сопутствующие файлы вместе при использовании автоматического обнаружения, перезапустите приложение после изменения лицензии и проверьте возможности через IDoconutLicenseService.

Не следует полагать, что наличие старой лицензии плагина подтверждает право на текущую сборку плагина. Тестируйте Viewer, Search, Annotation, Converter и DICOM отдельно, используя утверждённые артефакты выпуска.

3. Запуск и внедрение зависимостей

Ранее Viewer создавался для каждого запроса, а параметры передавались в middleware:

csharp
// Предыдущая интеграция — только для сравнения; не компилируйте этот код с текущим SDK.
var viewer = new Viewer(_cache, _accessor);
// …
appBranch.UseDoconut(new DoconutOptions { UnSafeMode = false, ShowDoconutInfo = false });

Текущая интеграция регистрирует Doconut один раз и получает Viewer через внедрение зависимостей:

csharp
builder.Services.AddDoconut(options =>
{
    options.UnsafeMode      = false;   // обратите внимание на изменение написания: UnSafeMode → UnsafeMode
    options.ShowDoconutInfo = false;
    options.LicensePath     = "Doconut.Viewer.lic";
});
builder.Services.AddDistributedMemoryCache(); // состояние сессии требует кэш (MVC/Razor Pages уже добавляют один)
builder.Services.AddSession();

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

Viewer является транзиентным сервисом. Менеджер сессий документа и его кэш владеют более долгоживущим состоянием документа, а не конкретным внедрённым экземпляром Viewer.

Три момента, которые нужно перенести:

  • new Viewer(cache, accessor) удалён. Внедрите Doconut.Viewer в ваш контроллер или используйте @inject Doconut.Viewer Viewer в Razor‑view.
  • UseDoconutResources() заменяет ручную привязку app.UseMiddleware<EmbeddedResourceMiddleware>() и должен выполняться до ветки документа.
  • UnSafeMode → UnsafeMode. Переименование на один символ будет обнаружено компилятором.

Когда UnsafeMode установлен в false, SDK проверяет токен сессии относительно исходного запроса, поэтому AddSession() / UseSession() всё равно должны находиться в конвейере, а UseSession() — перед веткой.

Методы, которые больше не существуют

БылоСейчас
viewer.OpenDocument(path, config, options)await viewer.OpenDocumentAsync(path, config, options)
viewer.InitCache()удалено — ничего вручную разогревать не нужно; удалите вызов и любые флаги типа «уже инициализировано»
viewer.ExportToPng(sharedPath)см. §7
viewer.ExportToCloud(cloudConfig)см. §7
using var v = new Viewer(...); v.CloseDocument(t)viewer.CloseDocument(token) у внедрённого экземпляра

4. Middleware и маршрутизация ресурсов

UseDoconut() теперь не принимает аргументов. Форма ветки MapWhen менять не требуется — меняется только middleware внутри неё:

csharp
app.UseDoconutResources();   // ДО ветки

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

В текущем конвейере:

  1. вызывайте UseSession() до Doconut, пока включена защита сессии;
  2. вызывайте UseDoconutResources() до UseDoconut();
  3. держите ResourcesPath, сгенерированные URL‑ы ресурсов и клиентский ResPath согласованными;
  4. держите сопоставленную ветку и клиентский BasePath согласованными.

MiddlewarePath — проверенная конфигурация; она сама по себе не создаёт ветку ASP.NET Core.

5. Конструирование и жизненный цикл 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 });
});

Возвращённый токен идентифицирует серверную сессию документа. Обращайтесь с ним как с токеном‑носителем: не регистрируйте его, не сохраняйте и не передавайте в аналитические системы.

6. Открытие и закрытие документов

Замените синхронный OpenDocument(...) на OpenDocumentAsync(...):

csharp
// Текущая интеграция: Viewer получен из DI, а открытие документа происходит асинхронно.
var token = await viewer.OpenDocumentAsync(path, new PdfConfig { AllowSearch = true });

Текущие перегрузки принимают путь к файлу или поток, необязательную конфигурацию формата, необязательный DocOptions и токен отмены. Явно закрывайте серверную сессию, когда браузер больше её не нуждается:

csharp
viewer.CloseDocument(token);

Удалите любые вызовы InitCache() и соответствующий флаг — нечего прогревать вручную. Не переиспользуйте токен, созданный предыдущей библиотекой после перехода: открывайте каждый документ заново через текущий API.

7. Web farm → distributed: самое большое изменение

UseDoconutWebFarm и WebFarmOptions больше не существуют. Если ваше приложение вызывает их, этот раздел — ваше обновление; если нет, переходите к §8.

Ранее один middleware делал всё: он обслуживал предварительно отрисованные изображения из общей папки и опросил пока другой узел ещё записывал их.

csharp
// Предыдущая интеграция — один вызов, неявная координация через файловую систему.
appBranch.UseDoconutWebFarm(new WebFarmOptions
{
    Path                = Path.Combine(env.WebRootPath, "webfarm"),
    PageWaitTimeSeconds = 180,
    StartWaitFromPage   = 5,
});

Та же задача теперь разделена на две явные части. Сторона записи — узел, открывающий документ, публикует весь набор артефактов (страницы, информацию о документе, поисковый индекс, метаданные) в общий ресурс:

csharp
var result = await _publisher.PublishAsync(          // DistributedDocumentPublisher, внедренный через DI
    pathToFile,
    new FileShareConfig
    {
        Location              = CloudLocation.FileShare,
        RootPath              = @"\\fileserver\doconut",   // тот же каталог, который вы используете сегодня
        UsePerTokenSubfolders = true,
    },
    config,
    documentOptions,
    new DistributedDocumentPublishOptions
    {
        CleanUpStagingDirectory = true,
        FirstPagePriority       = true,
    });

return Content(result.Token);

Сторона чтения — любой узел обслуживает из общего ресурса:

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 = /* тот же FileShareConfig, что выше */;
    }, "/"));
ДоСейчас
WebFarmOptions.PathFileShareConfig.RootPath
PageWaitTimeSeconds / StartWaitFromPageудалено — заменено FirstPagePriority на стороне записи плюс FileShareConfig.ReadReadyPollMs на стороне чтения
viewer.OpenDocument(...) затем viewer.ExportToPng(share)один вызов PublishAsync(...)
DocOptions.IsWebfarm / WebfarmPathпо‑прежнему присутствует, назван IsWebFarm / WebFarmPath — но не нужен в пути публикации

Ваша топология не меняется. Укажите RootPath на тот же UNC‑ресурс, и каждый узел будет работать так же, как сейчас. Изменяется лишь то, что публикация становится вызываемой операцией, а не побочным эффектом рендеринга.

Обе части должны согласовываться. Если RootPath или UsePerTokenSubfolders различаются между публикующим и обработчиком, другой узел вернёт 404. Сформируйте конфигурацию в одном вспомогательном методе и вызывайте её с обеих сторон.

PageWaitTimeSeconds = 180 означал «блокировать до трёх минут в ожидании появления страницы». Замена явная: с FirstPagePriority = true страница 1 становится доступной сразу, а последующие страницы отвечают HTTP 202 Accepted, пока не будут записаны. Встроенный viewer автоматически повторяет запросы, когда установлен retryOn409. Клиент, который не делает повторов, будет видеть сломанные плитки для ещё рендерящихся страниц.

Полная схема, включая фоновую публикацию и билеты доступа, описана в разделе Распределённые развертывания.

8. Конвертация — это плагин, и гораздо меньше

Зарегистрируйте плагин, затем внедрите фасад DocumentConverter:

csharp
builder.Services.AddDoconut(o => o.AddPlugin<ConverterPlugin>());
csharp
// Предыдущая интеграция
var converter = viewer.Converter.GetConverter();
var config    = new WordConfigConverter { TargetFormat = WordConfigConverter.EnTargetFormat.PDF };
var result    = converter.Convert(stream, SourceFormatConverter.DOCX, config);

// Текущая интеграция
var result = await _converter.ConvertAsync(stream, ".docx", ConversionTarget.Pdf, null, ct);

Что это заменяет:

  • SourceFormatConverter — удалён. Передавайте расширение файла как строку, включая точку.
  • Типы *ConfigConverter для каждой семьи (WordConfigConverter, ExcelConfigConverter, …), каждый с вложенным перечислением EnTargetFormat — удалены. Теперь существует одно перечисление ConversionTarget для каждой семьи.
  • viewer.Converter.GetConverter() — удалён. Внедрите Doconut.DocumentConverter.

ConvertAsync возвращает поток, поддерживающий поиск, поэтому return File(result, mime, name) работает напрямую — копия MemoryStream, необходимая в старом коде, не нужна. В поставляемом примере это удалило переключатель расширений с 68 случаями и десять почти одинаковых контроллеров.

Смотрите Плагин конвертера для полного описания.

9. Облачные провайдеры

UseDoconutCloud стал обобщённым. Провайдер теперь передаётся как типовой аргумент вместо значения Location, переключаемого внутри middleware:

csharp
// Предыдущая интеграция
appBranch.UseDoconutCloud(new CloudOptions { Location = CloudLocation.CDN, ... });

// Текущая интеграция
branch.UseDoconutCloud<CDNCloudHandler>(options =>
{
    options.Location          = CloudLocation.CDN;
    options.CloudUploadConfig = new CDNConfig { DoconutCdnUrl = "..." };
}, "/");

Классы конфигурации остались без изменений, за исключением пространства имён (Doconut.Configs.Cloud → Doconut.Clouds): AzureConfig, AmazonConfig, GoogleCloudConfig, DropBoxConfig, RedisConfig, CDNConfig, FTPConfig, а также новый FileShareConfig. Обработчики называются <Provider>CloudHandler.

Обработчик CDN является только для чтения — он обслуживает то, что уже находится на CDN; загрузка не производится.

10. Объекты конфигурации, названия которых изменились

РаньшеСейчас
DoconutOptions.UnSafeModeUnsafeMode
DocOptions.IsWebfarmIsWebFarm
DocOptions.WebfarmPathWebFarmPath
DocOptions.ImageResolutionвсё ещё присутствует, но устарел — задавайте разрешение в конфигурации формата вместо этого

DocOptions также получает IsSecured.

Текущий API также более строго разделяет ответственности по сравнению с предыдущим, поэтому проверьте, что каждая настройка находится в объекте, которому она теперь принадлежит:

ОбластьТекущий тип
Пути middleware, лицензирование, регистрация плагиновDoconutOptions
Пароль, тайм‑аут, безопасность, водяной знакDocOptions
Отрисовка формата и DPIPdfConfig, WordConfig, ExcelConfig и другие типы BaseConfig
Настройки виджета браузера по умолчаниюViewerConfig или эквивалентные параметры JavaScript
Сгенерированные CSS и скриптыCssConfig и ScriptConfig
Общее хранилище и облачные провайдерыFileShareConfig и остальные конфигурации из Doconut.Clouds

Не переносите DocOptions.ImageResolution как управление отрисовкой. Он устарел; задавайте BaseConfig.ImageResolution в конфигурации конкретного формата. Пересмотрите все значения по умолчанию, вместо того чтобы предполагать, что прежняя конфигурация ведёт себя так же.

11. Клиентский просмотрщик — два изменения, которые тихо не работают

Оба этих изменения оставляют сервер в полностью рабочем состоянии. Ваш документ рендерится, страница выглядит правильно, и в консоли браузера ничего не появляется. Прочитайте этот раздел, даже если ваш C# компилируется с первой попытки.

Обратные вызовы просмотрщика теперь являются опциями, а не глобальными функциями

Предыдущий просмотрщик вызывал ваши обработчики по имени, формируя глобальное имя функции из идентификатора контейнера. Достаточно было объявить function ctlDoc_OnViewerReady() на странице с <div id="div_ctlDoc">. Текущий просмотрщик принимает явные обратные вызовы в объекте опций и больше не ищет эти глобальные функции:

javascript
objctlDoc = $("#div_ctlDoc").docViewer({
    // ... ваши текущие параметры ...
    onViewerBusy:     ctlDoc_OnViewerBusy,      // было найдено по имени
    onViewerReady:    ctlDoc_OnViewerReady,     // было найдено по имени
    onCopy:           ctlDoc_Copy,              // было ctlDoc_Copy(text)
    onAutoLoadStatus: ctlDoc_AutoLoadStatus     // было ctlDoc_AutoLoadStatus(page)
});

Почему это проблематично: старый вызов был обёрнут в пустой catch, который глотал все ошибки. Теперь ваши функции просто не вызываются, и об ошибке ничего не сообщается. Обычный симптом — индикатор загрузки, который никогда не останавливается, потому что функция, скрывающая его, была ctlDoc_OnViewerReady. Сам документ при этом в порядке.

Полный список опций: onPageLoading, onPageLoaded, onThumbnailClicked, onPageClicked, onDoubleClick, onViewerBusy, onViewerReady, onViewerError, onCopy, onAnnSaved, onAnnSaveError, onAnnLoaded, onAnnClosed, onAutoLoadStatus, onThumbsShown и onError. Обратного вызова при клике по ссылке нет: обработка гиперссылок встроена и управляется параметром showHyperlinks.

ResPath должен указывать на префикс ресурса

javascript
ResPath: '',                      // РАНЬШЕ — ресурсы поступали из корня приложения
ResPath: 'doconut-res/images',    // СЕЙЧАС — префикс, который монтирует UseDoconutResources()

Если вы изменили префикс через DoconutOptions.ResourcesPath, используйте это значение вместо него.

12. Панель инструментов Viewer, поиск и аннотации

Не переносите старые скрипты по одному. Текущие справочные приложения собирают один полный пакет страницы:

  1. выпустить CSS Viewer и лицензированный CSS поиска/аннотаций с помощью ReferenceCss;
  2. отрисовать панель инструментов Viewer, принадлежащую приложению;
  3. отрисовать searchBarMount, annBarMount и необходимый монтировщик Viewer;
  4. выпустить скрипты Viewer и лицензированных модулей с помощью ReferenceScripts;
  5. загрузить собственный вспомогательный скрипт панели инструментов приложения;
  6. инициализировать один objViewer;
  7. инициализировать лицензированные ленты поиска и аннотаций;
  8. вызвать attach(objViewer) для каждой ленты;
  9. открыть документ и вызвать objViewer.View(token).

Поиск и аннотации — это модули, присоединённые к тому же Viewer, а не независимые панели инструментов. Основная панель принадлежит хост‑приложению; ленты поиска и аннотаций являются встроенными, ограниченными возможностями ресурсами.

Удаляйте вручную скопированные файлы, такие как documentLinks.js и docViewer.UI.js, только после того, как текущая страница начнёт работать с ресурсами, выпущенными ReferenceCss и ReferenceScripts.

13. Регистрация плагинов

Статические методы лицензирования плагинов не регистрируют текущие плагины. Установите и зарегистрируйте каждый выпущенный пакет явно:

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

AddDoconut() проверяет зарегистрированные возможности плагинов при запуске. Converter и DICOM — это выпущенные плагины .NET Standard. Обычные поиск и аннотации — встроенные лицензированные функции, а не пакеты AddPlugin<TPlugin>().

14. Сессия и безопасность документов

Текущая интеграция привязывает документы к непрозрачным токенам и кэшированным сессиям. При значении по умолчанию UnsafeMode = false UseDoconut() добавляет безопасность доступа к документу, и хост должен настроить ASP.NET‑сессию:

csharp
builder.Services.AddDistributedMemoryCache(); // состояние сессии требует кэш (MVC/Razor Pages уже добавляют один)
builder.Services.AddSession();
app.UseSession();

Оставляйте DocOptions.IsSecured = true, если только проверенный дизайн не требует иного. Никогда не используйте UnsafeMode = true как миграционный ярлык на отдельном узле. Тестируйте запросы без токена, с повреждённым токеном, с истёкшим токеном и с токеном из другой сессии браузера.

В ферме запрос страницы может попасть на узел, который никогда не видел начального запроса, поэтому проверка per‑session отклонит его. Это единственный случай, когда UnsafeMode = true допустим — и его необходимо сочетать с подписанными билетами доступа через AddDoconutDistributedDocumentSecurity, а не использовать отдельно. См. Распределённые развертывания.

Примечание к именованию

Во всех фреймворках класс называется Viewer. Если вы встречаете DocumentViewer в старых фрагментах кода или сторонних статьях, такого типа никогда не было в SDK.

15. Предлагаемый порядок работы

  1. Убедитесь, что хостовый фреймворк может использовать netstandard2.1. Если нет — остановитесь.
  2. Обновите пакет до 26.8.0 и соберите проект. Разберите ошибки компиляции — большинство связаны со строками using в §1.
  3. Перенесите инициализацию в AddDoconut() и вызовы middleware в их новый порядок (§3, §4).
  4. Внедрите Viewer там, где вы его создавали, сделайте OpenDocument асинхронным и удалите InitCache() (§5, §6).
  5. Если вы используете веб‑ферму, выполните §7 — единственная часть, требующая редизайна, а не переименования.
  6. Если вы конвертируете документы, выполните §8.
  7. Выполните §11 — изменения на клиенте. Это те изменения, которые не объявятся сами.
  8. Откройте реальный документ в браузере и наблюдайте за индикатором загрузки. Зеленая сборка ничего не доказывает: лицензирование, регистрация плагинов, путь к ресурсам и обратные вызовы viewer могут провалиться только во время выполнения. Для фермы проверьте, что документ, опубликованный на одном узле, обслуживается другим.

Тестирование миграции

Как минимум, проверьте:

  • запуск приложения с производственной лицензией и всеми зарегистрированными плагинами;
  • CSS/скрипты Viewer и все запросы изображений страниц по выбранным путям;
  • открытие документа, навигация, масштабирование, миниатюры, печать и явное закрытие;
  • поиск в документе с текстом и отсутствие возможности поиска в файле, содержащем только изображения;
  • загрузка, сохранение, экспорт аннотаций и управление возможностями;
  • обнаружение целей конвертера, вывод, загрузка и состояние водяного знака;
  • страницы, кадры и анимация DICOM; технические метаданные недоступны в этом пакете;
  • документы, защищённые паролем, пользовательские шрифты, нелатинский текст и настроенные тайм‑ауты;
  • отклонение токенов между сессиями и поведение при истёкшей сессии;
  • для фермы: опубликовать на одном узле, запросить позднюю страницу с другого и убедиться, что Viewer повторно запрашивает ответы 202, а не отображает сломанные плитки;
  • мобильные устройства, тёмный режим и путь обратного прокси в продакшене.

План отката

Сохраните предыдущий артефакт развертывания, соответствующие пакеты, файлы лицензий и скопированные ресурсы браузера вместе. Безопасный откат переключает всю генерацию приложения; он не смешивает сервер предыдущего поколения с текущими скриптами или текущий сервер с вызовами new Viewer(...).

Перед переключением задокументируйте:

  • слот развертывания или артефакт, используемый для отката;
  • влияние на общие хранилища, если таковое имеется — артефакты, опубликованные в версии 26.8.0, не используются предыдущим промежуточным ПО веб‑фермы;
  • как будут инвалидированы активные сессии документов;
  • проверка состояния (health check) и тестовый документ, используемый для решения об откате;
  • кто может восстановить предыдущий набор пакетов и конфигурацию.

Унаследованная документация

Переведённое предыдущее руководство доступно по ссылке Унаследованная настройка .NET Standard. Предыдущий шлюз интеграции объясняет те же сигналы идентификации и ссылается обратно на это руководство по миграции.

Сохраняйте исторический URL в закладках и служебных запросах, пока установки netstandard2.0 ещё существуют. Он описывает другую генерацию и не перенаправляется на текущий API.

Была ли эта страница полезной?