Tatham Oddie

Enter the Tatrix

Generating HTML emails using ASP.NET

with 6 comments

It’s a pretty common requirement these days to send a nicely formatted email, yet I’ve come across very few “nice” solutions.

The solution I’ve come to use is simple, and documented across the web, but rarely used in the real world.

The most common code I see (and what I used to write back in the days of .NET1.0 powered dinosaurs roaming the earth) revolves around ugly use of the StringBuilder:

MailBody.Append("<html><head></head><body> \n");
MailBody.Append("<span style=\"font-size: 11 px; font-family:Verdana,Helvetica, sans-serif\">Hi,<br><br>Your account information as it has been retrieved from the database:</span><br><br> \n");
MailBody.Append("<div style=\"font-size: 11 px; font-family:Verdana,Helvetica, sans-serif\">Username: " + UserData.Username + "<br><br>" + "Password: " + UserData.Password + "</div> \n");
MailBody.Append("</body></html>");

Ugly. Unmaintainable.

Instead, create a user control for your email template using standard ASP.NET controls:

<%@ Control Language="C#" AutoEventWireup="true" CodeBehind="PasswordRecovery.ascx.cs" Inherits="SampleApp.WebUI.EmailTemplates.PasswordRecovery" %>
<h1>Password Recovery</h1>
<p>Your new password is <asp:Literal ID="NewPassword" runat="server" />.</p>

Expose a property for each value that you need to include in the email:

public string Password
{
     get { return NewPassword.Text; }
     set { NewPassword.Text = value; }
}

Now just render the control on demand:

private string RenderControl(Control control)
{
    StringBuilder stringBuilder = new StringBuilder();
    StringWriter stringWriter = new StringWriter(stringBuilder);
    HtmlTextWriter htmlTextWriter = new HtmlTextWriter(stringWriter);

    control.RenderControl(htmlTextWriter);

    return stringBuilder.ToString();
}

How simple is that. :)

UPDATE: I should mention how to instantiate the control – just calling the default constructor isn’t good enough as you’ll find that all of your controls are null. This is the magic line you’ll need:

EmailTemplates.MembershipApplication emailTemplate = (EmailTemplates.MembershipApplication)LoadControl("~/EmailTemplates/MembershipApplication.ascx"); 

Written by Tatham Oddie

April 2, 2007 at 13:29

Posted in Uncategorized

6 Responses

Subscribe to comments with RSS.

  1. Hi Tatham,

    I’ve been looking for a better way to render HTML emails than manual stringbuilder work. As you say, its ugly and unmanageable if the HTMl is significant.

    I’ve tried implementing this code but I’m having trouble. First I can’t seem to place the rendercontrol function within a code behind file. It complains it shadows an overridable methiod in the base class ‘Control’. Second I’m using VB! Yeah I know, I used to be a C+ developer but had to switch with my work, so been using it no for long time and its fairly productive.

    Anyway, that aside, I’d really appreciate it if you could provide a complete example of the coding and maybe a sample usercontrol its applied to. I’ll then be able to convert to my native coding language.

    Any help much appreciated.
    Steve

    Steve

    September 20, 2008 at 02:33

  2. OK putting the rendercontrol in a public class file has solved point1. So now I’m stuck on instantiating the control and setting all the literals in the template.

    Steve

    September 20, 2008 at 02:51

  3. Finally managed to get everything working. Thanks for the pointers in the first place. I’m now generating very nice emails.

    Steve

    September 20, 2008 at 23:11

  4. Thx I really appreciate your example, I’m having some difficulties though.

    Maybe I’m not as clever as the average bear, but:

    1) Where should the .ascx file be located?
    2) The “RenderControl(Control control)” method, where is this suppose to go? Obviously not in the .ascx.cs file..
    3) Instantiating or initializing the control, you have “EmailTemplates.MembershipApplication”. Is this your own class or is this a built in .net class?

    David

    October 17, 2008 at 13:49

  5. Ah, just re-read Steve’s comment, so the RenderControl method goes in a public class, completely separate from the .ascx file, still working on the rest though.

    David

    October 17, 2008 at 13:50

  6. Hi, I want to say I have been using this pattern for years and it is very successful. I use ASPX, not ascx, and then I use httpwebquest to crawl the contents of that ASPX page..

    Advantages
    1. We can use repeater or datagrid in that ASPX or ASCX
    2. HTML CSS is very strict, we can change design
    3. We can have a master page for email header and footer, because header and footer are replicated contents in most emails
    4 We can truly seperate the presentation layer

    ben

    February 5, 2009 at 21:28


Leave a Reply