Search code examples
razorrazorengine

Get a reference to a compiled template


I would like to set email related properties on my razor template base class which can be used to send an email with the rendered template as the body.

How can I get a reference to the compiled template?


Solution

  • No you can't and that's by design. But you probably want to do the following instead:

    public class EmailDataHolder {
        public string Destination { get; set; }
        public string Subject { get; set; }
    }
    // In the custom TemplateBase class:
    public class EmailTemplateBase<T> : TemplateBase<T>
    {
        public EmailDataHolder EmailProperties { get { return Viewbag.DataHolder; } }
        // Or for even simpler templates
        //public string Subject { get { return Viewbag.DataHolder.Subject; }; set { Viewbag.DataHolder.Subject = value; } }
    }
    
    // Your code
    public static Task SendEmailAsync<T>(string templateName, string destination, T model)
    {
        var holder = new EmailDataHolder();
        dynamic viewbag = new DynamicViewBag();
        viewbag.DataHolder = holder;
        holder.Destination = destination;
        var body = Engine.Razor.Run(templateName, typeof(T), model, (DynamicViewBag)viewbag);
    
        MailMessage msg = new MailMessage();
        msg.To.Add(new MailAddress(holder.Destination));
        msg.Subject = holder.Subject;
        msg.AlternateViews.Add(AlternateView.CreateAlternateViewFromString(body, null, MediaTypeNames.Text.Html));
    
        SmtpClient smtpClient = new SmtpClient();
        return smtpClient.SendMailAsync(msg);
    }
    

    If you want to use @model you want to configure RazorEngine to use this custom TemplateBase implementation:

    config.BaseTemplateType = typeof(EmailTemplateBase<>);
    

    and then you can use it like this:

    @inherits EmailTemplateBase<HelloWorldModel>
    @{
        Layout = "CI";
        EmailProperties.Subject = "Hello World";
        // with the simpler version
        //Subject = "Hello World";
    }
    Hello @Model.Name,<br/>
    this is a test email...
    

    While this doesn't really give you the reference to the compiled template it allows you to save data within the template and use it later.