Integrate WebViewer with ASP.NET to Enable Saving and Loading Annotations

In addition to showing how to add the WebViewer component to an ASP.NET project, this sample expands on annotation functionality by enabling saving and loading the annotation objects into the local file system.

The saving and loading are done through GET and POST HTTP messages that are handled by an AnnotationController in the project. The annotations are stored as XFDF strings embedded in the messages and saved as XFDF files on disk.

WebViewer provides a slick out-of-the-box responsive UI that enables you to view, annotate and manipulate PDFs and other document types inside any web project.

Click the button below to view the full project in GitHub.

1var viewerElement = document.getElementById('viewer');
2var DOCUMENT_ID = 'webviewer-demo-1';
3
4WebViewer({
5 path: '/Scripts/webviewer/lib',
6 initialDoc: 'https://pdftron.s3.amazonaws.com/downloads/pl/demo.pdf',
7 documentXFDFRetriever: () => loadXfdfString(DOCUMENT_ID)
8}, viewerElement).then(instance => {
9 const {annotationManager} = instance.Core;
10
11 // Add a save button on header
12 const topHeader = instance.UI.getModularHeader('default-top-header');
13 const items = topHeader.getItems();
14
15 const saveButton = {
16 type: 'customButton',
17 img: '<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><path d="M0 0h24v24H0z" fill="none"/><path d="M17 3H5c-1.11 0-2 .9-2 2v14c0 1.1.89 2 2 2h14c1.1 0 2-.9 2-2V7l-4-4zm-5 16c-1.66 0-3-1.34-3-3s1.34-3 3-3 3 1.34 3 3-1.34 3-3 3zm3-10H5V5h10v4z"/></svg>',
18 title: 'Save Annotations',
19 onClick: function() {
20 // Save annotations when button is clicked
21 // widgets and links will remain in the document without changing so it isn't necessary to export them
22 annotationManager.exportAnnotations({ links: false, widgets: false }).then(function (xfdfString) {
23 saveXfdfString(DOCUMENT_ID, xfdfString)
24 .then(function() {
25 alert('Annotations saved successfully.');
26 })
27 .catch(function () {
28 alert('Annotations not saved successfully.');
29 });
30 });
31 }
32 };
33
34 items.push(saveButton);
35 topHeader.setItems(items);
36});
37
38// Make a POST request with XFDF string
39var saveXfdfString = function(id, xfdfString) {
40 return new Promise(function(resolve) {
41 fetch(`/api/annotation?id=${id}`, {
42 method: 'POST',
43 body: xfdfString
44 }).then(function(res) {
45 if (res.status === 200 || res.status === 204) {
46 resolve();
47 }
48 });
49 });
50};
51
52// Make a GET request to get XFDF string
53var loadXfdfString = function(id) {
54 return new Promise(function(resolve) {
55 fetch(`/api/annotation?id=${id}`, {
56 method: 'GET'
57 }).then(function(res) {
58 if (res.status === 200 || res.status === 204) {
59 res.text().then(function(xfdfString) {
60 resolve(xfdfString);
61 });
62 }
63 });
64 });
65};
66

Did you find this helpful?

Trial setup questions?

Ask experts on Discord

Need other help?

Contact Support

Pricing or product questions?

Contact Sales