code first, ask questions later

User Control Email Templates in asp.net

Just about every project i work on needs to send customized emails and everytime I hate doing it. Inspired by some answers in this stackoverflow question I thought I’d give a simple .ascx based email template system a dig.

First thing I did was set up a base class for template controls to inherit from. This class inherits from UserControl and has the methods to render the control to a string. It also has methods and properties to set up “tags” to replace in the email body.

public class EmailTemplateBase : UserControl
{
    public EmailTemplateBase()
    {
        Tags = new Dictionary<string, string>();
    }

    public Dictionary<string, string> Tags { get; set; }

    protected string GetTagValue(string tagName)
    {
        return Tags[tagName].Value;
    }

    protected string GetTagValue(string tagName, string defaultValue)
    {
        string val = GetTagValue(tagName);
        return string.IsNullOrEmpty(val) ? defaultValue : val;
    }

    public string RenderTemplate()
    {
        StringBuilder sb = new StringBuilder();
        StringWriter sw = new StringWriter(sb);
        Html32TextWriter htw = new Html32TextWriter(sw);
        RenderControl(htw);

        // Get full body text
        return sb.ToString();
    }
}

Below is a simple example from the project I am working on it is used for sending feedback emailsĀ  This template is really simple but because the rendering uses the same page cycle as a regular control you can style and render the template how ever you like.

<p>
   Feedback from System sent <%= GetTagValue("sent")%>
</p>

<p>
    <strong>Sender: </strong> <%= GetTagValue("sender")%><br />
    <strong>Subject: </strong> <%= GetTagValue("subject")%>
</p>

<p>
    <strong>Message: </strong> <br />
     <%= GetTagValue("message").Replace(Environment.NewLine, "<br />")%>
</p>

I created a class to easily load and use the email templates within my code by passing the location of the template on the server.


public class EmailTemplate
{
    private readonly EmailTemplateBase _template;

    public EmailTemplate(string templateLocation)
    {
        Page p = new Page();
        _template = (EmailTemplateBase) p.LoadControl(templateLocation);
    }

    public Dictionary<string, string> Tags
    {
        get { return _template.Tags; }
        set { _template.Tags = value; }
    }

    public string Render()
    {
        return _template.RenderTemplate();
    }
}

Below is how I use the templates in my code, sending using a basic email sender class I have (or better still fluent email).

var template = new Common.Email.EmailTemplate("~/Emails/Templates/Feedback.ascx");
template.Tags.Add("sender", sender);
template.Tags.Add("sent", sent);
template.Tags.Add("subject", subject);
template.Tags.Add("message", message);

string body = template.Render();

EmailSender.Send(from, fromName, to, toName, subject, body);

I could probably try encapsulate a bit more of the email sending inside my template (toName, toAddress etc) to clean this up a bit so feel free to tell me how come I suck.

blog comments powered by Disqus