Products Technologies Demo Docs Blog Support Company

Best Practices for Mail Merge and Form Field Processing in ASP.NET Core C# Applications

This article provides best practices for mail merge and form field processing in ASP.NET Core C# applications using TX Text Control .NET Server. It shows how to use the Document Editor to create templates and how to merge data into those templates using the MailMerge class.

Best Practices for Mail Merge and Form Field Processing in ASP.NET Core C# Applications

TX Text Control provides all the necessary components used in a typical form field processing workflow. From designing the template using a customizable and programmable document editor, to merging data into the template, to deploying the form for users to fill in form fields. After the document is completed, the final document is created as a PDF and the completed form field values are extracted for processing.

This tutorial describes the best-practice sample project that contains all the necessary process steps and classes to integrate such a document processing workflow into your own applications.

It shows the following steps:

  • Designing the template using the TX Text Control Document Editor
  • Merging data into the template
  • Deploying the form for users to fill in form fields
  • Extracting the form field values from the completed document
  • Creating the final document as a PDF with flattened form fields

Form Field Processing Workflow

The Sample Project

The sample project is an ASP.NET Core MVC C# application that uses the TX Text Control Document Editor to design the template. The template is then merged with data and deployed for users to fill in form fields using the Document Viewer. After the document is completed, the final document is created as a PDF and the completed form field values are extracted for processing.

Designing the Template

The template is designed using the TX Text Control Document Editor. The editor is a fully programmable and customizable WYSIWYG word processing editor that can be integrated into any application. The editor is used to design the template with merge fields and form fields that are later filled in by users.

After starting the sample project, the dashboard shows two options: Create Template and Merge and Deploy. Click on Create Template to start the Document Editor.

Form Field Processing Workflow

A view containing the TX Text Control Document Editor will open and you can begin designing your template. A sample JSON data object is loaded into the editor to demonstrate how merge fields can be used to merge data into the template. This data source is also used to merge the template to generate the document. To load a pre-designed template that contains merge fields and form fields that match the data source, click Load Pre-Designed Template.

Form Field Processing Workflow

Saving the Template

If you are happy with the template click on Save Template and close the view by clicking Close.

Let's take a look at what happens in the code in this step. The SaveDocument JavaScript function saves the document and sends it to the SaveTemplate controller endpoint.

function saveDocument() {
    TXTextControl.saveDocument(TXTextControl.StreamType.InternalUnicodeFormat, document => {
        dirtyFlag = false;

        // send document.data to endpoint using ajax
        $.ajax({
            type: "POST",
            url: "/Document/SaveTemplate?templateName=@templateName",
            data: JSON.stringify(document.data),
            contentType: "application/json",
            dataType: "json",
            success: function (response) {
                toggleSaveButtonEnabled();
            },
            error: function (response) {
                console.log(response);
            }
        });
    });
}

The endpoint saves the document to the server and returns the generated document filename. This filename is used to load the document in the Document Viewer later.

[HttpPost]
public IActionResult SaveTemplate([FromBody] string document, [FromQuery] string templateName)
{
    if (string.IsNullOrEmpty(document) || string.IsNullOrEmpty(templateName))
    {
        return BadRequest("Invalid input: Document and template name must be provided.");
    }

    try
    {
        // Convert base64 string to byte array
        byte[] bytes = Convert.FromBase64String(document);

        // Ensure the directory exists
        string directoryPath = Path.Combine("Templates");
        if (!Directory.Exists(directoryPath))
        {
            Directory.CreateDirectory(directoryPath);
        }

        // Safely combine the path and template name
        string filePath = Path.Combine(directoryPath, templateName);

        // Save the document to a file
        System.IO.File.WriteAllBytes(filePath, bytes);

        // Return JSON with the file name
        return Json(new { templateName = templateName });
    }
    catch (FormatException)
    {
        return BadRequest("Invalid base64 string.");
    }
    catch (IOException ex)
    {
        return StatusCode(500, "Error saving the file.");
    }
    catch (Exception ex)
    {
        return StatusCode(500, "An unexpected error occurred.");
    }
}

Merging Data into the Template

