Viewer
The main document viewer class
Viewer (namespace Doconut) is the public entry point for opening documents from Razor pages, MVC controllers, Blazor components, or minimal APIs. It is sealed, registered as a transient service by AddDoconut(), and resolved via constructor injection — never construct it directly.
Viewer holds no per-request state and intentionally does not implement IDisposable: document sessions live independently in the session cache, so disposing the service could never tear down an open document (see Core Concepts → How the Viewer Works).
OpenDocumentAsync
Opens a document and returns the session token the client widget uses for all subsequent requests.
| Overload | Use when |
|---|---|
Task<string> OpenDocumentAsync(string filePath, DocOptions? options = null, CancellationToken ct = default) | Opening from disk with automatic format detection and the format's default config |
Task<string> OpenDocumentAsync(string filePath, BaseConfig? config, DocOptions? options = null, CancellationToken ct = default) | You need per-format rendering options (PdfConfig, WordConfig, …) |
Task<string> OpenDocumentAsync(Stream stream, FileInfo fileInfo, BaseConfig? config = null, DocOptions? options = null, CancellationToken ct = default) | The document isn't a file on disk (upload, database, blob). fileInfo must carry the correct extension — it drives format detection |
// Simple open
string token = await viewer.OpenDocumentAsync(path);
// With per-format config and options
token = await viewer.OpenDocumentAsync(
path,
new PdfConfig { AllowSearch = true, AllowCopy = true },
new DocOptions { TimeOut = 30 });
// From an upload
await using var ms = new MemoryStream();
await file.CopyToAsync(ms);
ms.Position = 0;
token = await viewer.OpenDocumentAsync(ms, new FileInfo(file.FileName));Exceptions to handle:
LicenseException— a found license is rejected (the message carries the rejection reason), or the format needs a plugin capability that is no longer granted. Calendar expiry without a rejection message degrades to watermarked rendering instead of throwing.FormatNotSupportedException—Document format '<extension>' is not supported.InvalidDataException— the file content is corrupt or doesn't match its extension.
CloseDocument
void CloseDocument(string token)Removes the session from the cache (disposing the document engine immediately), deletes the security marker, and revokes the access grant. Optional — sliding expiration performs the same cleanup — but recommended for large documents.
GetPageCount
int GetPageCount(string token)Total pages of the open session. Throws if the token is unknown or expired.
DocOptions
Per-open, format-independent options (namespace Doconut):
| Type | Property | Default | Description |
|---|---|---|---|
string | Password | "" | Password for protected documents (copied into the format config automatically). |
int | ImageResolution | 0 | Obsolete. Kept for compatibility only — set ImageResolution on the format config instead. |
string | Watermark | "" | Custom watermark text drawn on rendered pages. Format string: "^Text~Color~FontSize~FontName~Opacity~Angle", e.g. "^Sample Copy~Red~24~Verdana~80~-45". |
int | TimeOut | 60 | Session sliding-expiration in minutes. |
bool | IsSecured | true | Not currently enforced — reserved. Token binding is controlled globally by DoconutOptions.UnsafeMode (see Core Concepts → Sessions & Security). |
The class also exposes specialized properties that are intentionally outside the normal single-host viewing flow:
| Type | Property | Default | Description |
|---|---|---|---|
bool | IsWebFarm | false | Marks the open operation as a web-farm scenario. Use only with the corresponding shared storage/session architecture. |
string | WebFarmPath | "" | Shared path used by the specialized web-farm workflow. Empty in the normal single-host viewer. |
bool | EditMode | false | Reserved for the separately distributed Editor workflow; leave false for the standard viewer. |
Custom watermark
DocOptions.Watermark uses six tilde-separated fields. An optional leading ^ requests the all-corners layout:
^Text~Color~FontSize~FontName~Opacity~Anglestring token = await viewer.OpenDocumentAsync(
path,
new PdfConfig(),
new DocOptions
{
Watermark = "^Confidential~Red~24~Verdana~80~-45",
TimeOut = 30
});| Field | Example | Meaning |
|---|---|---|
Leading ^ | ^ | Optional all-corners layout. Without it, normal watermark placement is used. |
| Text | Confidential | Text rendered on each page. It must not be empty. |
| Color | Red | Named color understood by the drawing layer. |
| FontSize | 24 | Font size; invalid numeric input falls back to the renderer default. |
| FontName | Verdana | Requested font family. Ensure it is installed in the deployment environment. |
| Opacity | 80 | Byte value from 0 to 255. It must parse successfully. |
| Angle | -45 | Rotation angle in degrees; invalid numeric input falls back to the default. |
The parser expects exactly six fields after the optional ^. An invalid definition is replaced by the SDK's visible Invalid Watermark fallback instead of silently disappearing.
License decision
| License state | Custom value supplied | Rendered result |
|---|---|---|
| Valid paid viewer license | No | Clean page |
| Valid paid viewer license | Yes | Custom watermark |
| Active Temporary/Demo base viewer | No | Clean base-viewer page |
| Active Temporary/Demo base viewer | Yes | Custom watermark when the clean base-viewer path applies |
| Missing, rejected, expired, wrong-version, or invalid-domain license | Either | Enforcement/evaluation watermark; the custom value does not override it |
| Plugin rendering under evaluation rules | Either | Evaluation watermark |
The same decision is applied to served page images and annotation exports. Animated GIF output is stamped frame by frame. A custom watermark is therefore a licensed application feature, not a way to replace or suppress the evaluation watermark.
Annotations API
Server-side annotation loading and export. The full walkthrough lives in Guides → Annotations; the surface is:
| Member | Purpose |
|---|---|
AnnotationManager GetAnnotationManager(string token) | Manager bound to the open session's page dimensions |
AnnotationManager GetAnnotationManager(string token, int pageWidth, int pageHeight) | Manager with explicit page dimensions |
AnnotationManager GetAnnotationManager(int pageWidth, int pageHeight) | Session-independent manager |
void LoadAnnotationData(string token, AnnotationManager manager) | Load annotations built in C# into the session |
void LoadAnnotationData(string token, string annotationData) | Load annotations from the encoded page/Base64 envelope returned by AnnotationManager.GetAnnotationData() |
void LoadAnnotationXML(string token, XmlDocument annotationXml) | Load annotations from XML |
XmlDocument GetAnnotationXML(string token) | Export the session's annotations as XML |
Task<byte[]> ExportAnnotationsToPdfAsync(string token, int zoom = 100, CancellationToken ct = default) | PDF with annotations burned in |
Task<int> ExportAnnotationsToPngAsync(…) | PNG files with annotations burned in |
Task<byte[]> ExportAnnotationsToPngZipAsync(string token, int zoom = 100, CancellationToken ct = default) | ZIP of per-page PNGs with annotations burned in |
DICOM metadata
Task<DicomMetadata?> GetDicomMetadataAsync(string token, CancellationToken ct = default)Returns DICOM tag metadata for sessions opened through the DICOM plugin; null for non-DICOM documents.
Resource helpers — ReferenceCss / ReferenceScripts
Emit the <link>/<script> tags for the embedded resources served by UseDoconutResources(), in correct dependency order. Bundles for license-gated features such as search and annotation are emitted only when the license enables them, keeping the client UI consistent with server behavior.
string ReferenceCss(CssConfig? config = null) // null → Bootstrap + viewer + search + annotation
string ReferenceScripts(ScriptConfig? config = null)CssConfig flags: IncludeBootstrapCss, IncludeViewerCss, IncludeSearchCss (search-gated), IncludeAnnotationCss (annotation-gated).
ScriptConfig flags: IncludeJQuery (required by all others), IncludeBootstrap, IncludeViewerScripts (core: docViewer.js + splitter + links), IncludeSearchScripts and IncludeSearchBar (search-gated), IncludeAnnotationScripts and IncludeAnnotationBar (annotation-gated).
@inject Doconut.Viewer Viewer
@Html.Raw(Viewer.ReferenceCss(new CssConfig { IncludeBootstrapCss = true, IncludeViewerCss = true }))
@Html.Raw(Viewer.ReferenceScripts(new ScriptConfig { IncludeJQuery = true, IncludeViewerScripts = true }))Was this page helpful?