Migrate from the classic .NET 6 integration
Move an existing Doconut.NET6 application to the current DI and async API
Doconut has two distinct .NET 6 integrations. They can use the same Doconut.NET6
package name, so identify the generation from the APIs in the application before changing
packages, startup, licenses, or browser resources.
Which .NET 6 integration are you using?
| If the project contains… | Generation |
|---|---|
app.MapWhen(... "DocImage.axd" ...) | Legacy / classic |
new Viewer(_cache, _accessor, ...) | Legacy / classic |
Viewer.DoconutLicense(...) or Viewer.SetLicensePlugin(...) | Legacy / classic |
Manually copied docViewer.js, documentLinks.js, or docViewer.UI.js | Legacy / classic |
builder.Services.AddDoconut(...) | Current integration |
app.UseDoconutResources() plus app.UseDoconut() | Current integration |
Viewer supplied by dependency injection | Current integration |
await viewer.OpenDocumentAsync(...) | Current integration |
If both columns appear in the same application, treat the migration as incomplete. Do not send one document token through resources or middleware from the other generation.
Why the NuGet package name may not tell you
Both generations have shipped under the Doconut.NET6 package ID. A package reference,
lock file, or cached .nupkg therefore does not identify the hosting API by itself.
Record the exact package version and inspect Program.cs, viewer construction, document
opening, and browser scripts together.
The current release audited for this guide is Doconut.NET6 26.7.0. Its optional public
packages are Doconut.NET6.Converter and Doconut.NET6.Dicom, pinned to the same release
version as the core package.
Before you migrate
- Create a branch and a deployable backup of the existing application.
- Record the exact core and plugin package versions.
- Inventory every
DocImage.axdmapping,new Viewer(...)call, license-loading call, copied Doconut script, custom toolbar action, and document-open endpoint. - Preserve the current
.licfiles and deployment secrets outside source control. - Capture a representative set of PDF, Office, image, CAD, email, DICOM, searchable, password-protected, and annotated documents.
- Record the existing session timeout, security behavior, fonts, and platform settings.
Migrate one environment before changing production. The current integration changes service lifetime, request routing, session ownership, and client resource delivery.
Package and license compatibility
Replace or update the core package deliberately; do not rely on the identical package ID to select the new API. The default command installs the latest stable release:
dotnet add package Doconut.NET6For a reproducible migration to the release audited by this guide, pass the version as a separate option:
dotnet add package Doconut.NET6 --version 26.7.0Keep every Doconut plugin at the same version as the core package. The current integration
loads licenses once during AddDoconut(), using this precedence:
LicenseStream > LicenseContent > LicensePath > automatic discoveryAutomatic discovery looks for Doconut.lic, then Doconut.Viewer.lic and companion
Doconut.Viewer.<Capability>.lic files. A classic call to
Viewer.DoconutLicense(...) or Viewer.SetLicensePlugin(...) is not a current startup
mechanism. Move the license to DoconutOptions, keep companion files together when using
automatic discovery, restart after changing a license, and verify capabilities through
IDoconutLicenseService.
Do not assume that the presence of an old plugin license proves entitlement for a current plugin build. Test Viewer, Search, Annotation, Converter, and DICOM separately with the approved release artifacts.
Startup and dependency injection
Classic applications construct Viewer with ASP.NET cache and request-accessor
dependencies:
// Classic integration — contrast only; do not compile this against the current SDK.
var viewer = new Viewer(_cache, _accessor, licenseFilePath);The current integration registers Doconut once and receives Viewer from dependency
injection:
builder.Services.AddDoconut(options =>
{
options.LicensePath = "Doconut.lic";
options.UnsafeMode = false;
});
builder.Services.AddSession();
app.UseSession();
app.UseDoconutResources();
app.UseDoconut();Viewer is a transient service. The document session manager and its cache own the
longer-lived document state, not the particular injected Viewer instance.
Middleware and resource routing
Remove the classic MapWhen branch that detects DocImage.axd:
// Classic integration — remove during the cutover.
app.MapWhen(
context => context.Request.Path.ToString().EndsWith("DocImage.axd"),
branch => branch.UseDoconut(new DoconutOptions()));In the current pipeline:
- call
UseSession()before Doconut while session security is enabled; - call
UseDoconutResources()beforeUseDoconut(); - keep
ResourcesPath, the generated resource URLs, and clientResPathaligned; - when mapping
UseDoconut()to a branch, keep that branch and clientBasePathaligned.
MiddlewarePath is validated configuration; it does not create an ASP.NET Core branch
by itself. Use either the simple pipeline in the compiling sample above or an explicit
app.Map("/doconut", branch => branch.UseDoconut()) arrangement used consistently by the
client.
Viewer construction and lifetime
Remove application-owned caches of Viewer objects. Inject Viewer into an endpoint,
Razor page, controller, or scoped application service:
app.MapPost("/api/open", async (Viewer viewer) =>
{
var token = await viewer.OpenDocumentAsync("wwwroot/files/Sample.pdf");
return Results.Ok(new { token });
});The returned token identifies a server-side document session. Treat it as a bearer credential: do not log it, persist it, or place it in analytics.
Opening and closing documents
Replace synchronous OpenDocument(...) with OpenDocumentAsync(...):
// Current .NET 6 integration: Viewer comes from DI and document opening is asynchronous.
var token = await viewer.OpenDocumentAsync(path, new PdfConfig { AllowSearch = true });Current overloads accept a file path or stream, an optional format config, optional
DocOptions, and a cancellation token. Close the server session explicitly when the
browser no longer needs it:
viewer.CloseDocument(token);Do not reuse a classic token after the cutover. Open each document again through the current API.
Configuration classes
The current API separates concerns:
| Concern | Current type |
|---|---|
| Middleware paths, licensing, plugin registration | DoconutOptions |
| Password, timeout, security, watermark | DocOptions |
| Format rendering and DPI | PdfConfig, WordConfig, ExcelConfig, and other BaseConfig types |
| Browser widget defaults | ViewerConfig or the equivalent JavaScript options |
| Generated CSS and scripts | CssConfig and ScriptConfig |
Do not carry DocOptions.ImageResolution forward as the rendering control. It is
obsolete; set BaseConfig.ImageResolution on the format-specific config. Review all
defaults instead of assuming a classic config has the same behavior.
Viewer toolbar, Search, and Annotation
Do not migrate the old scripts one by one. The current reference applications compose one complete page package:
- emit Viewer CSS and licensed Search/Annotation CSS with
ReferenceCss; - render the application-owned Viewer toolbar;
- render
searchBarMount,annBarMount, and the required Viewer mount; - emit Viewer and licensed module scripts with
ReferenceScripts; - load the application's own
viewerToolbar.js; - initialize one
objViewer; - initialize the licensed Search and Annotation Ribbons;
- call
attach(objViewer)on each Ribbon; - open the document and call
objViewer.View(token).
Search and Annotation are modules attached to the same Viewer, not independent toolbars. The main toolbar belongs to the host application; the Search and Annotation Ribbons are embedded, capability-gated resources.
Remove manually copied classic files such as documentLinks.js and docViewer.UI.js
only after the current page works with resources emitted by ReferenceCss and
ReferenceScripts.
Plugin registration
Classic static plugin-license methods do not register current plugins. Install and register each released package explicitly:
builder.Services.AddDoconut(options =>
{
options.AddPlugin<Doconut.Plugins.Converter.ConverterPlugin>();
options.AddPlugin<Doconut.Plugins.Dicom.DicomPlugin>();
});AddDoconut() validates registered plugin capabilities at startup. Converter and DICOM
are released .NET 6 plugins. Normal Search and Annotation are built-in licensed features,
not AddPlugin<TPlugin>() packages.
Session and document security
The current integration binds documents to opaque tokens and cached sessions. With the
default UnsafeMode = false, UseDoconut() adds document-access security and the host
must configure ASP.NET session:
builder.Services.AddSession();
app.UseSession();Keep DocOptions.IsSecured = true unless a reviewed design requires otherwise. Never use
UnsafeMode = true as a migration shortcut. Test requests with no token, a malformed
token, an expired token, and a token from a different browser session.
The Distributed reference application adds access tickets and transport details. Those APIs are not required for a normal single-node migration.
Testing the migration
At minimum, verify:
- application startup with the production license and every registered plugin;
- Viewer CSS/scripts and all page-image requests under the chosen paths;
- document open, navigation, zoom, thumbnails, print, and explicit close;
- Search on a text-bearing document and the non-searchable state of an image-only file;
- Annotation load, save, export, and capability gating;
- Converter target discovery, output, download, and watermark state;
- DICOM pages, frames, and animation; .NET 6 technical metadata is unavailable;
- password-protected documents, custom fonts, non-Latin text, and configured timeouts;
- cross-session token rejection and expired-session behavior;
- mobile, dark mode, and the production reverse-proxy path.
Rollback plan
Keep the classic deployment artifact, matching packages, license files, and copied browser
resources together. A safe rollback switches the entire application generation; it does
not mix a classic server with current scripts or a current server with classic
DocImage.axd calls.
Before cutover, document:
- the deployment slot or artifact used for rollback;
- the database/cache impact, if any;
- how active document sessions will be invalidated;
- the health check and smoke document used to decide rollback;
- who can restore the previous package set and configuration.
Legacy documentation
The translated classic manual remains available at Legacy .NET 6 setup. The new Classic integration gateway explains the same identification signals and links back to this migration guide.
Keep the historic URL in bookmarks and support tickets while classic installations still exist. It documents a different generation and is not redirected to the current API.
Was this page helpful?