How the Viewer Works

The document request lifecycle

Doconut renders documents as paginated images, served by an HTTP handler your Web.config registers. Understanding the lifecycle — open, token, page requests, close — explains almost every behavior you will observe, including the error messages.

The moving parts

  • Viewer — the public service you resolve from DoconutHost.Services. It opens documents and returns session tokens.
  • The document session — a server-side object holding the loaded document, kept in memory under its token.
  • DocImage.axd — the Doconut.DocImageHandler declared in Web.config. It answers every request the browser widget makes (pages, thumbnails, search, annotations, …), always identified by the token.
  • /doconut-res/* — the Doconut.DoconutResourceModule, which serves the widget's own scripts, styles, and icons.

Viewer is stateless — by design

Viewer holds no per-request document state and does not implement IDisposable. Sessions live independently of it and are cleaned up by expiration or an explicit CloseDocument(token). System.Web has no constructor injection, so resolve it where you need it — typically in a controller action:

csharp
// POST /ViewerApi/Open?fileName=Sample.pdf
[HttpPost]
public async Task<ActionResult> Open(string fileName)
{
    var viewer = Doconut.DoconutHost.Services.GetRequiredService<Viewer>();
    var path   = Server.MapPath("~/files/" + Path.GetFileName(fileName));

    var token = await viewer.OpenDocumentAsync(path);
    return Content(token, "text/plain");
}

What happens inside OpenDocumentAsync

  1. License gate. A rejected license (tampered, blacklisted, or a build outside the license's update window) throws LicenseException immediately, with the reason as the message. Opening never silently degrades for an invalid license; a missing license only watermarks.
  2. Session creation. The viewer factory picks the format viewer for the file extension and loads the document (see Rendering Pipeline). The session is stored in memory under a new random token with a sliding expiration of DocOptions.TimeOut minutes (default 60). Every page request resets the clock.
  3. Access grant. With UnsafeMode = false (the default), the token is bound to the ASP.NET session of the request that opened it: a secure-{token} entry is written into that session. The open must therefore run in a request with session state — see Sessions & Security.
  4. The token is returned. It is the only identifier the browser needs for everything that follows.

The asynchronous overloads take a file path, a file path plus a per-format config (PdfConfig, WordConfig, …), or a Stream plus a FileInfo whose extension selects the format. For Web Forms code-behind that does not use asynchronous pages, OpenDocument offers the same three inputs synchronously (a path, a stream with a file name, or a byte array with a file name).

How the widget gets pages

The widget calls DocImage.axd with the token in the query string. What the handler does depends on the request:

QueryPurpose
?token=…&page=NRendered page image (PNG)
?token=…&page=N&thumb=1Thumbnail
?token=…&zoom=…Zoomed page rendering
?token=…&search=termFull-text search (license-gated)
?token=…&bookmarksDocument outline and bookmarks
?token=…&copy / &showlinks / &fileFormat / &metaText copy, hyperlinks, format information, DICOM metadata
?token=…&action=rotate/flip/closePage actions and explicit close (POST)
?token=…&AnnSave=… / &AnnLoadSave and load annotations

Every request is checked first:

  • No token → 404, or a version banner when ShowDoconutInfo = true.
  • Token not granted to this ASP.NET session → an error image reading You Are Not Authorized To View This Page.
  • Unknown or expired token → an error image reading Document session not found. Please re-open document.

The error images are ordinary PNGs sent with status 200, so the widget can show them where the page would be. A monitoring check that only looks at the status code will report them as served pages; a real page is tens to hundreds of kilobytes, an error image about 2 KB.

Closing a document

csharp
viewer.CloseDocument(token);

CloseDocument removes the session (releasing the document engine and its memory immediately), removes the secure-{token} entry from the current request's ASP.NET session, and revokes the token. It is optional — sliding expiration does the same cleanup — but for large documents it releases memory the moment the user is done. From the browser, objViewer.Close(true) sends the equivalent close request to DocImage.axd.

Takeaways

  • One open document = one session = one token, granted to the ASP.NET session that opened it.
  • The token expires on a sliding window; a viewer left idle past DocOptions.TimeOut needs a re-open.
  • Viewer can be resolved and shared freely; the sessions carry all the state.

האם דף זה היה מועיל?