Loading Documents
Documents that come from a database, a storage service or your own Web API get into the Document Viewer in two ways: from a file or from memory when the view is rendered, and from JavaScript while the viewer runs. Load settings for comments and PDF documents complete the options.
The examples extend the application of the ASP.NET Core tutorial and use the file App_Data/template.docx from its section "Load a File With DocumentPath".
Ways to Load a Document
| Way | Use it when | Set with |
|---|---|---|
| A file on the server | The document is a file your application can read | DocumentPath in the view |
| Data from memory | Your controller reads the document, for example from a database | DocumentData in the view, a base64-encoded string |
| Data at run time | Users choose another document while the page is open | loadDocument in JavaScript |
The viewer detects the format of the document. With the Core engine, it displays DOCX, PDF, RTF, HTML and the TX Text Control format; DOC documents need the Classic engine. If both DocumentData and DocumentPath are set, DocumentData is loaded, and DocumentPath only sets the name that the status bar shows.
Pass a Document From the Controller
In most applications, the controller reads the document and passes it to the view, for example as part of the view model. Create Controllers/DocumentController.cs with a class for the document and an action that the next section uses:
using Microsoft.AspNetCore.Mvc;
public class DocumentController : Controller
{
// Return a document from the App_Data folder as base64-encoded data
[]
public DocumentData Load(string name)
{
var file = Path.Combine("App_Data", Path.GetFileName(name));
return new DocumentData
{
Name = Path.GetFileName(name),
Data = Convert.ToBase64String(System.IO.File.ReadAllBytes(file))
};
}
}
public class DocumentData
{
public string Name { get; set; } = string.Empty;
public string Data { get; set; } = string.Empty;
}
Change the Index action of Controllers/HomeController.cs so that it passes the document to the view:
public IActionResult Index()
{
// Read the document, for example from a database or a file
var document = new DocumentData
{
Name = "template.docx",
Data = Convert.ToBase64String(System.IO.File.ReadAllBytes("App_Data/template.docx"))
};
return View(document);
}
Replace the content of Views/Home/Index.cshtml:
@using TXTextControl.Web.MVC.DocumentViewer
@model DocumentData
<div style="width: 800px; height: 600px;">
@Html.TXTextControl().DocumentViewer(settings => {
settings.DocumentData = Model.Data;
settings.DocumentPath = Model.Name;
settings.Dock = DocumentViewerSettings.DockStyle.Fill;
}).Render()
</div>
The code works as follows:
DocumentController.Loadreads a file and returns its name and its content as a base64-encoded string.Path.GetFileNamekeeps only the file name, so that a request can't read files outside the App_Data folder. Don't name the controllerTextControl: the viewer package already contains a controller with that name.- The
Indexaction passes aDocumentDataobject to the view as its model. - The view sets
DocumentDatato the content andDocumentPathto the name, which the status bar shows.
Run the application: the viewer shows template.docx, and the status bar shows its name.
Load a Document at Run Time
loadDocument loads a base64-encoded document into the running viewer. The following code loads template.docx from the Load action when users click a button, and logs when the viewer has loaded it. Add it below the viewer's div in Views/Home/Index.cshtml:
<input type="button" onclick="loadFromServer('template.docx')" value="Load template.docx" />
<script>
window.addEventListener("documentViewerLoaded", function () {
TXDocumentViewer.addEventListener("documentLoaded", function () {
console.log("The document has been loaded.");
});
});
async function loadFromServer(name) {
const response = await fetch("/Document/Load?name=" + encodeURIComponent(name));
if (!response.ok) {
console.log("The document couldn't be read: " + response.status);
return;
}
const stored = await response.json();
const loaded = await TXDocumentViewer.loadDocument(stored.data, stored.name);
console.log("loadDocument returned " + loaded);
}
</script>
loadDocumenttakes the base64-encoded document and the name that the status bar shows. It returns a promise that resolves to a Boolean value when the document has been loaded. Its optional third and fourth parameters take the signature settings of Digital Signatures and load settings.- addEventListener attaches a handler to
documentLoaded, which the viewer raises when a document has been loaded. TXDocumentViewerexists only after the viewer has raiseddocumentViewerLoaded, so the handler is attached in its handler.
Always pass a document name to loadDocument. To load into one of several viewers on a page, call the method on its tx-document-viewer element, as shown in JavaScript.
Load Comments of the Document
Comments that are part of the document, rather than annotations of the viewer, are loaded as annotations when the load setting LoadEmbeddedComments is true. Load the Comments of a Document shows the setting in the view and in loadDocument.
Load PDF Documents With PDF.js
By default, PDF documents are imported by the engine. TX Text Control has no PDF renderer: the import turns the content of the PDF document into a document of its own, which makes the text searchable and gives access to positions and form field data, but it doesn't reproduce the PDF document as a PDF reader shows it. The following invoice letter, a PDF document created with TX Text Control, lost its table, its colors and its font sizes when the viewer imported it with the Core engine:

Displayed with PDF.js, the same PDF document looks like the original:

PDF.js, the PDF renderer of Mozilla, displays PDF documents in the browser exactly as they are, and they still get thumbnails, zooming, annotations and the two-page view like other formats. To use it, set the paths to the library and worker files of PDF.js 4 or later in the PDFJS settings. The files can be part of your application or come from a CDN:
@Html.TXTextControl().DocumentViewer(settings => {
settings.DocumentPath = "App_Data/sample.pdf";
settings.Dock = DocumentViewerSettings.DockStyle.Fill;
settings.DocumentLoadSettings.PDFJS.LibrarySourcePath =
"https://cdnjs.cloudflare.com/ajax/libs/pdf.js/4.0.379/pdf.min.mjs";
settings.DocumentLoadSettings.PDFJS.WorkerSourcePath =
"https://cdnjs.cloudflare.com/ajax/libs/pdf.js/4.0.379/pdf.worker.min.mjs";
}).Render()
In JavaScript, pass the same settings with the property pdfjs of the load settings and null for the signature settings:
const loadSettings = {
pdfjs: {
librarySourcePath: "https://cdnjs.cloudflare.com/ajax/libs/pdf.js/4.0.379/pdf.min.mjs",
workerSourcePath: "https://cdnjs.cloudflare.com/ajax/libs/pdf.js/4.0.379/pdf.worker.min.mjs"
}
};
TXDocumentViewer.loadDocument(stored.data, stored.name, null, loadSettings);
LibrarySourcePath and WorkerSourcePath were introduced in version 32.2.1 and replace the earlier BasePath, which older articles use.
Large Documents
Since version 32.0 SP3, the backend streams the pages of a document as it renders them, and your code doesn't need to do anything for this; How a Document Reaches the Browser describes it.
Other Frontends
Angular, React and plain JavaScript pages use the same loadDocument method, and their components take the document in documentData:
- Angular: load a document in a
documentViewerLoadedhandler. - React: load a document when the viewer is ready.
- JavaScript: load a document from a plain HTML page.
The Blazor component loads documents from C# code; the blog article Getting Started: Document Viewer for Blazor in ASP.NET Core shows how.
Next Steps
- Saving Documents: get the document back from the viewer.
- Annotations: load annotations together with the document.
- Events: all events of the viewer.