After saving the template, the dashboard shows the Merge and Deploy option. Click on this option to merge the template with the sample data and deploy the document for users to fill in form fields.

Select the template you created from the drop-down list and click Merge and Load.

Form Field Processing Workflow

This is where the MergeTemplate endpoint is called with the name of the template.

[HttpGet]
public IActionResult MergeTemplate([FromQuery] string templateName)
{
    if (string.IsNullOrEmpty(templateName))
    {
        return BadRequest("Template name must be provided.");
    }

    try
    {
        // Safely combine the path and template name
        string templatePath = Path.Combine("Templates", templateName);
        string dataPath = Path.Combine("Data", "data.json");

        if (!System.IO.File.Exists(templatePath))
        {
            return NotFound("Template not found.");
        }

        if (!System.IO.File.Exists(dataPath))
        {
            return NotFound("Data file not found.");
        }

        // Read the template and data files
        byte[] templateBytes = System.IO.File.ReadAllBytes(templatePath);
        string jsonData = System.IO.File.ReadAllText(dataPath);

        using (ServerTextControl tx = new ServerTextControl())
        {
            // Load the template
            tx.Create();
            tx.Load(templateBytes, BinaryStreamType.InternalUnicodeFormat);

            MailMerge merge = new MailMerge
            {
                TextComponent = tx,
                FormFieldMergeType = FormFieldMergeType.Preselect
            };

            // Merge the template with JSON data
            merge.MergeJsonData(jsonData);

            // Save the merged document to a byte array
            byte[] document;
            tx.Save(out document, BinaryStreamType.InternalUnicodeFormat);

            // Convert byte array to base64 string
            string documentBase64 = Convert.ToBase64String(document);

            // Return the document as a JSON object
            return Json(new { document = documentBase64 });
        }
    }
    catch (IOException ex)
    {
        return StatusCode(500, "Error reading files or saving the document.");
    }
    catch (Exception ex)
    {
        return StatusCode(500, "An unexpected error occurred.");
    }
}

The endpoint merges the template with the sample data and returns the merged document. This document is loaded into the Document Viewer for users to fill in form fields.

Form Field Processing Workflow

Finalizing the Document

Fill in some of the form fields and click Submit to send the document back to the server. The asynchronous JavaScript function finalizeDocument saves the document by including the form field values. The returned document is then sent to the Finalize controller method, which generates and returns a PDF document that is then offered for download and loaded into the viewer.

async function finalizeDocument() {

    // export the document with the form fields
    const saveSettings = { mergeFormFields: true, embedAnnotations: false };
    const result = await TXDocumentViewer.saveDocument(
        TXDocumentViewer.StreamType.InternalUnicodeFormat,
        saveSettings);

    const base64 = await result.base64();

    // finalize the document on the server
    $.ajax({
        type: "POST",
        url: "/Document/Finalize?templateName=" + templateName,
        data: JSON.stringify(base64),
        contentType: "application/json",
        dataType: "json",
        success: function (data) {
            var link = document.createElement('a');
            link.href = 'data:application/pdf;base64,' + data.document;
            link.download = 'document.pdf';
            link.click();

            var documentLoadSettings = {
                pdfjs: { 
                  workerSourcePath: 'https://cdnjs.cloudflare.com/ajax/libs/pdf.js/4.0.379/pdf.worker.min.mjs', 
                  librarySourcePath: 'https://cdnjs.cloudflare.com/ajax/libs/pdf.js/4.0.379/pdf.min.mjs'
                }
            }

            // load the document into the viewer
            TXDocumentViewer.loadDocument(data.document, "document.pdf", null, documentLoadSettings);
        }
    });
}

The Finalize method uses the ServerTextControl to load the document, flatten the form fields, and extract the form field values as a JSON string for further processing. This generated JSON is stored in the Data folder on the server for demonstration purposes.

