Documents with form elements such as form text boxes, check box fields, drop-downs and date picker elements can be created like mail merge templates and dynamically pre-completed with known values. This helps to generate custom forms where some fields are already completed with known values to accelerate the completion process and to improve the user experience.

Sample Database

The sample uses a simple, serverless NoSQL database (LiteDB) to store customer address data. The Customer model is defined through the following code:

public class Customer
{
public long Id { get; set; }
public string Name { get; set; }
public string Firstname { get; set; }
public string Street { get; set; }
public string City { get; set; }
public string State { get; set; }
public string Postalcode { get; set; }
public DateTime DOB { get; set; }
public bool Tax { get; set; }
}
view raw Customer.cs hosted with ❤ by GitHub

The sample view is a very simple table that lists all customers from the database:

Selecting the user

The template contains some form text fields, drop-downs, a date picker element and a check box to cover all available form field elements. The form field names match the property names in the Customer data model.

Sample template

When clicking the button Download Form, the sample template is loaded into a 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.
instance in order to loop through all form fields in each text part (headers, footers, main text, text frames).

[HttpPost]
public ActionResult GenerateForm(int Id)
{
Customer customer;
byte[] baCreatedFormDocument;
// get customer by Id from database
using (var db = new LiteDatabase(Server.MapPath("~/App_Data/customers.db")))
{
var col = db.GetCollection<Customer>("customers");
col.EnsureIndex(x => x.Id);
customer = col.Query()
.Where(x => x.Id == Id)
.SingleOrDefault();
}
using (TXTextControl.ServerTextControl tx = new TXTextControl.ServerTextControl())
{
tx.Create();
// the form template
tx.Load(Server.MapPath("~/App_data/form_template.tx"),
TXTextControl.StreamType.InternalUnicodeFormat);
// loop through all form fields of each text part
foreach (IFormattedText textPart in tx.TextParts)
{
foreach (FormField formField in textPart.FormFields)
{
// get associated value of property; check for null!
var propertyValue =
typeof(Customer).GetProperty(formField.Name)?.GetValue(customer);
// cast values for specific form field types
switch (formField.GetType().ToString())
{
case "TXTextControl.TextFormField": // accepts strings
case "TXTextControl.SelectionFormField":
if (propertyValue != null)
((TextFormField)formField).Text = (string)propertyValue;
break;
case "TXTextControl.CheckFormField": // accepts bool
if (propertyValue != null)
((CheckFormField)formField).Checked = (bool)propertyValue;
break;
case "TXTextControl.DateFormField": // accepts Win32 file dates
if (propertyValue != null)
{
if (Convert.ToDateTime(propertyValue.ToString())
!= DateTime.MinValue)
((DateFormField)formField).Date =
Convert.ToDateTime(propertyValue.ToString());
}
break;
}
}
}
// export form
tx.Save(out baCreatedFormDocument, BinaryStreamType.AdobePDF);
}
// return the PDF as an attachment
MemoryStream pdfStream = new MemoryStream();
pdfStream.Write(baCreatedFormDocument, 0, baCreatedFormDocument.Length);
pdfStream.Position = 0;
Response.AppendHeader("content-disposition",
"attachment; filename=form_" + Id + ".pdf");
return new FileStreamResult(pdfStream, "application/pdf");
}
view raw test.cs hosted with ❤ by GitHub

Generic Function to Merge the Data

The customer address record with the given Id is retrieved from the database and used to populate the existing form fields. The interesting code line is the following line:

var propertyValue = typeof(Customer).GetProperty(formField.Name)?.GetValue(customer);
view raw Customer.cs hosted with ❤ by GitHub

This code is trying to read a property from the Customer object with the form field name. This makes this code very generic as the values are then casted to the proper type and applied to the appropriate property ( Text TX Text Control .NET Server for ASP.NET
TXTextControl Namespace
TextField Class
Text Property
Returns or sets the text which is contained within a text field.
, Checked TX Text Control .NET Server for ASP.NET
TXTextControl Namespace
CheckFormField Class
Checked Property
Gets or set a value indicating whether the checkbox is in the checked state.
, Date TX Text Control .NET Server for ASP.NET
TXTextControl Namespace
DateFormField Class
Date Property
Gets or sets the DateFormField's date.
).

After all available fields have been merged, the document is exported to PDF and returned as an attachment for download:

Sample template

You can download the sample from our GitHub repository to try this on your own. Let us know, if you have any questions about how to integrate document workflows into your business applications.