# How to Add Electronic and Digital Signatures to PDFs in ASP.NET Core C# and Angular

> Learn how to add electronic and digital signatures to PDFs in ASP.NET Core C# and Angular. This tutorial shows how to create an Angular application with an ASP.NET Core backend that uses the Document Viewer to display and sign PDF documents.

- **Author:** Bjoern Meyer
- **Published:** 2024-03-20
- **Modified:** 2025-11-16
- **Description:** Learn how to add electronic and digital signatures to PDFs in ASP.NET Core C# and Angular. This tutorial shows how to create an Angular application with an ASP.NET Core backend that uses the Document Viewer to display and sign PDF documents.
- **12 min read** (2303 words)
- **Tags:**
  - Angular
  - ASP.NET Core
  - Document Viewer
  - E-Sign
  - Electronic Signature
  - Digital Signature
- **Web URL:** https://www.textcontrol.com/blog/2024/03/20/how-to-add-electronic-and-digital-signatures-to-pdfs-in-asp-net-core-c-sharp-and-angular/
- **LLMs URL:** https://www.textcontrol.com/blog/2024/03/20/how-to-add-electronic-and-digital-signatures-to-pdfs-in-asp-net-core-c-sharp-and-angular/llms.txt
- **LLMs-Full URL:** https://www.textcontrol.com/blog/2024/03/20/how-to-add-electronic-and-digital-signatures-to-pdfs-in-asp-net-core-c-sharp-and-angular/llms-full.txt
- **GitHub Repository:** https://github.com/TextControl/TXTextControl.Web.Angular.Core.Signing

---

