DevExpress Reports for Web & Office File API — Sign PDF Documents (v23.1)

Reporting Team Blog
28 August 2023

In our most recent major update (v23.1), we introduced the ability to digitally sign reports exported to PDF from our Web Document Viewer and native Blazor Report Viewer. Users can either sign the exported document using the Document Viewer’s UI or app developers can customize the exported document using the CustomizeExportDocumentOnFinish method.

In this blog post, I will describe how to sign the exported PDF document within the Web Document Viewer and native Blazor Report Viewer.

Sign Reports from the Viewer's UI

You can implement the IPdfSignatureOptionsProviderAsync interface across all supported Web platforms.

To proceed, we need to supply the Web Document Viewer with signatures that a user can select when signing an exported PDF document. To do this, implement the IPdfSignatureOptionsProviderAsync interface. The following code supplies the Document Viewer with two digital signatures, for Jane Cooper and John Smith:

using System;
using System.Collections.Generic;
using System.IO;
using System.Threading.Tasks;
using DevExpress.XtraPrinting;
using DevExpress.XtraReports.Web.WebDocumentViewer;
using Microsoft.AspNetCore.Hosting;

public class CustomPdfSignatureOptionsProviderAsync : IPdfSignatureOptionsProviderAsync {
    readonly Dictionary<string, PdfSignatureOptions> signatures = new Dictionary<string, PdfSignatureOptions>();
    public CustomPdfSignatureOptionsProviderAsync(IWebHostEnvironment webHostEnvironment) {
        var signatureDictionaryPath = Path.Join(webHostEnvironment.ContentRootPath, "Signatures");
        signatures.Add(Guid.NewGuid().ToString(), new PdfSignatureOptions() {
            Certificate = new System.Security.Cryptography.X509Certificates.X509Certificate2(Path.Combine(signatureDictionaryPath, "certificate.pfx"), "123"),
            ContactInfo = "Jane Cooper",
        });
        signatures.Add(Guid.NewGuid().ToString(), new PdfSignatureOptions() {
            Certificate = new System.Security.Cryptography.X509Certificates.X509Certificate2(Path.Combine(signatureDictionaryPath, "certificate.pfx"), "123"),
            ContactInfo = "John Smith",
            Location = "Australia",
            Reason = "I Agree",
            ImageSource = DevExpress.XtraPrinting.Drawing.ImageSource.FromFile(Path.Combine(signatureDictionaryPath, "John_Smith.png"))
        });
    }

    public Task<Dictionary<string, PdfSignatureOptions>> GetAvailableOptionsAsync() {
        return Task.FromResult(signatures);
    }
}

To learn more about signature options, refer to the following help topic: PdfSignatureOptions class.

Register the created interface in your application. The following code snippet illustrates usage in an ASP.NET Core application:

services.AddSingleton<IPdfSignatureOptionsProviderAsync, CustomPdfSignatureOptionsProviderAsync>();

You can now select the required signature from the Signature drop-down list in the PDF Export Options section:

Web Document Viewer - Signature Options, DevExpress

If your report contains a XRPdfSignature control, a visual signature will be applied to the report exported to PDF:

Visual Digital Signature, DevExpress

If your document does not contain a XRPdfSignature control, the document will be signed, but the visual signature will not be applied. Open the exported document in Adobe Acrobat Reader to view the signed document.

In a Blazor Server application using our native Blazor Report Viewer, you need to implement the IPdfSignatureOptionsProviderAsync interface and register the service in your application. To sign the document on export, select the signature from the Signature Options drop-down list in the PDF Export Options section:

Blazor Native Report Viewer - Signature Options, DevExpress

Customize the Exported Document

We added aCustomizeExportDocumentOnFinish method. This method allows you to retrieve and modify export results.

Let's now use this new method to sign the report document. We will use the PDF Document API component from the Office File API suite to apply the signature.

Override the CustomizeExportDocumentOnFinish method and specify the digital signature to be applied. We use the following PDF Document API members for this purpose:

using System.IO;
using DevExpress.Office.DigitalSignatures;
using DevExpress.Pdf;
using DevExpress.XtraReports.Web.ClientControls;
using DevExpress.XtraReports.Web.WebDocumentViewer;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.Logging;

public class CustomViewerOperationLogger : WebDocumentViewerOperationLogger {
    readonly ILogger<CustomViewerOperationLogger> logger;
	readonly IWebHostEnvironment webHostEnvironment;

	public CustomViewerOperationLogger(ILogger<CustomViewerOperationLogger> logger, IHttpContextAccessor httpContextAccessor, IWebHostEnvironment webHostEnvironment) {
		this.logger = logger;
		this.webHostEnvironment = webHostEnvironment;
	}

	public override void CustomizeExportDocumentOnFinish(string documentId, string exportOperationId, ExportedDocument exportedDocument) {
		if(exportedDocument.ContentType == "application/pdf") {
			string certificateFile = Path.Join(webHostEnvironment.ContentRootPath, "Signatures", "certificate.pfx");
			using(PdfDocumentSigner documentSigner = new PdfDocumentSigner(new MemoryStream(exportedDocument.Bytes))) {
				var signer = new Pkcs7Signer(certificateFile, "123", HashAlgorithmType.SHA256);
				PdfSignatureBuilder signature = new PdfSignatureBuilder(signer);
				signature.ContactInfo = "John Smith";
				signature.Reason = "I Agree";
				MemoryStream stream = new MemoryStream();
				documentSigner.SaveDocument(stream, signature);
				exportedDocument.Bytes = stream.ToArray();
			}
			logger.LogInformation($"Exported document {documentId} is signed with the \"certificate.pfx\" signature certificate.");
		}
	}
}

Register the created WebDocumentViewerOperationLogger class descendant as a service in your application:

services.AddScoped<WebDocumentViewerOperationLogger, CustomViewerOperationLogger>();

Note that the code snippet above doesn't visualize the digital signature. To confirm that the document is signed, open it in the PDF editor.

For more information on signature-related PDF Document APIs, refer to the following help topic:

Samples and Demos

We added a GitHub example to demonstrate how you can implement the IPdfSignatureOptionsProviderAsync interface and use the CustomizeExportDocumentOnFinish method:

And don't forget to check out our updated demos to explore this new functionality at your own pace:

What's New in v23.1

If you have yet to review the features/capabilities introduced in our most recent major update, please visit the following webpage and let us know what you think of this release by responding to our online survey: DevExpress Reporting — Explore Our Newest Features (v23.1).

Free DevExpress Products - Get Your Copy Today

The following free DevExpress product offers remain available. Should you have any questions about the free offers below, please submit a ticket via the DevExpress Support Center at your convenience. We'll be happy to follow-up.