Blazor Server and WebAssembly
Rendering is server-side either way. In Server the call is direct; in WebAssembly you expose the open call as a minimal API endpoint and hand the returned token to the widget. Both are a handful of lines.
Blazor gives you a component model and a render loop that does not much care for third-party JavaScript. Doconut works with that rather than against it: rendering happens server-side in your own process, and the widget mounts into a plain element you control through the normal interop lifecycle.
The problem
The client-side route means shipping a rendering engine into the browser. In Blazor WebAssembly that lands directly on your download size, and it only ever covers PDF — the moment someone uploads a DOCX or an XLSX you are back to square one.
The iframe-to-Office route means your documents take a trip through somebody else's infrastructure, which is a conversation with your security team you probably do not want to have twice.
Doconut takes the third route. The file is rasterized to page images by your own server, and Blazor only has to host a div. Your component tree never re-renders a viewer it does not own, and the diff engine has nothing to fight with.
Capabilities
Rendering is server-side either way. In Server the call is direct; in WebAssembly you expose the open call as a minimal API endpoint and hand the returned token to the widget. Both are a handful of lines.
Initialise the widget once, after the first render, through the standard JS interop hook. Because Blazor never owns the viewer's internal DOM, subsequent re-renders leave it untouched.
Interactive Server, Interactive WebAssembly, or Auto. The viewer is driven by an opaque token rather than component state, so switching render mode does not change the integration.
The same component opens PDF, DOCX, XLSX, PPTX, DWG, MSG and the rest of the catalogue. You write one viewer page, not one per file family.
Navigation UI comes with the widget. You are wiring up a viewer, not building one out of a canvas and a page-number input.
Nothing is streamed to the browser except rendered page images, which matters more in WebAssembly than people expect — the client is, after all, fully inspectable.
Integration
doconutHost.mount is a few lines of your own JavaScript that calls $('#div_ctlDoc').docViewer({ ... }) and then .View(token). Keeping it outside Blazor is deliberate — the widget's DOM should not be something the renderer tries to reconcile.
Supported platforms
// Program.cs — order matters
builder.Services.AddDoconut(options =>
{
options.LicensePath = "Doconut.Viewer.lic";
});
builder.Services.AddSession();
app.UseSession(); // before UseDoconut()
app.UseDoconutResources(); // before UseDoconut()
app.UseDoconut();
// Viewer.razor — open server-side, hand the token to the widget
@inject Doconut.Viewer Viewer
@inject IJSRuntime JS
<div id="divDocViewer"><div id="div_ctlDoc"></div></div>
@code {
protected override async Task OnAfterRenderAsync(bool firstRender)
{
if (!firstRender) return;
// Authorize first — the viewer renders whatever you hand it.
string token = await Viewer.OpenDocumentAsync("wwwroot/files/Sample.pdf");
await JS.InvokeVoidAsync("doconutHost.mount", token);
}
}Details
Both. Rendering always happens server-side, so in WebAssembly you add one endpoint that calls OpenDocumentAsync and returns the token. The client never parses a document, which is exactly why the WASM payload stays unaffected.
No, provided you mount into an element Blazor treats as a leaf. Render an empty div and let the widget populate it through interop — the diff engine has no children to reconcile.
No. One page handles the whole catalogue. The format is detected from the document you open, not selected by you in advance.
ASP.NET Core
Registers as ordinary DI plus middleware. Inherits the authentication, logging and hosting you already have.
ASP.NET CoreServer-side PDF rendering into page images — the user reads the document without ever receiving the file.
PDFA temporary licence takes a few minutes to request and runs entirely on your own machine. The files that matter are the ones already breaking your current viewer.