DoconutExtensions
Service and middleware registration
DoconutExtensions (namespace Doconut.Middleware) is the static class with the three calls every Doconut host makes: one service registration and two middleware registrations.
builder.Services.AddDoconut(options => { /* … */ });
// …
app.UseDoconutResources(); // BEFORE UseDoconut()
app.UseDoconut();AddDoconut
IServiceCollection AddDoconut(this IServiceCollection services, Action<DoconutOptions>? configure = null)Builds the DoconutOptions, validates them fail-fast (see DoconutOptions → Startup validation), and registers the full service graph:
| Service | Lifetime | Role |
|---|---|---|
DoconutOptions | Singleton | The configuration object |
IViewerFactory | Singleton | Maps extensions to format viewers |
IDocumentSessionManager | Singleton | Token → session cache (IMemoryCache is registered too) |
IDoconutLicenseService | Singleton | License loaded once at startup (precedence: LicenseStream → LicenseContent → LicensePath → auto-search) |
PageImageService | Singleton | Page-image pipeline (watermark/rotate/scale/annotations) |
| Document security (access store) | Singleton | Grants for token-to-session binding |
Viewer | Transient | The public open/close facade |
DocumentConverter | Transient | Conversion facade — requires the Converter plugin |
DistributedDocumentPublisher | — | Publishes a document's artifacts to shared storage |
Health check "doconut" | — | Reports license/expiry state through ASP.NET health checks |
There is no equivalent call in the previous .NET Standard library. It constructed
new Viewer(cache, accessor) per request and passed options to the middleware; both are
replaced by this single registration.
Two behaviors worth knowing:
- Converter requires its plugin. Resolving
DocumentConverterwithoutoptions.AddPlugin<ConverterPlugin>()throws:
InvalidOperationException: No IDocumentConverter is registered. Add the converter plugin: options.AddPlugin<Doconut.Plugins.Converter.ConverterPlugin>().- Plugin entitlement is validated at startup. A missing license, legacy
TRIALfile, or paid license without a registered plugin's capability fails atAddDoconut()time. Temporary/Demo registrations survive their expiry date, while runtime gates revoke the expired capabilities.
The health check integrates with the standard ASP.NET Core mechanism — map it if you want license state on your health endpoint:
app.MapHealthChecks("/health");UseDoconut
IApplicationBuilder UseDoconut(this IApplicationBuilder app)Adds the Doconut page-image middleware. It answers every request carrying a ?token= query parameter — pages, thumbnails, search, annotations, page actions (the full request table is in Core Concepts → How the Viewer Works). When UnsafeMode is false, the document-security layer is wired in automatically before it.
It takes no arguments. Passing a DoconutOptions instance here was the previous
library's shape and no longer compiles.
The reference sample routes the widget's requests through a path branch, keeping the historic request shape:
app.MapWhen(
ctx => ctx.Request.Path.Value?.EndsWith("DocImage.axd", StringComparison.OrdinalIgnoreCase) == true,
branch => branch.UseDoconut());UseDoconutResources
IApplicationBuilder UseDoconutResources(this IApplicationBuilder app)Serves the embedded JS, CSS, images, and fonts at DoconutOptions.ResourcesPath (default /doconut-res). These are the files that Viewer.ReferenceCss() / ReferenceScripts() emit tags for.
Always call it before UseDoconut(). If the viewer area stays empty and the browser console shows 404s for /doconut-res/..., this call is missing or misplaced.
This is the supported replacement for wiring the embedded-resource middleware by hand with
app.UseMiddleware<EmbeddedResourceMiddleware>().
Serving from shared storage
Two further registrations exist for deployments where the node that renders a document is not necessarily the node that serves its pages. Both are covered end to end in Distributed Deployments; the signatures are:
IServiceCollection AddDoconutDistributedAsyncPublish(...) // opt-in background publish queue
IServiceCollection AddDoconutDistributedWidgets(...) // shared backing store for widget uploadsThe read side is a separate middleware from the Doconut.Clouds package:
IApplicationBuilder UseDoconutCloud<THandler>(
this IApplicationBuilder app,
Action<CloudOptions>? configure = null,
string pathPrefix = "/doconut-cloud")
where THandler : BaseCloudHandlerUseDoconutWebFarm(...) and WebFarmOptions do not exist in this release. See the
migration guide for the setting-by-setting mapping.
Ordering recap
app.UseRouting();
app.UseSession(); // required when UnsafeMode = false
app.UseDoconutResources(); // 1st Doconut call
app.UseDoconut(); // 2nd Doconut call (or via a MapWhen branch)Was this page helpful?