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 fromDoconutHost.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— theDoconut.DocImageHandlerdeclared inWeb.config. It answers every request the browser widget makes (pages, thumbnails, search, annotations, …), always identified by the token./doconut-res/*— theDoconut.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:
// 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
- License gate. A rejected license (tampered, blacklisted, or a build outside the license's update window) throws
LicenseExceptionimmediately, with the reason as the message. Opening never silently degrades for an invalid license; a missing license only watermarks. - 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.TimeOutminutes (default 60). Every page request resets the clock. - Access grant. With
UnsafeMode = false(the default), the token is bound to the ASP.NET session of the request that opened it: asecure-{token}entry is written into that session. The open must therefore run in a request with session state — see Sessions & Security. - 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:
| Query | Purpose |
|---|---|
?token=…&page=N | Rendered page image (PNG) |
?token=…&page=N&thumb=1 | Thumbnail |
?token=…&zoom=… | Zoomed page rendering |
?token=…&search=term | Full-text search (license-gated) |
?token=…&bookmarks | Document outline and bookmarks |
?token=…© / &showlinks / &fileFormat / &meta | Text copy, hyperlinks, format information, DICOM metadata |
?token=…&action=rotate/flip/close | Page actions and explicit close (POST) |
?token=…&AnnSave=… / &AnnLoad | Save and load annotations |
Every request is checked first:
- No token →
404, or a version banner whenShowDoconutInfo = 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
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.TimeOutneeds a re-open. Viewercan be resolved and shared freely; the sessions carry all the state.
هل كانت هذه الصفحة مفيدة؟