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:
If your report contains a XRPdfSignature control, a visual signature will be applied to the report exported to PDF:
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:
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:
- The
PdfDocumentSigner
object to sign the exported document. - The
PdfSignatureBuilder
object to specify certificate settings. Pass thePkcs7Signer
object to thePdfSignatureBuilder
object constructor to apply a PKCS#7 signature. - To sign the exported document, we call the
PdfDocumentSigner.SaveDocument
method and pass the createdPdfSignatureBuilder
object as a parameter:
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).