My answer, uses hannes neukermans answer from here.
I needed to use RazorEngine in an MVC project to send emails incorporating html strings stored in a database so that they could be edited by admin users.
The standard RazorEngine config didn't allow @Html.Raw to work.
In my emails class I set up a new Engine.Razor (Engine is static) that incorporates the classes Hannes recommends. I only needed the Raw method, but you can obviously add others :
you will need these:
using RazorEngine;
using RazorEngine.Templating; // For extension methods.
using RazorEngine.Text;
using RazorEngine.Configuration;
These are the classes to provide the @Html helpers
public class HtmlSupportTemplateBase<T> : TemplateBase<T>
{
public HtmlSupportTemplateBase()
{
Html = new MyHtmlHelper();
}
public MyHtmlHelper Html { get; set; }
}
public class MyHtmlHelper
{
/// <summary>
/// Instructs razor to render a string without applying html encoding.
/// </summary>
/// <param name="htmlString"></param>
/// <returns></returns>
public IEncodedString Raw(string htmlString)
{
return new RawString(WebUtility.HtmlEncode(htmlString)); //you may not need the WebUtility.HtmlEncode here, but I did
}
}
I could then use @Html.Raw in my emails template to incorporate the editable html
public class Emails
{
public static TemplateServiceConfiguration config
= new TemplateServiceConfiguration(); // create a new config
public Emails()
{
config.BaseTemplateType = typeof(HtmlSupportTemplateBase<>);// incorporate the Html helper class
Engine.Razor = RazorEngineService.Create(config);// use that config to assign a new razor service
}
public static void SendHtmlEmail(string template, EmailModel model)
{
string emailBody
= Engine.Razor.RunCompile(template, model.Type.ToString(), typeof(EmailModel), model);
var smtpClient = getStaticSmtpObject(); // an external method not included here
MailMessage message = new MailMessage();
message.From = new MailAddress(model.FromAddress);
message.To.Add(model.EmailAddress);
message.Subject = model.Subject;
message.IsBodyHtml = true;
message.Body = System.Net.WebUtility.HtmlDecode(emailBody);
smtpClient.SendAsync(message, model);
}
}
Then I could use it by passing in the string read from the actual .cshtml template and the model holding the email data.
string template = System.IO.File.ReadAllText(ResolveConfigurationPath("~/Views/Emails/Email.cshtml"));
SendHtmlEmail(template, model);
ResolveConfigurationPath is another external function I found.
public static string ResolveConfigurationPath(string configPath)
{
if (configPath.StartsWith("~/"))
{
// +1 to Stack Overflow:
// http://stackoverflow.com/questions/4742257/how-to-use-server-mappath-when-httpcontext-current-is-nothing
// Support unit testing scenario where hosting environment is not initialized.
var hostingRoot = HostingEnvironment.IsHosted
? HostingEnvironment.MapPath("~/")
: AppDomain.CurrentDomain.BaseDirectory;
return Path.Combine(hostingRoot, configPath.Substring(2).Replace('/', '\\'));
}
return configPath;
}