DoconutHost

The composition root for System.Web

DoconutHost (namespace Doconut) is a static class that owns Doconut's services for the whole worker process. ASP.NET Core applications build those services into the framework's own container; classic ASP.NET has no container, so DoconutHost builds one and keeps it. The DocImage.axd handler and the resource module resolve everything they need from it, and so does your code.

MemberPurpose
static void Initialize(Action<DoconutOptions>? configure = null, Action<IServiceCollection>? configureServices = null)Builds the services — once
static IServiceProvider Services { get; }The built container
static bool IsInitialized { get; }true once Initialize has run
static void Shutdown()Stops background work and disposes the container

Initialize

Call it from Application_Start in Global.asax.cs:

csharp
// Global.asax.cs, Application_Start - once per worker process. A second call is a no-op:
// the first call's options win.
Doconut.DoconutHost.Initialize(
    options =>
    {
        options.LicensePath = HostingEnvironment.MapPath("~/wwwroot/Doconut.Viewer.lic");
    },
    services =>
    {
        // Optional. Runs after Doconut's own registrations and before the container is built,
        // so it can add services or replace one Doconut registered.
        services.AddMemoryCache();
    });
  • configure receives the DoconutOptions: license, security switches, plugins, widgets.
  • configureServices is optional. It runs after Doconut has registered its own services and before the container is built, so it can add services — AddDoconutDistributed for a web farm is the usual one — or replace a registration Doconut made.

The first call wins. Initialize is idempotent: a second call returns immediately, and neither of its delegates runs. That keeps a duplicated Application_Start harmless, but it also means configuration cannot be changed by calling Initialize again — recycle the application pool instead.

An exception thrown here — a plugin without a license, invalid options, an incomplete farm configuration — happens inside Application_Start. ASP.NET then answers every request with an empty 500, and the exception is recorded only in the Windows event log (Application log, source ASP.NET).

Services and IsInitialized

System.Web has no constructor injection for controllers, pages, or handlers, so resolve Doconut's services where you use them:

csharp
// System.Web has no constructor injection: resolve Doconut services where you use them.
var viewer = Doconut.DoconutHost.Services.GetRequiredService<Viewer>();

// Registered only when the Converter plugin is (see the plugin page).
var converter = Doconut.DoconutHost.Services.GetRequiredService<DocumentConverter>();

Services throws InvalidOperationException (DoconutHost.Initialize must be called in Application_Start (Global.asax) before any Doconut request is served.) when read before Initialize. Code that may run earlier — a module, a static constructor — can check IsInitialized first.

What your code typically resolves:

ServiceLifetimeRole
ViewerTransientOpen, close, annotations, resource helpers — see Viewer
DocumentConverterTransientConversion — registered only with the Converter plugin
IDoconutLicenseServiceSingletonThe loaded license and its capabilities — see Licensing
DoconutOptionsSingletonThe options passed to Initialize
HealthCheckServiceSingletonRuns the "doconut" health check (below)

Resolve from DoconutHost.Services, never from a container of your own. Registering Doconut into another container builds a second, separate set of services that the handler and the module never see: documents opened through it are unknown to DocImage.axd.

Shutdown

csharp
// Global.asax.cs, Application_End - stops background work and disposes the container.
// Safe to call twice, and safe when Initialize never ran.
Doconut.DoconutHost.Shutdown();

Shutdown stops Doconut's background work (used by the distributed mode) and disposes the container. It is safe to call twice, and safe when Initialize never ran — for example when the application pool recycles before the first request.

Health check

Doconut registers a health check named "doconut" that reports the license state. Classic ASP.NET has no health-check endpoint of its own, so expose it from a controller:

csharp
// GET /Health - Doconut registers a "doconut" health check that reports the license state:
// Healthy (valid), Degraded (trial or no license file), Unhealthy (expired).
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");
}
StatusMeaning
HealthyA valid license is loaded
DegradedTrial, or no license file found
UnhealthyThe license has expired

The ASP.NET Core extension methods

The package also contains UseDoconut() and UseDoconutResources(), the ASP.NET Core pipeline extensions, because it shares its code with the ASP.NET Core packages. On this package both are marked [Obsolete] and are not used: a System.Web application has no request pipeline to add them to. Their replacements are the two Web.config registrations from Installation:

ASP.NET Core.NET Framework 4.7.2
builder.Services.AddDoconut(...)DoconutHost.Initialize(...) in Application_Start
app.UseDoconut()Doconut.DocImageHandler on DocImage.axd in Web.config
app.UseDoconutResources()Doconut.DoconutResourceModule in Web.config
Constructor injectionDoconutHost.Services.GetRequiredService<T>()
Host shutdownDoconutHost.Shutdown() in Application_End

Byla tato stránka užitečná?