Plugin System
Extend the viewer with plugins
Doconut's core stays lean; optional functionality ships as plugins — separate NuGet packages that contribute viewers or services and are switched on by your license. This page explains the registration model, what happens at startup when a license does not cover a plugin, and how to plug in your own viewer.
Registering a plugin
Each plugin package exposes one plugin class. Register it once, in Application_Start:
Doconut.DoconutHost.Initialize(options =>
{
options.AddPlugin<Doconut.Plugins.Converter.ConverterPlugin>();
options.AddPlugin<Doconut.Plugins.Dicom.DicomPlugin>();
});
// A registered plugin whose license is missing throws here, in Application_Start, and the
// site then answers every request with an empty 500. The reason is in the Windows event log.AddPlugin<TPlugin>() creates the plugin and lets it register its contributions with DoconutOptions. Everything a plugin contributes is tagged with the plugin's required capability, and DoconutHost.Initialize checks every registered plugin against the license before the site serves its first request.
A missing plugin license stops the site
When no active license grants a registered plugin's capability — no license at all, a legacy TRIAL file, or a paid license without that capability — DoconutHost.Initialize throws InvalidOperationException from Application_Start:
The Converter plugin is registered via AddPlugin but no active license grants Converter.
Remove the AddPlugin<...>() call or install a license (or trial/demo) that includes Converter.In System.Web, an exception in Application_Start does not produce an error page. Every request answers an empty 500, the IIS log shows nothing useful, and the message appears only in the Windows event log (Application log, source ASP.NET). When a site stops responding right after an AddPlugin line was added, check the license files in wwwroot first — see License Setup.
The contract
A plugin implements a deliberately small interface:
public interface IDoconutPlugin
{
string Name { get; } // e.g. "Doconut DICOM Viewer"
LicenseCapability RequiredCapability { get; } // the license gate
void Register(IDoconutPluginBuilder builder); // contribute viewers/services
}Inside Register, the builder accepts two kinds of contribution:
builder.RegisterViewer(".dcm", () => new DicomViewer())— a viewer for a file extension,builder.RegisterService<TContract>(() => …)— a typed service other parts of the pipeline can look up.
Capabilities and gating
Capabilities are the license units. Converter and Dicom ship as opt-in plugins; Search and Annotation are built-in features gated the same way. The base viewer is not a capability — it is the prerequisite, exposed as IsViewerLicensed on the license service.
Startup validation normally keeps an unlicensed plugin out of the request pipeline. The viewer factory also applies two defensive rules, which matter if entitlements change while the site runs:
- A plugin that overrides a built-in viewer (it claims an extension a built-in viewer also handles): with the capability licensed, the plugin's viewer wins; without it, Doconut falls back to the built-in viewer. Users still see their document; they just don't get the plugin's behavior.
- A plugin-only format (
.dcmand.ima— DICOM has no built-in viewer): without the capability, opening fails:
LicenseException: This document type requires the 'Dicom' plugin license.An active Temporary license grants every capability. That is a classic go-live surprise: the same AddPlugin lines that ran during evaluation stop the site when the purchased license omits one of those capabilities. Compare IsCapabilityGranted(...) with what you bought before deploying. With no license at all, nothing is granted — a missing license is not a Temporary license.
The same gating reaches the browser: Viewer.ReferenceScripts() and ReferenceCss() emit the files for license-gated features (Search, Annotation) only when the license grants them, so the page never offers a feature the server will refuse.
Feature and plugin map
| Feature | How it is enabled | Capability | Contributes |
|---|---|---|---|
| Annotation | Built into the viewer; include the annotation resources | Annotation | Browser authoring, session persistence, burned-in exports |
| Search | Built into searchable format viewers; include the search resources | Search | Native text index, highlights, result navigation |
| Converter | Install Doconut.NETFramework.Converter and register ConverterPlugin | Converter | C# conversion service and an optional web widget |
| DICOM | Install Doconut.NETFramework.Dicom and register DicomPlugin | Dicom | Medical-image viewing for .dcm and .ima |
Annotation and Search do not use AddPlugin<TPlugin>(). Converter and DICOM each have a page under Plugins with their configuration and usage. On this package, DICOM renders pages, frames, and animations, but does not read technical metadata — see DICOM Plugin.
Custom viewers — your own format handler
You can plug a viewer into the pipeline without writing a plugin package, directly in Application_Start:
Doconut.DoconutHost.Initialize(options =>
{
options.RegisterViewer(
".myext",
() => new MyCustomViewer(), // implements IFormatViewer
() => new ImageConfig { ImageResolution = 150 }); // optional default config
});Custom viewers take precedence over everything — built-ins and plugins alike — and are not license-gated: they are your code. When you supply no default config, the factory uses an ImageConfig.
Takeaways
- Plugins are registered explicitly in
DoconutHost.Initialize, and their capabilities are validated there; a missing entitlement stops the site with an empty500whose reason is in the Windows event log. - Override-style plugins degrade gracefully; plugin-only formats fail with a
LicenseException. - An active Temporary license unlocks everything; production unlocks what you bought. Check with
IDoconutLicenseServicebefore shipping.
Questa pagina è stata utile?