[HttpPost]
public IActionResult Finalize([FromBody] string document, [FromQuery] string templateName)
{
   if (string.IsNullOrEmpty(document) || string.IsNullOrEmpty(templateName))
   {
       return BadRequest("Document and template name must be provided.");
   }

   try
   {
       using (ServerTextControl tx = new ServerTextControl())
       {
           // Load the document
           tx.Create();
           byte[] bytes = Convert.FromBase64String(document);
           tx.Load(bytes, BinaryStreamType.InternalUnicodeFormat);

           // Convert form fields to JSON
           string jsonData = FormFieldHelper.FormFieldsToJson(tx);

           // Get filename from templateName without extension
           string fileName = Path.GetFileNameWithoutExtension(templateName);
           string dataPath = Path.Combine("Data", fileName + ".json");

           // Ensure the directory exists
           string directoryPath = Path.GetDirectoryName(dataPath);
           if (!Directory.Exists(directoryPath))
           {
               Directory.CreateDirectory(directoryPath);
           }

           // Save JSON data to file
           System.IO.File.WriteAllText(dataPath, jsonData);

           // Flatten form fields
           FormFieldHelper.FlattenFormFields(tx);

           // Save the document to a byte array
           byte[] finalDocument;
           tx.Save(out finalDocument, BinaryStreamType.AdobePDF);

           // Convert byte array to base64 string
           string finalDocumentBase64 = Convert.ToBase64String(finalDocument);

           // Return the document as a JSON object
           return Json(new { document = finalDocumentBase64 });
       }
   }
   catch (FormatException)
   {
       return BadRequest("Invalid base64 string.");
   }
   catch (IOException ex)
   {
       return StatusCode(500, "Error processing the document.");
   }
   catch (Exception ex)
   {
       return StatusCode(500, "An unexpected error occurred.");
   }
}

In the following screenshot, you can see the flattened PDF file loaded into the Document Viewer and the downloaded PDF file.

Form Field Processing Workflow

Conclusion

This tutorial showed how to create a form field processing workflow using TX Text Control. The sample project demonstrates how to design a template using the TX Text Control Document Editor, merge data into the template, deploy the document for users to fill in form fields, extract the form field values from the completed document, and create the final document as a PDF with flattened form fields.

The sample project is available on GitHub and can be downloaded and tested. The project contains all the necessary process steps and classes to integrate such a document processing workflow into your own applications.

Stay in the loop!

Subscribe to the newsletter to receive the latest updates.

GitHub

Download and Fork This Sample on GitHub

We proudly host our sample code on github.com/TextControl.

Please fork and contribute.

Download ZIP

Open on GitHub

Open in Visual Studio

Requirements for this sample

  • TX Text Control .NET Server
  • Visual Studio 2022

ASP.NET

Integrate document processing into your applications to create documents such as PDFs and MS Word documents, including client-side document editing, viewing, and electronic signatures.

ASP.NET Core
Angular
Blazor
JavaScript
React
  • Angular
  • Blazor
  • React
  • JavaScript
  • ASP.NET MVC, ASP.NET Core, and WebForms

Learn more Trial token Download trial

Related Posts

ASP.NETReportingASP.NET Core

Advantages of Flow Type Layout Reporting vs. Banded Reporting or PDF…

This article shows the advantages of flow type layout reporting compared to banded reporting or populating PDF placeholders in .NET C#. It explains the differences and the benefits of using a flow…


ASP.NETASP.NET CoreDOCX

Use MailMerge in .NET on Linux to Generate Pixel-Perfect PDFs from DOCX…

This article explores how to use the TX Text Control MailMerge feature in .NET applications on Linux to generate pixel-perfect PDFs from DOCX templates. This powerful combination enables…


ASP.NETASP.NET CoreContract

Generating Dynamic NDAs Using TX Text Control MailMerge in C# .NET

This article demonstrates how to generate dynamic NDAs using TX Text Control MailMerge in C# .NET. It covers the process of creating a template, binding data, and generating the final document.


ASP.NETASP.NET CoreBackend

Designing a Maintainable PDF Generation Web API in ASP.NET Core (Linux) C#…

This article shows how to create a PDF generation Web API in ASP.NET Core on Linux using TX Text Control .NET Server. The clean architecture is used to create a maintainable and testable solution.


ASP.NETASP.NET CoreMailMerge

Manipulating Table Cells During the MailMerge Process in .NET C#

This article shows how to manipulate table cells during the mail merge process in .NET C#. The FieldMerged event can be used to manipulate the table cells after they are merged.