Migration

Doconut.NETFramework 26.8.0 (.NET Framework 4.7) to 26.9.0 (.NET Framework 4.7.2)

This page covers upgrading an existing ASP.NET application from Doconut.NETFramework 26.8.0 or earlier (.NET Framework 4.7) to 26.9.0 and later (.NET Framework 4.7.2). The Doconut samples package carries the complete migration guide and the classic samples ported to the new API — MVC 5, a web farm, and Web Forms. Diffing your application against the sample it started from is the fastest path.

One package, two versions

Both libraries publish under the same package ID, Doconut.NETFramework. The version tells them apart:

VersionTargetAPI
26.8.0 and earlier.NET Framework 4.7the previous API
26.9.0 and later.NET Framework 4.7.2the new API

Updating the package is the upgrade. There is no separate package to install and no compatibility layer: 26.9.0 is a different API surface, so expect compile errors after the update — the rest of this page. The .NET Framework 4.7 line is discontinued and 26.8.0 is its last release. You can stay on it — nothing here is a security fix you would miss — but new releases, plugins, the distributed mode, and the drop-in widgets arrive only on 26.9.0 and later.

1. Retarget and update the package

Retarget the web project to .NET Framework 4.7.2 first: a project that still targets 4.7 cannot install 26.9.0, and NuGet refuses the update. Then update Doconut.NETFramework and add the plugin packages you use (Doconut.NETFramework.Converter, Doconut.NETFramework.Dicom, …). Each plugin needs a license that grants it.

If the project uses packages.config, the update runs the previous version's uninstall step, which removes the DocImage handler from Web.config, and 26.9.0 does not add it back. Register it again as shown in step 3; until you do, DocImage.axd answers 404 and no page paints.

2. Namespaces: almost everything moved to the root

BeforeNow
using Doconut.Configs.View;using Doconut;
using Doconut.Models;using Doconut;
using Doconut.Configs;using Doconut;
using Doconut.Configs.Cloud;using Doconut.Clouds;
using Doconut.Configs.Conversion;unchanged

Type names did not change: WordConfig, PdfConfig, ExcelConfig, CssConfig, ScriptConfig, FileShareConfig and the rest are all still there. In most files the whole edit is deleting using lines.

3. Startup: DoconutHost.Initialize and two Web.config entries

The classic package built its viewer per request, with options as properties of that instance. The new package has a composition root, built once in Application_Start, and the viewer is a service you resolve:

csharp
// Before - Doconut.NETFramework 26.8.0 and earlier, per request
var viewer = new Viewer
{
    ID = "ctlDoc",
    IncludeJQuery = true,
    BasePath = "/",
    FitType = "width"
};
csharp
// Doconut.NETFramework 26.9.0+ - Viewer resolved from DoconutHost, license configured once in DoconutHost.Initialize()
var viewer = Doconut.DoconutHost.Services.GetRequiredService<Viewer>();
var token  = await viewer.OpenDocumentAsync(path, new PdfConfig { AllowSearch = true });

DoconutHost.Initialize goes in Application_Start and DoconutHost.Shutdown in Application_End, and Web.config gains the DocImage.axd handler and the resource module — both are in Installation. The per-page appearance settings (FitType, FixedZoom, ShowHyperlinks, …) moved from the viewer instance to the widget's options, or to a ViewerConfig passed to Viewer.RenderViewer (see ViewerConfig). new Viewer() still compiles once DoconutHost.Initialize has run, so migrated code-behind can keep that line while you move the settings.

Security works as before. Opening a document grants the current ASP.NET session access to its pages, and DocImage.axd refuses everyone else. The DoconutUnSafeMode app setting that switched this off is now options.UnsafeMode in DoconutHost.Initialize — leave it false. See Sessions & Security.

The startup failure that takes the whole site down. A registered plugin whose capability no license grants throws in Application_Start, and the application then answers an empty 500 to every request — no error page, nothing in the IIS log, only an entry in the Windows event log (source ASP.NET). Licenses are read from wwwroot under the site root and nowhere else, and the base Doconut.Viewer.lic must be present or the plugin licenses beside it are not read. See License Setup.

4. Web farm: from a flag to the distributed mode

The classic model was viewer.IsWebfarm = true plus ExportToPng(path). The new model is registered once: every node shares one store and one signing key, and a signed ticket bound to the browser replaces "whichever node answers":

