Store and Merge Templates in a Database using LiteDB and ASP.NET Core C#
Editing the template, storing it in a database, and then merging it is a typical workflow for TX Text Control. This example will show you how to create a new template and how to store it in a LiteDB database. The template is then loaded from the database and merged with data.

A very typical application for the variety of components that are part of TX Text Control is the visual creation of templates that are stored in a database. Documents in formats such as PDF are created by merging data into the stored templates.
To store the templates, this sample application uses a file-based database called LiteDB. The templates are created using the Document Editor visual component, and the templates are finally merged using the Mail
Template Overview
When you start the application, you will see an overview of all the templates you have created.
Data Excerpt Files
When you create a new template, the Document Editor is opened and dummy JSON data is generated to fill in the drop-down lists that contain the names of the fields that can be used.
A simple invoice structure is used as the data source.
public class Invoice
{
public string InvoiceID { get; set; }
public Customer Customer { get; set; }
public string InvoiceNumber { get; set; }
public string InvoiceDate { get; set; }
public List<LineItem> LineItems { get; set; }
}
public class LineItem
{
public string LineItemID { get; set; }
public string Description { get; set; }
public string Quantity { get; set; }
public string Price { get; set; }
public string Tax { get; set; }
public string Total { get; set; }
}
public class Customer
{
public string CustomerID { get; set; }
public string Name { get; set; }
public string Email { get; set; }
public string Phone { get; set; }
public string Address { get; set; }
public string City { get; set; }
public string State { get; set; }
public string Zip { get; set; }
public string Country { get; set; }
}
The GetDummyInvoiceData method generates a dummy JSON file from the data structure, which is then used in the Document Editor.
public static string GetDummyInvoiceData()
{
Invoice invoice = new Invoice
{
InvoiceID = "123456789",
InvoiceNumber = "123456789",
InvoiceDate = "2020-01-01",
Customer = new Customer
{
CustomerID = "123456789",
Name = "John Doe",
Email = ""
},
LineItems = new List<LineItem>
{
new LineItem
{
LineItemID = "123456789",
Description = "Item 1",
Quantity = "1",
Price = "100.00",
Tax = "10.00",
Total = "110.00"
},
new LineItem
{
LineItemID = "123456789",
Description = "Item 2",
Quantity = "1",
Price = "100.00",
Tax = "10.00",
Total = "110.00"
},
new LineItem
{
LineItemID = "123456789",
Description = "Item 3",
Quantity = "1",
Price = "100.00",
Tax = "10.00",
Total = "110.00"
}
}
};
List<Invoice> invoices = new List<Invoice>();
invoices.Add(invoice);
return JsonConvert.SerializeObject(invoices);
}
Creating the Editor
In the controller method Editor, the dummy data is created, and if an existing template is to be opened, the template is retrieved from the database.
public IActionResult Editor(string id = null)
{
EditorViewModel model = new EditorViewModel()
{
InvoiceData = InvoiceData.GetDummyInvoiceData(),
DocumentId = id
};
if (id != null)
{
// url encoded
id = id.Replace("%2F", "/");
model.TemplateData = Storage.GetTemplate(id);
}
return View(model);
}
In the view itself, the data and template are loaded into a Document Editor instance.
@{
if (Model.TemplateData != null)
{
@Html.TXTextControl().TextControl().LoadDataFromJson(Model.InvoiceData).LoadText(Convert.FromBase64String(Model.TemplateData), TXTextControl.Web.BinaryStreamType.InternalUnicodeFormat).Render()
}
else
{
@Html.TXTextControl().TextControl().LoadDataFromJson(Model.InvoiceData).Render()
}
}
Template Storage
Once the template with merge fields and repeating blocks is created, the template can be saved using the Save button.
The saveDocument JavaScript function saves the document and posts it to the Home/Save endpoint along with the document ID.
function saveDocument() {
TXTextControl.saveDocument(TXTextControl.StreamType.InternalUnicodeFormat, function (content) {
$.ajax({
type: "POST",
url: "/Home/Save?id=@Model.DocumentId",
contentType: "application/json",
data: JSON.stringify(content),
success: function () {
setDirtyFlag();
$("#save").addClass("disabled");
},
error: function () {
alert("An error occurred while saving the data.");
}
});
});
}
The endpoint calls the Storage.AddTemplate method with the document data and ID.
[HttpPost]
public IActionResult Save([FromBody] Content data, string id)
{
Storage.AddTemplate(new MemoryStream(Convert.FromBase64String(data.Data)), id);
return Ok();
}
This method uses LiteDB to store the file in the database with the unique identifier.
private static readonly LiteDatabase db = new LiteDatabase(@"Filename=App_Data/documents.db; Connection=shared");
public static void AddTemplate(MemoryStream stream, string id = null, string name = "template.tx")
{
var templateId = id ?? "$/templates/" + Guid.NewGuid().ToString();
db.FileStorage.Upload(templateId, name, stream);
}
Mail Merge
When you click Merge, the template is retrieved from the database and merged with the invoice data.
A PDF is created and downloaded directly.
The Merge method retrieves the template from the database by the given ID and uses Mail
public IActionResult Merge(string id)
{
// url encoded
id = id.Replace("%2F", "/");
var templateData = Storage.GetTemplate(id);
using (TXTextControl.ServerTextControl tx = new TXTextControl.ServerTextControl())
{
tx.Create();
tx.Load(Convert.FromBase64String(templateData), TXTextControl.BinaryStreamType.InternalUnicodeFormat);
using (MailMerge mailMerge = new MailMerge())
{
mailMerge.TextComponent = tx;
mailMerge.MergeJsonData(InvoiceData.GetDummyInvoiceData());
}
tx.Save(out byte[] data, TXTextControl.BinaryStreamType.AdobePDF);
// return pdf document
return File(data, "application/pdf", "document.pdf");
}
}
To see how the database interface works to store templates and merge data into them to generate PDF documents, you can download the full sources of this sample.
Download and Fork This Sample on GitHub
We proudly host our sample code on github.com/TextControl.
Please fork and contribute.
Requirements for this sample
- TX Text Control .NET Server Core
- Visual Studio 2022
Related Posts
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…
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.
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.
Getting Started: ServerTextControl and MailMerge in a .NET 8 Console…
This article shows how to create a .NET 8 console application on Linux using Docker and WSL that uses the ServerTextControl to create a document and MailMerge to merge JSON data into the document.…
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.