Using XSLT as email template engine in C#

Email has been (and will be for some time) one of the main means to communicate with your customers and perform various core business and security tasks (such as confirming a newly created accounts, helping a user reset their lost password, notify updates and required actions, etc.). These emails usually consist of static sections and some dynamic parts that are specific to the user receiving the email.

Sometimes, a simple string replacement approach works to achieve such goal (that’s what I used to do before). But if you need something more elegant and powerful than that, a good option would be using XSLT. I am no XSLT expert and I won’t talk about it in this post, but I encourage you to learn about it if you don’t already know. In order to follow the principle of separation of concerns and improve testability, the solution is separated into four components with their corresponding interface (contract):

  • A XSLT template compiler (ITemplateCompiler). A simple wrapper that uses cached XslCompiledTransform‘s.
  • An email sender (IEmailSender). Another wrapper, in this case, around the SmtpClient. This is abstracted away in order to mock the actual sending of the email when testing (dump the result to console or to a text file, etc.).
  • A custom XML serializer (IXmlSerializer). Why not use the built in XML serializer? Simple: it doesn’t work with anonymous objects. Sometimes we want to pass our variables without having to explicitly create a class for it. In case you do want to use the regular serializer, you can always create a wrapper that implements IXmlSerializer.
  • A template email sender (ITemplateEmailSender). Integrates all the above mentioned services.

The XSLT compiler

Not much to say about it. It will accept an input XML stream (this would be your variables object serialized as XML), an XSLT file path (or stream), and an output stream to dump the resulting transformation. If you use the overload that accepts the XSLT file path, the XslCompiledTransform object will be cached.

The email sender

Again, as simple as it sounds. Just to decouple the actual sending of the email. In the example, I dump the result to an HTML file called output.html.

The XML Serializer

For the custom XML serializer, I borrowed Martin Normark‘s solution, but made some modifications to it, mainly allowing for the serialization of any kind enumerable, not only arrays.

Basically, it will turn any object into XML following these rules:

  1. If no root element name is provided, “object” will be used.
  2. All properties will be serialized as XML nodes with the same name as the property.
  3. For collection properties, the main node will be named after the property, and the child nodes will have the same name with the suffix “Item” appended.

The template email sender

This is the one that puts all together, and has dependencies to everything else. It only has a Send method (and its async counterpart). You’ll notice that it does not accept a from parameter. That’s because you usually handle that in the SMTP configuration part of your project’s web.config or app.config. If you need it, just go ahead and add it.

Additionally, this service has a LayoutFilePath property. Inspired by ASP .NET’s layout (or master) pages, only much simpler, this allows to have a base, static HTML content file where you can put the frame and layout that is common to all the emails that you will send. If this property is null, then the output will be only what results from the XSLT transformation. The only requirement for your layout file is that you need to include the following wherever you want the content placed:

<!-- Content -->

For example:

<html>
<head>
</head>
<body>
<div style="height: 10px; font-size: 10px; line-height: 10px;">&nbsp;</div>
<table width="602" border="0" cellspacing="0" cellpadding="0" align="center">
<tbody>
<tr>
<td>
<!-- Content --></td>
</tr>
</tbody>
</table>
<div style="height: 10px; font-size: 10px; line-height: 10px;">&nbsp;</div>
</body>
</html>

Putting it all together

var templateDirectory = Path.Combine(Environment.CurrentDirectory, "Templates");
var layoutFile = Path.Combine(templateDirectory, "layout.html");
var xsltFilePath = Path.Combine(templateDirectory, "ActivateAccount.xslt");
var variables = new
{
FirstName = "Axel",
LastName = "Zarate",
Username = "azarate",
Logo = "http://www.logotree.com/images/single-logo-design/logo-design-sample-14.jpg",
ActivationLink = "http://localhost/Account/Activate/azarate"
};

var templateEmailSender = new TemplateEmailSender(emailSender, templateCompiler, xmlSerializer)
{
LayoutFilePath = layoutFile
};

templateEmailSender.Send(xsltFilePath, variables, "axel.zarate@mail.com", "This is a template test");

Advice: To maximize email viewing compatibility across different clients, use regular tables for layout and old HTML attributes for appearance (width, bgcolor, etc.).

Check out the source code and sample.

7 thoughts on “Using XSLT as email template engine in C#

  1. Thank you Axel; What will the XSLT look like if we have to render a collection of items in a tabular format? Can you please post an example XSLT for that?

    • Hi, I’ve updated the Sample Code and added a simple use of an if condition and a for each statements in the XSLT file. You can play around with different values to get a better feel.

      • Excellent; I just tried it and now I can get the xml; I asked because I wanted to modify the XSLT for my requirements, but wasn’t sure what the serialized object will look as xml. Muchas Gracias.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s