csharp
Doconut.DoconutHost.Initialize(
    options => options.UnsafeMode = false,
    services => services.AddDoconutDistributed(d =>
    {
        d.Store             = CloudLocation.FileShare;
        d.FileShareRootPath = @"\\fileserver\doconut-shared";   // WebfarmPath is an alias
        d.SigningKey        = farmKey;                           // >= 32 bytes, the same on every node
    }));

Then open documents normally, binding the browser (DocOptions.BrowserId = DoconutFarmBinding.EnsureBrowserId(...)) and handing viewer.AccessToken to the widget with the token. Sessions & Security has the steps; the web-farm sample is a complete node. IsWebfarm and WebfarmPath still compile, but they no longer switch anything on.

Two things that look like success and are not: DistributedDocumentPublisher.PublishAsync writes a document's rendered files but opens no session, so a viewer pointed at a published token gets the ~2 KB error image with status 200; and a test client without the doconut-client cookie gets that same image, not a 401. Tell a real page from the error image by size.

5. Conversion is a plugin, and much smaller

The SourceFormatConverter enum, the twelve *ConfigConverter classes, and their nested target enums are replaced by one enum, ConversionTarget, and one call:

csharp
// Before
var converterPlugin = viewer.Converter.GetConverter();
var config = new CadConfigConverter();
((CadConfigConverter)config).TargetFormat = CadConfigConverter.EnTargetFormat.PDF;
var result = converterPlugin.Convert(streamFile, SourceFormatConverter.DWG, config);

// Now
var converter = Doconut.DoconutHost.Services.GetRequiredService<DocumentConverter>();
var result = await converter.ConvertAsync(file.InputStream, ".dwg", ConversionTarget.Pdf, null, ct);

The source format comes from the extension you pass. There is no compatibility shim: every SourceFormatConverter reference is a compile error you resolve by deleting it. The per-format option objects did not survive — WordConfigConverter.HtmlOptions and CadConfigConverter.CadOptions.ShowColor have no equivalent through ConvertAsync. In Web Forms, never block on ConvertAsync — see Converter Plugin.

6. Cloud storage: reach it as a shared folder

The cloud configuration types moved to Doconut.Clouds unchanged. The cloud request handlers, however, are ASP.NET Core components, and a classic application has no pipeline to run them in. From a System.Web site, reach cloud storage as a shared folder — on Azure, an Azure Files share mounted on each node — addressed through FileShareConfig.

7. The client-side changes that fail silently

Every item below compiles, runs, logs nothing, and does the wrong thing:

BeforeNow
ResPath: 'doconut-res'ResPath: 'doconut-res/images' — otherwise every icon 404s while the document renders
function ctlDoc_ViewerReady() { }docViewer({ onViewerReady: function () { } }) — viewer callbacks are options now
var viewer = $(el).docViewer({...}).View(token)Assign docViewer(...) first, then call viewer.View(token) separately
viewer.Refit() to fit a pageviewer.FitType('width') — Refit() only recalculates the layout
var n = viewer.Search(kw, exact)viewer.Search(kw, exact, function (n) { … }) — the count arrives in the callback
if (viewer.SaveAnnotations()) { … }docViewer({ onAnnSaved: …, onAnnSaveError: … })
function ctlDoc_Created() { } (annotations)Unchanged — annotation event functions are still globals, found by name

Three more: the viewer does not draw its own toolbar (your page wires Zoom, Next, GotoPage and the rest to its own buttons); a viewer created inside a hidden Bootstrap modal measures 0×0 and paints nothing until you give its container an explicit height and refit it on shown.bs.modal; and AllowSearch defaults to false for PDF, so a document renders perfectly while every search returns nothing.

8. What disappears

GoneInstead
DocumentSearch / TextSearch.csNothing — search runs on the text the format viewers extract
Viewer.WatermarkInfoNo equivalent
WordConfigConverter.HtmlOptionsNo option objects through ConvertAsync
SourceFormatConverter, the *ConfigConverter classesConversionTarget and ConvertAsync
Doconut.Configs.EditorRemoved
viewer.IsWebfarm + ExportToPng(path)AddDoconutDistributed and ordinary opening

Suggested order of work

  1. Retarget, swap the package, and get Global.asax compiling with DoconutHost.Initialize and the two Web.config registrations. The site should start.
  2. One viewer page: get a document to render, then work through section 7 until the toolbar, search, and annotations behave. Verify in a real browser — nothing in that section raises an error.
  3. Conversion (section 5): mechanical, and most of the compile errors.
  4. The remaining pages, using the ported samples as the diff target.
  5. The web farm (section 4), if you have one. Test with two nodes and a browser, or a client that keeps cookies.

Ήταν αυτή η σελίδα χρήσιμη;