Skip to content
Alexander Selishchev edited this page Aug 12, 2021 · 11 revisions

By default, RazorEngine will not encode values to be HTML safe, there are reasons for that.

  • you need to escape values by yourself
  • you need to implement @Raw helper by yourself

But dont worry, this page is here to help.

Default behavior

IRazorEngine razorEngine = new RazorEngine();
IRazorEngineCompiledTemplate template = razorEngine.Compile("Hello @Model.Name");

string result = template.Run(new
{
    Name = "<b>Test</b>"
});

Console.WriteLine(result);

will output

Hello <b>Test</b>

HtmlSafeTemplate

RazorEngine razorEngine = new RazorEngine();

var razorEngineCompiledTemplate = razorEngine.Compile<HtmlSafeTemplate>(
    "<div title=\"@Model\">This is now safe: @Model</div>\n" + 
    "<div>but not this: @Raw(Model)</div>");

string result = razorEngineCompiledTemplate.Run(instance =>
{
    instance.Model = "<script>alert(\"1\");</script>";
});

Console.WriteLine(result);

Output:

<div title="&lt;script>alert(&quot;1&quot;);&lt;/script>">This is now safe: &lt;script&gt;alert(&quot;1&quot;);&lt;/script&gt;</div>
<div>but not this: <script>alert("1");</script></div>

Code

public class RawContent
{
    public object Value { get;set;}

    public RawContent(object value)
    {
        Value = value;
    }
}

public class HtmlSafeTemplate : RazorEngineTemplateBase
{
    public object Raw(object value)
    {
        return new RawContent(value);
    }

    public override Task WriteAsync(object obj = null)
    {
        object value = obj is RawContent rawContent 
            ? rawContent.Value 
            : System.Web.HttpUtility.HtmlEncode(obj);

        return base.WriteAsync(value);
    }

    public override Task WriteAttributeValueAsync(string prefix, int prefixOffset, object value, int valueOffset, int valueLength, bool isLiteral)
    {
        value = value is RawContent rawContent
            ? rawContent.Value
            : System.Web.HttpUtility.HtmlAttributeEncode(value?.ToString());

        return base.WriteAttributeValueAsync(prefix, prefixOffset, value, valueOffset, valueLength, isLiteral);
    }
}