The MailMerge TX Text Control .NET Server for ASP.NET
DocumentServer Namespace
MailMerge Class
The MailMerge class is a .NET component that can be used to effortlessly merge template documents with database content in .NET projects, such as ASP.NET web applications, web services or Windows services.
class in TX Text Control is a powerful feature for creating dynamic, data-driven documents. It automates the process of merging templates with data to create personalized or structured documents such as letters, invoices, or reports.

Merge Blocks are an advanced feature of the MailMerge class that allows you to create repeating sections in a document, such as:

  • Tables with multiple rows.
  • Lists of items (e.g., invoice line items).
  • Nested data structures (e.g., orders with multiple products).

The MailMerge class allows you to use various data sources to merge content into templates, including JSON, XML, or IEnumerable objects. In this article, we will focus on using objects and arrays of objects that contain self-calculating properties.

Self-Calculating Business Objects

Self-calculating business objects are a programming design pattern (not formally recognized as a named design pattern in canonical design patterns) in which objects contain properties and methods to automatically calculate certain derived values, such as a sum total, based on their internal state or related objects. This approach ensures that calculated values remain accurate and consistent without requiring external logic to perform the calculations.

A self-calculating business object typically includes:

  • Properties that store raw data or values.
  • Methods that calculate derived values based on the raw data or other objects.
  • Event handlers that update derived values when raw data changes.

Since we are only using the data for merging and providing fixed records, we don't need the event handlers in this case.

Example: Invoice with Line Items

Consider an Invoice class that contains a list of LineItem objects. The Invoice object dynamically calculates the total cost of items and the LineItem object calculates the total cost of the line item based on the quantity and unit price.

public class Invoice
{
public string Customer { get; set; }
public List<LineItem> LineItems { get; set; }
public decimal Total => LineItems.Sum(x => x.Total);
}
public class LineItem
{
public string Name { get; set; }
public int Quantity { get; set; }
public decimal Price { get; set; }
public decimal Total => Quantity * Price;
}
view raw test.cs hosted with ❤ by GitHub

The following screenshot shows a sample invoice template with merge fields for the invoice customer, the merge block for the line items, and the total amount:

TX Text Control MailMerge Template

The following code snippet shows how to merge the Invoice object into the template:

// Create an instance of the Invoice class and populate it with customer data and line items.
Invoice invoice = new Invoice()
{
Customer = "John Doe", // Set the customer's name.
LineItems = new List<LineItem>() // Initialize the list of line items for the invoice.
{
new LineItem() { Name = "Item 1", Quantity = 2, Price = 10 }, // Add the first line item.
new LineItem() { Name = "Item 2", Quantity = 3, Price = 20 }, // Add the second line item.
new LineItem() { Name = "Item 3", Quantity = 1, Price = 30 } // Add the third line item.
}
};
// Create a new instance of ServerTextControl, which will handle the document processing.
using (ServerTextControl tx = new ServerTextControl())
{
tx.Create(); // Initialize the TextControl instance.
// Load the template file into the TextControl instance.
tx.Load("template.tx", StreamType.InternalUnicodeFormat);
// Create a MailMerge instance and associate it with the TextControl instance.
MailMerge mailMerge = new MailMerge()
{
TextComponent = tx // Set the TextControl instance as the target for the MailMerge.
};
// Perform the mail merge using the invoice object to populate the template placeholders.
mailMerge.MergeObject(invoice);
}
view raw test.cs hosted with ❤ by GitHub

The following screenshot shows the resulting document with the merged data. The red circles highlight the merge fields that have been dynamically replaced with the calculated values:

TX Text Control MailMerge Result

Self-calculating business objects offer significant advantages in scenarios that require dynamic and real-time calculations, such as invoices, shopping carts, or financial reports. By encapsulating the calculation logic within the objects themselves, they ensure that derived values such as totals, subtotals, or tax amounts are always accurate and up-to-date, reflecting any changes in the underlying data instantly. This approach not only improves consistency throughout the application, but also reduces the need for repetitive external logic, simplifying code and improving maintainability.

The code above showed how to merge a single object, but MailMerge can also be used to merge a list of objects, such as an array or a list. This allows you to create multiple instances of the same template with different data, such as generating invoices for multiple customers or reports for multiple products.

The following code snippet shows how to merge a list of Invoice objects into the template using the MergeObjects TX Text Control .NET Server for ASP.NET
DocumentServer Namespace
MailMerge Class
MergeObjects Method
Merges a collection of type System.Collections.IEnumerable containing objects of any type or instances of type System.Collections.Generic.Dictionary with string keys into the loaded document template.
method:

// Create a list of invoices, each containing a customer and a list of line items.
List<Invoice> invoices = new List<Invoice>()
{
// First invoice for customer "ACME Inc."
new Invoice()
{
Customer = "ACME Inc.", // Set the customer name.
LineItems = new List<LineItem>() // Define the line items for this invoice.
{
new LineItem() { Name = "Product 1", Quantity = 2, Price = 100 }, // First line item.
new LineItem() { Name = "Product 2", Quantity = 3, Price = 200 } // Second line item.
}
},
// Second invoice for customer "Sample, LLC"
new Invoice()
{
Customer = "Sample, LLC", // Set the customer name.
LineItems = new List<LineItem>() // Define the line items for this invoice.
{
new LineItem() { Name = "Product 3", Quantity = 1, Price = 300 }, // First line item.
new LineItem() { Name = "Product 4", Quantity = 4, Price = 400 } // Second line item.
}
},
// Third invoice for customer "Test GmbH"
new Invoice()
{
Customer = "Test GmbH", // Set the customer name.
LineItems = new List<LineItem>() // Define the line items for this invoice.
{
new LineItem() { Name = "Product 5", Quantity = 2, Price = 500 }, // First line item.
new LineItem() { Name = "Product 6", Quantity = 3, Price = 600 } // Second line item.
}
}
};
// Create a new instance of ServerTextControl for document processing.
using (ServerTextControl tx = new ServerTextControl())
{
tx.Create(); // Initialize the ServerTextControl instance.
// Load the template document that contains placeholders for the mail merge.
tx.Load("template.tx", StreamType.InternalUnicodeFormat);
// Create a MailMerge instance and associate it with the ServerTextControl instance.
MailMerge mailMerge = new MailMerge()
{
TextComponent = tx // Attach the ServerTextControl as the target for the merge operation.
};
// Merge the list of invoice objects into the template document.
// This processes all invoices, creating a document for each one based on the template.
mailMerge.MergeObjects(invoices);
}
view raw test.cs hosted with ❤ by GitHub

The resulting document will contain multiple invoices, each with its own line items and total amount.

Conclusion

Self-calculating business objects are a powerful design pattern that simplifies the process of creating dynamic, data-driven documents using TX Text Control's MailMerge feature. By encapsulating the calculation logic within the objects themselves, you can ensure that the derived values are always accurate and up-to-date, reflecting any changes in the underlying data immediately. This approach not only improves consistency throughout the application, but also reduces the need for repetitive external logic, simplifying code and improving maintainability.