I use razor engine like this:
public class EmailService : IService
{
private readonly ITemplateService templateService;
public EmailService(ITemplateService templateService)
{
if (templateService == null)
{
throw new ArgumentNullException("templateService");
}
this.templateService = templateService;
}
public string GetEmailTemplate(string templateName)
{
if (templateName == null)
{
throw new ArgumentNullException("templateName");
}
Assembly assembly = Assembly.GetAssembly(typeof(EmailTemplate));
Stream stream = assembly.GetManifestResourceStream(typeof(EmailTemplate), "{0}.cshtml".FormatWith(templateName));
string template = stream.ReadFully();
return template;
}
public string GetEmailBody(string templateName, object model = null)
{
if (templateName == null)
{
throw new ArgumentNullException("templateName");
}
string template = GetEmailTemplate(templateName);
string emailBody = templateService.Parse(template, model, null, null);
return emailBody;
}
}
The templating service I use is injected although it’s just a default implementation:
internal ITemplateService InstanceDefaultTemplateService()
{
ITemplateServiceConfiguration configuration = new TemplateServiceConfiguration();
ITemplateService service = new TemplateService(configuration);
return service;
}
Since in this case in particular I will be building emails from these templates. I want to be able to use @sections for the email’a subject, and different sections of the email body, while using a layout where I specify the styles that are common to the whole email structure (which will look like one of MailChimp‘s probably).
The question is then twofold:
- How can I specify layouts in
RazorEngine? - How can I specify these layouts from strings (or a stream)? since as you can see, I use embedded resources to store the razor email templates.
Update
Maybe I wasn’t clear, but I’m referring to the RazorEngine library.
Turns out after some digging that layouts are supported, we just have to declare them with
_Layoutinstead ofLayoutAs for the embedded resource issue, I implemented the following
ITemplateResolverThen you just wire it like this:
The type you pass is just for referencing the assembly and namespace where the resources are embedded.
One last thing, in order to have the templates resolved with our resolver we have to resolve them like this:
.Runis just a simple extension method since I can’t find any use for aViewBag.UPDATE
Here are the missing extensions