In this article, you will learn how to sign a document and export it as a PDF using Angular and an ASP.NET Core backend. Using [TX Text Control .NET Server](https://www.textcontrol.com/product/tx-text-control-dotnet-server/) and the [Document Viewer for Angular](https://www.textcontrol.com/product/client-package/), the electronic signature is captured and applied to a signature field that is digitally signed with a certificate to ensure that your documents are secure and reliable.

TX Text Control provides all the necessary capabilities to capture signatures from end users and process the document to create a fully signed and secure PDF document. It provides the server-side API to generate the PDF and the front-end UI tools for a modern, reliable and effortless signature experience.

### Signature Support

TX Text Control provides two different types of signatures: Electronic signatures and digital signatures.

- **Electronic Signature**  
    An electronic signature is a signature that is captured using a touch screen or a mouse. It is a visual representation of a signature that is placed on a document. It is not necessarily cryptographically secured, but can be digitally signed.
- **Digital Signature**  
    A digital signature is a cryptographic signature that is applied to a document. It is cryptographically secured and ensures that the document has not been tampered with. It is based on a certificate that is issued by a trusted authority.

In most typical scenarios, the two types are combined so that visual signature fields contain the visual representation and are digitally signed with a certificate.

### Document Viewer for Angular

The Document Viewer for Angular is a modern, web-based document viewer that is available for many platforms and provides all the functionality needed to capture signatures.

- **Out-of-the-box UI**  
    The Document Viewer for Angular provides a ready-to-use UI to display and sign documents. It is customizable and can be integrated into any Angular application.
    
    ![Angular Document Viewer UI](https://s1-www.textcontrol.com/assets/dist/blog/2024/03/20/a/assets/viewer_ui.webp "Angular Document Viewer UI")
- **Signature Fields**  
    The Document Viewer for Angular provides support for signature fields that can be placed on the document to capture electronic signatures. These fields can be digitally signed with a certificate to ensure that the document is secure and reliable.
    
    ![Angular Document Viewer Signature Fields](https://s1-www.textcontrol.com/assets/dist/blog/2024/03/20/a/assets/viewer_signature.webp "Angular Document Viewer Signature Fields")
- **Form Filling**  
    The Document Viewer for Angular provides support for form fields that can be placed on the document to capture data. These fields can be exported as a PDF form.
    
    ![Angular Document Viewer Forms Filling](https://s1-www.textcontrol.com/assets/dist/blog/2024/03/20/a/assets/viewer_forms.webp "Angular Document Viewer Forms Filling")
- **Draw, Type or Upload Signatures**  
    The Document Viewer for Angular provides different ways to capture signatures. Users can draw, type or upload a signature image to sign the document.
    
    ![Angular Document Viewer Signature Capture](https://s1-www.textcontrol.com/assets/dist/blog/2024/03/20/a/assets/viewer_draw.webp "Angular Document Viewer Signature Capture")

### Prerequisites

In order to get started, you will need the following components:

- A trial or full version of [TX Text Control .NET Server](https://www.textcontrol.com/product/tx-text-control-dotnet-server/).
- Visual Studio 2022.

> **npm and Angular command-line interface (CLI)**
> 
> The client-side part of this tutorial can also be built independently of Visual Studio using the Angular CLI. To learn how to create an Angular CLI application using the TX Text Control, read this article.
> 
> [Getting Started: Document Editor with Angular CLI v17.0 ](https://www.textcontrol.com/blog/2023/12/13/getting-started-document-editor-with-angular-cli-17/llms-full.txt)

### Creating the Application

The following tutorial will show you how to create an *Angular with ASP.NET Core* application that includes the client-side npm package and the required backend middleware.

1. In Visual Studio 2022, create a new project, select *Angular with ASP.NET Core* as the project template and continue with Next.
    
    ![ASP.NET Core with Angular application](https://s1-www.textcontrol.com/assets/dist/blog/2024/03/20/a/assets/visualstudio1.webp "ASP.NET Core with Angular application")
2. Select a project name and location confirm with *Next*.
3. Choose *.NET 8 (Long Term Support)* as the *Framework*, enable *Use Controllers* and continue with *Create*.
    
    ![ASP.NET Core with Angular application](https://s1-www.textcontrol.com/assets/dist/blog/2024/03/20/a/assets/visualstudio2.webp "ASP.NET Core with Angular application")

#### Adding NuGet Packages

1. Right-click on the project that ends with *.Server* in the Solution Explorer and select *Manage NuGet Packages...*.
    
    Select *Text Control Offline Packages* from the *Package source* drop-down.
    
    *Install* the latest versions of the following packages:
    
    
    - *TXTextControl.TextControl.ASP.SDK*
    - *TXTextControl.Web.DocumentViewer*
    
    ![NuGet Packages](https://s1-www.textcontrol.com/assets/dist/blog/2024/03/20/a/assets/visualstudio3.webp "NuGet Packages")
2. Switch the package source to *nuget.org* and choose *Installed* to check for available updates. Update the installed packages to the most current version.

#### Preparing the Pipeline

1. Open the file *Program.cs* in the *.Server* project and a replace the complete code with the following code:
    
    ```
    using TXTextControl.Web.MVC.DocumentViewer;
    var builder = WebApplication.CreateBuilder(args);
    
    // adding CORS policy to allow all origins
    builder.Services.AddCors(options =>
    {
      options.AddDefaultPolicy(
             builder =>
             {
               builder.AllowAnyOrigin()
                  .AllowAnyMethod()
                  .AllowAnyHeader();
             });
    });
    
    // Add services to the container.
    builder.Services.AddControllers();
    
    var app = builder.Build();
    app.UseDefaultFiles();
    app.UseStaticFiles();
    
    // Configure the HTTP request pipeline.
    app.UseHttpsRedirection();
    app.UseAuthorization();
    app.UseRouting();
    
    // adding CORS middleware
    app.UseCors();
    
    app.UseTXDocumentViewer();
    app.MapControllers();
    app.MapFallbackToFile("/index.html");
    app.Run();
    ```

#### Adding npm Packages

The Angular application has already been created by the Visual Studio project template and is available in the Solution Explorer ending with *.client*.

1. In the *Solution Explorer*, expand the Angular application node, right-click *npm*, and select *Install new npm packages* from the context menu.
    
    ![Install new npm packages](https://s1-www.textcontrol.com/assets/dist/blog/2024/03/20/a/assets/visualstudio4.webp "Install new npm packages")
2. Search for *@txtextcontrol/tx-ng-document-viewer* and install the package. Add *--legacy-peer-deps* as a *Other npm arguments* to force the installation for newer Angular versions.
    
    ![Install @txtextcontrol/tx-ng-document-viewer](https://s1-www.textcontrol.com/assets/dist/blog/2024/03/20/a/assets/visualstudio5.webp "Install @txtextcontrol/tx-ng-document-viewer")
3. Open the file *src -> app -> app.module.ts*, add replace the complete content with the following code and save it:
    
    ```
    import { HttpClientModule } from '@angular/common/http';
    import { NgModule } from '@angular/core';
    import { BrowserModule } from '@angular/platform-browser';
    
    import { AppRoutingModule } from './app-routing.module';
    import { AppComponent } from './app.component';
    import { DocumentViewerModule } from '@txtextcontrol/tx-ng-document-viewer';
    
    @NgModule({
      declarations: [
        AppComponent
      ],
      imports: [
        BrowserModule, HttpClientModule,
        AppRoutingModule, DocumentViewerModule
      ],
      providers: [],
      bootstrap: [AppComponent]
    })
    export class AppModule { }
    ```

#### Creating the Self-Signed Certificate

In the next steps, a self-signed certificate is created using Windows PowerShell.

- Use the **New-SelfSignedCertificate** PowerShell cmdlet to create a self signed certificate. Open a PowerShell and type in the following command:
    
    ```
    New-SelfSignedCertificate -Type Custom -Subject "CN=Text Control, O=Text Control, C=US" -KeyUsage DigitalSignature -FriendlyName "TextControlSelf" -CertStoreLocation "Cert:\CurrentUser\My" -TextExtension @("2.5.29.37={text}1.3.6.1.5.5.7.3.3", "2.5.29.19={text}")
    ```
    
    After running this command, the certificate is added to the certificate store (specified in the "-CertStoreLocation" parameter). The output of the command shows the certificate's thumbprint.
    
    ```
    PSParentPath: Microsoft.PowerShell.Security\Certificate::CurrentUser\My
    
    Thumbprint                                Subject
    ----------                                -------
    6BA35B742656FB2EC48B09116ABAE5123082F116  CN=Text Control, O=Text Control, C=US
    ```
- Copy this thumbprint and insert it into the following command:
    
    ```
    $password = ConvertTo-SecureString -String yourpassword -Force -AsPlainText 
    Export-PfxCertificate -cert "Cert:\CurrentUser\My\6BA35B742656FB2EC48B09116ABAE5123082F116" -FilePath textcontrolself.pfx -Password $password
    ```
- The file *textcontrol\_self.pfx* is created in the same folder. Copy this to your application's folder from where you want to load the certificate (*App\_Data* in our Web API sample above).

#### Creating the Controller

1. Right-click on the *Controllers* folder in the *.Server* project and select *Add -> Controller...*. Choose *MVC Controller - Empty* and confirm with *Add*. Name it *DocumentController* and click *Add*.
2. Replace the complete content of the *DocumentController.cs* with the following code:
    
    ```
    using Microsoft.AspNetCore.Mvc;
    using System.Security.Cryptography.X509Certificates;
    using TXTextControl;
    using TXTextControl.Web.MVC.DocumentViewer;
    using TXTextControl.Web.MVC.DocumentViewer.Models;
    
    namespace MyAngularBackend.Server.Controllers
    {
      [ApiController]
      [Route("[controller]")]
      public class DocumentController : ControllerBase
      {
    
        private readonly ILogger<DocumentController> _logger;
    
        public DocumentController(ILogger<DocumentController> logger)
        {
          _logger = logger;
        }
    
        [HttpGet]
        [Route("Load")]
        public DocumentData Load()
        {
          // open file as byte and convert to base64
          byte[] fileBytes = System.IO.File.ReadAllBytes("App_Data/document.tx");
          string file = Convert.ToBase64String(fileBytes);
          return new DocumentData { Name = "document.pdf", Document = file };
        }
    
        [HttpPost]
        [Route("Sign")]
        public string Sign([FromBody] SignatureData signatureData)
        {
          byte[] bPDF;
    
          // create temporary ServerTextControl
          using (ServerTextControl tx = new ServerTextControl())
          {
            tx.Create();
    
            // load the document
            tx.Load(Convert.FromBase64String(signatureData.SignedDocument.Document),
              BinaryStreamType.InternalUnicodeFormat);
    
            // create a certificate
            X509Certificate2 cert = new X509Certificate2("App_Data/textcontrol_self.pfx", "123");
    
            // create a list of digital signatures
            var signatureFields = new List<DigitalSignature>();
    
            // create a digital signature for each signature box
            foreach (SignatureBox box in signatureData.SignatureBoxes)
            {
              signatureFields.Add(new DigitalSignature(cert, null, box.Name));
            }
    
            // create save settings
            SaveSettings saveSettings = new SaveSettings()
            {
              CreatorApplication = "Your Application",
              SignatureFields = signatureFields.ToArray()
            };
    
            // save the document as PDF
            tx.Save(out bPDF, BinaryStreamType.AdobePDFA, saveSettings);
          }
    
          // return as Base64 encoded string
          return Convert.ToBase64String(bPDF);
        }
      }
    }
    ```

#### Adding the Document Viewer

1. Open the file *src -> app -> app.component.ts* and replace the complete content with the following code:
    
    ```
    import { HttpClient } from '@angular/common/http';
    import { Component, OnInit, HostListener } from '@angular/core';
    
    declare const TXDocumentViewer: any;
    interface DocumentData {
      document?: string;
      name?: string;
    }
    
    @Component({
      selector: 'app-root',
      templateUrl: './app.component.html',
      styleUrl: './app.component.css',
    })
    export class AppComponent implements OnInit {
    
      public documentData: DocumentData = {};
    
      constructor(private http: HttpClient) { }
    
      @HostListener('window:documentViewerLoaded', ['$event'])
      onDocumentViewerLoaded() {
    
        TXDocumentViewer.signatures.setSubmitCallback(function (data: string) {
          var element = document.createElement('a');
          element.setAttribute('href', 'data:application/pdf;;base64,' + data);
          element.setAttribute('download', "results.pdf");
          document.body.appendChild(element);
          element.click();
        })
    
        var signatureSettings = {
          showSignatureBar: true,
          redirectUrlAfterSignature: 'https://localhost:7275/document/sign',
          ownerName: 'Paul',
          signerName: 'Jacob',
          signerInitials: 'PK',
          signatureBoxes: [{ name: 'txsign', signingRequired: true, style: 0 }]
        };
    
        TXDocumentViewer.loadDocument(this.documentData.document, this.documentData.name, signatureSettings);
      }
    
      ngOnInit() {
        this.getDocument();
      }
    
      getDocument() {
        this.http.get<DocumentData>('/document/load').subscribe(
          (result) => {
            this.documentData = result;
          }
        );
      }
    
      title = 'myangularbackend.client';
    }
    ```
2. Open the file *src -> app -> app.component.html* and replace the complete content with the following code:
    
    ```
    <tx-document-viewer width="800px"
                        height="800px"
                        basePath="https://localhost:7275"
                        dock="Window"
                        [toolbarDocked]="true"
                        [showThumbnailPane]="true">
    </tx-document-viewer>
    ```
    
    The port number in the code (in this case *7275*) can be found in the *Properties -> launchSettings.json* file of your *.Server* application.
3. Open the file *src -> proxy.conf.js* and replace the code with the following code:
    
    ```
    const PROXY_CONFIG = [
      {
        context: [
          "/document",
        ],
        target: "https://localhost:7275",
        secure: false
      }
    ]
    
    module.exports = PROXY_CONFIG;
    ```
    
    Replace the port number with the appropriate port number, similar to the previous step.

#### Adding a Sample Document

1. Download the sample document [document.tx](https://s1-www.textcontrol.com/assets/dist/blog/2024/03/20/a/assets/document.tx) and save it to the *App\_Data* folder of the *.Server* project. Create the folder, if it doesn't exist.

#### Running the Application

1. Run the application by pressing *F5* in Visual Studio. The application starts and the Document Viewer is loaded with the sample document.
    
    ![Running the application](https://s1-www.textcontrol.com/assets/dist/blog/2024/03/20/a/assets/results1.webp "Running the application")
2. Click on the signature field to sign the document. The signature dialog is opened and the signature can be drawn, typed or uploaded.
3. After signing the document, the signature is applied and the document is digitally signed with the certificate.
    
    ![Signed document](https://s1-www.textcontrol.com/assets/dist/blog/2024/03/20/a/assets/results2.webp "Signed document")

### Workflow Explanation

The following is a step-by-step description of the signing process.

#### Loading the Document

When the application is started, the document is loaded from the server and displayed in the Document Viewer. This is done using an HttpGet method that retrieves the template from the server.

```
getDocument() {
 this.http.get<DocumentData>('/document/load').subscribe(
   (result) => {
     this.documentData = result;
   }
 );
}
```

Server-side, the *Load* method returns the document to be loaded and returned as a base64-encoded string.

```
[HttpGet]
[Route("Load")]
public DocumentData Load()
{
  // open file as byte and convert to base64
  byte[] fileBytes = System.IO.File.ReadAllBytes("App_Data/document.tx");
  string file = Convert.ToBase64String(fileBytes);
  return new DocumentData { Name = "document.pdf", Document = file };
}
```

#### Signing the Document

When all signature fields are signed, the *Sign* method is called. The implemented HttpPost endpoint *Sign* is requested by the Document Viewer after the signing process. In this method, a digital certificate is applied to the signed electronic signature representation using the SignatureFields property. This property specifies an array of DigitalSignature objects, each of which defines an X.509 certificate and is associated with a SignatureField in the document. These certificates can be used to digitally sign a PDF or a PDF/A file.

```
[HttpPost]
[Route("Sign")]
public string Sign([FromBody] SignatureData signatureData)
{
  byte[] bPDF;

  // create temporary ServerTextControl
  using (ServerTextControl tx = new ServerTextControl())
  {
    tx.Create();

    // load the document
    tx.Load(Convert.FromBase64String(signatureData.SignedDocument.Document),
      BinaryStreamType.InternalUnicodeFormat);

    // create a certificate
    X509Certificate2 cert = new X509Certificate2("App_Data/textcontrol_self.pfx", "123");

    // create a list of digital signatures
    var signatureFields = new List<DigitalSignature>();

    // create a digital signature for each signature box
    foreach (SignatureBox box in signatureData.SignatureBoxes)
    {
      signatureFields.Add(new DigitalSignature(cert, null, box.Name));
    }

    // create save settings
    SaveSettings saveSettings = new SaveSettings()
    {
      CreatorApplication = "Your Application",
      SignatureFields = signatureFields.ToArray()
    };

    // save the document as PDF
    tx.Save(out bPDF, BinaryStreamType.AdobePDFA, saveSettings);
  }

  // return as Base64 encoded string
  return Convert.ToBase64String(bPDF);
}
```

The following diagram illustrates the signature workflow.

![Signature Workflow](https://s1-www.textcontrol.com/assets/dist/blog/2024/03/20/a/assets/diagram.webp "Signature Workflow")

### Conclusion

This tutorial showed how to create an Angular application with an ASP.NET Core backend that uses the Document Viewer to display and sign PDF documents. The Document Viewer provides all the necessary UI and API to capture signatures and to digitally sign the document with a certificate. The server-side API provides the necessary methods to load and save the document and to apply the digital signature.

Download the sample from GitHub and test the signature process with your own certificate.

---

## About Bjoern Meyer

As CEO, Bjoern is the visionary behind our strategic direction and business development, bridging the gap between our customers and engineering teams. His deep passion for coding and web technologies drives the creation of innovative products. If you're at a tech conference, be sure to stop by our booth - you'll most likely meet Bjoern in person. With an advanced graduate degree (Dipl. Inf.) in Computer Science, specializing in AI, from the University of Bremen, Bjoern brings significant expertise to his role. In his spare time, Bjoern enjoys running, paragliding, mountain biking, and playing the piano.

- [LinkedIn](https://www.linkedin.com/in/bjoernmeyer/)
- [X](https://x.com/txbjoern)
- [GitHub](https://github.com/bjoerntx)

---

## Series

- [MailMerge with Angular and ASP.NET Core](https://www.textcontrol.com/blog/2024/03/15/mailmerge-with-angular-and-asp-net-core/llms.txt)
- **How to Add Electronic and Digital Signatures to PDFs in ASP.NET Core C# and Angular** (this article)
- [Document Viewer for Angular: SignatureSettings Explained](https://www.textcontrol.com/blog/2024/03/20/signaturesettings-explained/llms.txt)
- [Asynchronous Loading and Saving in Angular Document Editor with an ASP.NET Core Web API](https://www.textcontrol.com/blog/2024/03/21/asynchronous-loading-and-saving-in-angular-document-editor-with-an-asp-net-core-web-api/llms.txt)
- [Preparing Forms for the Document Viewer and Customizing the Signing Process in Angular and ASP.NET Core](https://www.textcontrol.com/blog/2024/03/25/preparing-forms-for-the-document-viewer-and-customizing-the-signing-process-in-angular-and-asp-net-core/llms.txt)
- [Handling Form Field Data in Angular Applications](https://www.textcontrol.com/blog/2024/03/27/handling-form-field-data-in-angular-applications/llms.txt)

---

## Related Posts

- [Adoption of Electronic vs. Paper Signatures in 2025](https://www.textcontrol.com/blog/2025/04/15/adoption-of-electronic-vs-paper-signatures-in-2025/llms.txt)
- [Building an ASP.NET Core Backend (Linux and Windows) for the Document Editor and Viewer](https://www.textcontrol.com/blog/2025/03/26/building-an-asp-net-core-backend-for-the-document-editor-and-viewer/llms.txt)
- [Preparing Documents for E-Signing for Multiple Signers in .NET C#](https://www.textcontrol.com/blog/2024/11/13/preparing-documents-for-e-signing-for-multiple-signers-in-net-c-sharp/llms.txt)
- [Optimizing Digital Signature Workflows: Starting with MS Word DOCX Files Instead of PDFs in C#](https://www.textcontrol.com/blog/2024/09/27/optimizing-digital-signature-workflows-starting-with-ms-word-docx-files-instead-of-pdfs-in-csharp/llms.txt)
- [Getting Started Video Tutorial: How to use the Document Viewer in Angular](https://www.textcontrol.com/blog/2024/08/05/getting-started-video-tutorial-how-to-use-the-document-viewer-in-angular/llms.txt)
- [Transforming Financial Documents into Smart and Secure Forms in ASP.NET Core C#](https://www.textcontrol.com/blog/2024/05/01/transforming-financial-documents-into-smart-and-secure-forms-in-asp-net-core-c-sharp/llms.txt)
- [Handling Form Field Data in Angular Applications](https://www.textcontrol.com/blog/2024/03/27/handling-form-field-data-in-angular-applications/llms.txt)
- [Preparing Forms for the Document Viewer and Customizing the Signing Process in Angular and ASP.NET Core](https://www.textcontrol.com/blog/2024/03/25/preparing-forms-for-the-document-viewer-and-customizing-the-signing-process-in-angular-and-asp-net-core/llms.txt)
- [Asynchronous Loading and Saving in Angular Document Editor with an ASP.NET Core Web API](https://www.textcontrol.com/blog/2024/03/21/asynchronous-loading-and-saving-in-angular-document-editor-with-an-asp-net-core-web-api/llms.txt)
- [Document Viewer for Angular: SignatureSettings Explained](https://www.textcontrol.com/blog/2024/03/20/signaturesettings-explained/llms.txt)
- [Building an ASP.NET Core Backend Application to Host the Document Editor and Document Viewer](https://www.textcontrol.com/blog/2024/03/14/building-an-asp-net-core-backend-application-to-host-the-document-editor-and-document-viewer/llms.txt)
- [Apply Digital Signatures to PDF Signature Fields Imported from MS Word in C#](https://www.textcontrol.com/blog/2023/08/25/apply-digital-signatures-to-pdf-signature-fields-imported-from-ms-word-in-csharp/llms.txt)
- [What is the Difference between Electronic and Digital Signatures?](https://www.textcontrol.com/blog/2022/10/20/what-is-the-difference-between-electronic-and-digital-signatures/llms.txt)
- [Document Viewer: Uploading Signatures](https://www.textcontrol.com/blog/2022/02/24/document-viewer-uploading-signatures/llms.txt)
