DoconutHost

Корневой элемент композиции для System.Web

DoconutHost (namespace Doconut) — это статический класс, который владеет сервисами Doconut для всего рабочего процесса. Приложения ASP.NET Core внедряют эти сервисы в собственный контейнер фреймворка; классический ASP.NET не имеет контейнера, поэтому DoconutHost создает его и хранит. Обработчик DocImage.axd и модуль ресурсов получают всё, что им нужно, из него, так же как и ваш код.

ЧленНазначение
static void Initialize(Action<DoconutOptions>? configure = null, Action<IServiceCollection>? configureServices = null)Создаёт сервисы — один раз
static IServiceProvider Services { get; }Созданный контейнер
static bool IsInitialized { get; }true один раз после того, как Initialize выполнен
static void Shutdown()Останавливает фоновые задачи и освобождает контейнер

Инициализация

Вызовите её из Application_Start в Global.asax.cs:

csharp
// Global.asax.cs, Application_Start — один раз на процесс‑рабочий. Второй вызов — без действия:
// опции первого вызова выигрывают.
Doconut.DoconutHost.Initialize(
    options =>
    {
        options.LicensePath = HostingEnvironment.MapPath("~/wwwroot/Doconut.Viewer.lic");
    },
    services =>
    {
        // Необязательно. Выполняется после собственных регистраций Doconut и до построения контейнера,
        // чтобы можно было добавить сервисы или заменить один, зарегистрированный Doconut.
        services.AddMemoryCache();
    });
  • configure получает DoconutOptions: лицензия, переключатели безопасности, плагины, виджеты.
  • configureServices необязателен. Он запускается после того, как Doconut зарегистрировал свои сервисы и до того, как контейнер построен, поэтому может добавить сервисы — обычно используется AddDoconutDistributed для веб-фермы — или заменить регистрацию, сделанную Doconut.

Первый вызов выигрывает. Initialize идемпотентен: второй вызов возвращает сразу, и ни один из его делегатов не выполняется. Это делает дублированный Application_Start безвредным, но также означает, что конфигурацию нельзя изменить, вызвав Initialize снова — вместо этого перезапустите пул приложений.

Исключение, выброшенное здесь — плагин без лицензии, недопустимые параметры, неполная конфигурация фермы — происходит внутри Application_Start. Затем ASP.NET отвечает на каждый запрос пустым 500, а исключение записывается только в журнал событий Windows (журнал Приложений, источник ASP.NET).

Сервисы и IsInitialized

System.Web не поддерживает внедрение через конструктор для контроллеров, страниц или обработчиков, поэтому получайте сервисы Doconut там, где вы их используете:

csharp
// System.Web не поддерживает внедрение через конструктор: разрешайте сервисы Doconut там, где вы их используете.
var viewer = Doconut.DoconutHost.Services.GetRequiredService<Viewer>();

// Регистрируется только когда подключён плагин Converter (см. страницу плагина).
var converter = Doconut.DoconutHost.Services.GetRequiredService<DocumentConverter>();

Services бросает InvalidOperationException (DoconutHost.Initialize must be called in Application_Start (Global.asax) before any Doconut request is served.), если читается до Initialize. Код, который может выполниться раньше — модуль, статический конструктор — может сначала проверить IsInitialized.

Что обычно разрешает ваш код:

СервисВремя жизниРоль
ViewerВременныйОткрытие, закрытие, аннотации, вспомогательные ресурсы — см. Просмотрщик
DocumentConverterВременныйКонверсия — зарегистрирована только с плагином Converter
IDoconutLicenseServiceОдиночныйЗагруженная лицензия и её возможности — см. Лицензирование
DoconutOptionsОдиночныйПараметры, переданные в Initialize
HealthCheckServiceОдиночныйВыполняет проверку состояния "doconut" (ниже)

Получайте из DoconutHost.Services, никогда не из собственного контейнера. Регистрация Doconut в другом контейнере создаёт второй, отдельный набор сервисов, который обработчик и модуль никогда не видят: документы, открытые через него, неизвестны DocImage.axd.

Остановка

csharp
// Global.asax.cs, Application_End — останавливает фоновую работу и освобождает контейнер.
// Безопасно вызывать дважды и безопасно, если Initialize никогда не запускался.
Doconut.DoconutHost.Shutdown();

Shutdown останавливает фоновые задачи Doconut (используемые в распределённом режиме) и освобождает контейнер. Безопасно вызывать дважды, и безопасно, если Initialize никогда не запускался — например, когда пул приложений перезапускается до первого запроса.

Проверка состояния

Doconut регистрирует проверку состояния с именем "doconut", которая сообщает о состоянии лицензии. Классический ASP.NET не имеет собственного конечного пункта проверки состояния, поэтому откройте её через контроллер:

csharp
// GET /Health — Doconut регистрирует проверку состояния здоровья "doconut", которая сообщает о состоянии лицензии:
// Здоровый (действительный), Ухудшенный (пробный или файл лицензии отсутствует), Нездоровый (истёк).
public async Task<ActionResult> Index()
{
    var health = Doconut.DoconutHost.Services.GetRequiredService<HealthCheckService>();
    HealthReport report = await health.CheckHealthAsync();

    Response.StatusCode = report.Status == HealthStatus.Unhealthy ? 503 : 200;
    return Content(report.Status.ToString(), "text/plain");
}
СтатусЗначение
HealthyЗагружена действительная лицензия
DegradedПробная версия или файл лицензии не найден
UnhealthyСрок действия лицензии истёк

Методы расширения ASP.NET Core

Пакет также содержит UseDoconut() и UseDoconutResources(), расширения конвейера ASP.NET Core, поскольку он использует общий код с пакетами ASP.NET Core. В этом пакете оба помечены [Obsolete] и не используются: приложение System.Web не имеет конвейера запросов, к которому их можно добавить. Их заменой являются две регистрации Web.config из Установка:

ASP.NET Core.NET Framework 4.7.2
builder.Services.AddDoconut(...)DoconutHost.Initialize(...) в Application_Start
app.UseDoconut()Doconut.DocImageHandler на DocImage.axd в Web.config
app.UseDoconutResources()Doconut.DoconutResourceModule в Web.config
Внедрение через конструкторDoconutHost.Services.GetRequiredService<T>()
Остановка хостаDoconutHost.Shutdown() в Application_End

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