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);
}
});
});
}
view raw test.js hosted with ❤ by GitHub

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.");
}
}
view raw test.cs hosted with ❤ by GitHub

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.");
}
}
view raw test.cs hosted with ❤ by GitHub

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);
}
});
}
view raw test.js hosted with ❤ by GitHub

The Finalize method uses the ServerTextControl TX Text Control .NET Server for ASP.NET
TXTextControl Namespace
ServerTextControl Class
The ServerTextControl class implements a component that provide high-level text processing features for server-based applications.
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.");
}
}
view raw test.cs hosted with ❤ by GitHub

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.