Миграция

Doconut.NETFramework 26.8.0 (.NET Framework 4.7) до 26.9.0 (.NET Framework 4.7.2)

Эта страница охватывает обновление существующего приложения ASP.NET с Doconut.NETFramework 26.8.0 или более ранней версии (.NET Framework 4.7) до 26.9.0 и более поздних (.NET Framework 4.7.2). Пакет примеров Doconut содержит полное руководство по миграции и классические примеры, портированные на новый API — MVC 5, веб‑ферму и Web Forms. Сравнение вашего приложения с образцом, от которого оно началось, — самый быстрый путь.

Один пакет, две версии

Обе библиотеки публикуются под одним и тем же идентификатором пакета, Doconut.NETFramework. Версия различает их:

ВерсияЦельAPI
26.8.0 и ранее.NET Framework 4.7предыдущий API
26.9.0 и позже.NET Framework 4.7.2новый API

Обновление пакета — это обновление. Отдельного пакета для установки нет и нет уровня совместимости: 26.9.0 имеет другую поверхность API, поэтому после обновления ожидайте ошибки компиляции — см. остальную часть этой страницы. Платформа .NET Framework 4.7 прекращена, а 26.8.0 является её последним выпуском. Вы можете оставаться на ней — здесь нет исправления безопасности, которое вы могли бы пропустить — но новые релизы, плагины, распределённый режим и готовые виджеты появляются только в 26.9.0 и более поздних версиях.

1. Перенастройка и обновление пакета

Сначала перенастройте веб‑проект на .NET Framework 4.7.2: проект, который всё ещё нацелен на 4.7, не может установить 26.9.0, и NuGet отклонит обновление. Затем обновите Doconut.NETFramework и добавьте пакеты плагинов, которые вы используете (Doconut.NETFramework.Converter, Doconut.NETFramework.Dicom, …). Каждый плагин требует лицензии, которая его предоставляет.

Если проект использует packages.config, обновление выполняет шаг удаления предыдущей версии, который удаляет обработчик DocImage из Web.config, а 26.9.0 не добавляет его обратно. Зарегистрируйте его снова, как показано в шаге 3; пока вы этого не сделаете, DocImage.axd отвечает 404 и страница не отрисовывается.

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

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

Имена типов не изменились: WordConfig, PdfConfig, ExcelConfig, CssConfig, ScriptConfig, FileShareConfig и остальные всё ещё присутствуют. В большинстве файлов вся правка состоит в удалении строк using.

3. Запуск: DoconutHost.Initialize и две записи в Web.config

Классический пакет создавал свой просмотрщик для каждого запроса, с параметрами в виде свойств этого экземпляра. Новый пакет имеет корень композиции, построенный один раз в Application_Start, и просмотрщик представляет собой сервис, который вы разрешаете:

csharp
// Раньше - Doconut.NETFramework 26.8.0 и более ранних, по запросу
var viewer = new Viewer
{
    ID = "ctlDoc",
    IncludeJQuery = true,
    BasePath = "/",
    FitType = "width"
};
csharp
// Doconut.NETFramework 26.9.0\u002B - Viewer разрешён из DoconutHost, лицензия настроена один раз в DoconutHost.Initialize()
var viewer = Doconut.DoconutHost.Services.GetRequiredService<Viewer>();
var token  = await viewer.OpenDocumentAsync(path, new PdfConfig { AllowSearch = true });

DoconutHost.Initialize помещается в Application_Start, а DoconutHost.Shutdown — в Application_End, и Web.config получает обработчик DocImage.axd и модуль ресурсов — оба находятся в Установка. Параметры внешнего вида для каждой страницы (FitType, FixedZoom, ShowHyperlinks, …) перенесены из экземпляра просмотрщика в параметры виджета или в ViewerConfig, передаваемый в Viewer.RenderViewer (см. ViewerConfig). new Viewer() всё ещё компилируется после выполнения DoconutHost.Initialize, поэтому перенесённый код‑behind может сохранять эту строку, пока вы перемещаете настройки.

Безопасность работает как и раньше. Открытие документа предоставляет текущей сессии ASP.NET доступ к его страницам, а DocImage.axd отказывает всем остальным. Параметр приложения DoconutUnSafeMode, который отключал это, теперь называется options.UnsafeMode в DoconutHost.Initialize — оставьте его false. См. Сессии и безопасность.

Сбой при запуске, который выводит весь сайт из строя. Зарегистрированный плагин, возможности которого не покрываются лицензией, бросает исключение в Application_Start, и приложение затем отвечает пустым 500 на каждый запрос — нет страницы ошибки, ничего в журнале IIS, только запись в журнале событий Windows (источник ASP.NET). Лицензии читаются из wwwroot в корне сайта и нигде больше, а базовый Doconut.Viewer.lic должен присутствовать, иначе лицензии плагина рядом с ним не читаются. См. Настройка лицензий.

4. Веб‑ферма: от флага к распределённому режиму

Классическая модель была viewer.IsWebfarm = true плюс ExportToPng(path). Новая модель регистрируется один раз: каждый узел использует один хранилище и один ключ подписи, а подписанный билет, привязанный к браузеру, заменяет «какой‑нибудь узел отвечает»:

csharp
Doconut.DoconutHost.Initialize(
    options => options.UnsafeMode = false,
    services => services.AddDoconutDistributed(d =>
    {
        d.Store             = CloudLocation.FileShare;
        d.FileShareRootPath = @"\\fileserver\doconut-shared";   // WebfarmPath — псевдоним
        d.SigningKey        = farmKey;                           // >= 32 байт, одинаково на каждом узле
    }));

Затем открывайте документы обычным способом, привязывая браузер (DocOptions.BrowserId = DoconutFarmBinding.EnsureBrowserId(...)) и передавая viewer.AccessToken виджету вместе с токеном. Сеансы и безопасность содержит шаги; пример веб‑фермы — это полноценный узел. IsWebfarm и WebfarmPath всё ещё компилируются, но они больше ничего не переключают.

Две вещи, которые выглядят как успех, но таковыми не являются: DistributedDocumentPublisher.PublishAsync записывает отрендеренные файлы документа, но не открывает сеанс, поэтому просмотрщик, указывающий на опубликованный токен, получает ошибочное изображение ~2 KB со статусом 200; и тестовый клиент без cookie doconut-client получает то же изображение, а не 401. Отличайте реальную страницу от изображения ошибки по размеру.

5. Преобразование — это плагин, и оно гораздо меньше

Перечисление SourceFormatConverter, двенадцать классов *ConfigConverter и их вложенные целевые перечисления заменены одним перечислением ConversionTarget и одним вызовом:

csharp
using System.IO;
using System.Threading;
using Doconut;
using Doconut.Configs.Conversion;

// Предположим, DoconutHost уже инициализирован и CancellationToken с именем ct доступен.
var provider = DoconutHost.Services;
var converter = (DocumentConverter)provider.GetService(typeof(DocumentConverter));
Stream source = /* ваш входной поток */;
var result = await converter.ConvertAsync(source, ".dwg", ConversionTarget.Pdf, null, ct);

Исходный формат берётся из переданного расширения. Совместимости нет: каждая ссылка SourceFormatConverter приводит к ошибке компиляции, которую нужно решить удалением. Объекты параметров для каждого формата не выжили — WordConfigConverter.HtmlOptions и CadConfigConverter.CadOptions.ShowColor не имеют эквивалента через ConvertAsync. В Web Forms никогда не блокируйте ConvertAsync — см. Плагин конвертера.

6. Облачное хранилище: доступ к нему как к общей папке

Типы конфигурации облака перенесены в Doconut.Clouds без изменений. Обработчики запросов к облаку, однако, являются компонентами ASP.NET Core, и классическое приложение не имеет конвейера для их выполнения. С сайта System.Web получайте доступ к облачному хранилищу как к общей папке — в Azure это общий ресурс Azure Files, смонтированный на каждом узле — доступный через FileShareConfig.

7. Изменения на клиенте, которые молча не работают

Каждый пункт ниже компилируется, запускается, ничего не логирует и делает неверное.

ДоТеперь
ResPath: 'doconut-res'ResPath: 'doconut-res/images' — иначе каждый значок возвращает 404, пока документ рендерится
function ctlDoc_ViewerReady() { }docViewer({ onViewerReady: function () { } }) — обратные вызовы просмотрщика теперь являются опциями
var viewer = $(el).docViewer({...}).View(token)Сначала назначьте docViewer(...), затем вызовите viewer.View(token) отдельно
viewer.Refit() для подгонки под страницуviewer.FitType('width') — Refit() только пересчитывает макет
var n = viewer.Search(kw, exact)viewer.Search(kw, exact, function (n) { … }) — количество приходит в обратном вызове
if (viewer.SaveAnnotations()) { … }docViewer({ onAnnSaved: …, onAnnSaveError: … })
function ctlDoc_Created() { } (аннотации)Не изменено — функции событий аннотаций всё ещё глобальны, находятся по имени

Три дополнительных момента: просмотрщик не рисует собственную панель инструментов (ваша страница подключает Zoom, Next, GotoPage и остальные к своим кнопкам); просмотрщик, созданный внутри скрытого модального окна Bootstrap, имеет размеры 0×0 и ничего не рисует, пока вы не зададите его контейнеру явную высоту и не подгоните его при shown.bs.modal; и AllowSearch по умолчанию использует false для PDF, поэтому документ отображается идеально, в то время как каждый поиск ничего не возвращает.

8. Что исчезает

УшлоВместо
DocumentSearch / TextSearch.csНичего — поиск работает по тексту, который извлекают просмотрщики форматов
Viewer.WatermarkInfoНет эквивалента
WordConfigConverter.HtmlOptionsНет объектных опций через ConvertAsync
SourceFormatConverter, классы *ConfigConverterConversionTarget и ConvertAsync
Doconut.Configs.EditorУдалено
viewer.IsWebfarm + ExportToPng(path)AddDoconutDistributed и обычное открытие

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

  1. Перенаправьте, замените пакет и заставьте Global.asax компилироваться с DoconutHost.Initialize и двумя регистрациями Web.config. Сайт должен запуститься.
  2. Одна страница просмотрщика: получите документ для отображения, затем пройдите через раздел 7, пока панель инструментов, поиск и аннотации не начнут работать. Проверьте в реальном браузере — в этом разделе не возникает ошибок.
  3. Конверсия (раздел 5): механическая, и большинство ошибок компиляции.
  4. Оставшиеся страницы, используя портированные образцы в качестве целевого diff.
  5. Веб‑ферма (раздел 4), если она у вас есть. Тестируйте с двумя узлами и браузером или клиентом, который сохраняет cookies.

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