I am using RazorEngine to parse templates from html snippets on a web page. (This is a legacy system that switching to Mvc Razor views isn't possible, so we are switching small sections over to using RazorEngine where it makes sense). There are many of questions on SO and the internet trying to get Mvc's Html and Url helpers to work with Razor engine. To get @Html
syntax to work, I've modified some code found here to add Html to the base template:
public HtmlHelper<t> Html
{
get
{
if (helper == null)
{
var writer = this.CurrentWriter; //TemplateBase.CurrentWriter
var vcontext = new ViewContext() { Writer = writer, ViewData = this.ViewData};
helper = new HtmlHelper<t>(vcontext, this);
}
return helper;
}
}
public ViewDataDictionary ViewData
{
get
{
if (viewdata == null)
{
viewdata = new ViewDataDictionary();
viewdata.TemplateInfo = new TemplateInfo() { HtmlFieldPrefix = string.Empty };
if (this.Model != null)
{
viewdata.Model = Model;
}
}
return viewdata;
}
set
{
viewdata = value;
}
}
After a lot of debugging into the Html source code I think I've managed to instantiate everything that the Html helper needs, and it runs successfully for @Html.Label
... The problem is that the resulting html is:
<label for="MyNumber">MyNumber</label>
When it obviously should be:
<label for="MyNumber">MyNumber</label>
I am stumped as to how to fix this. I was not able to find how the encoding happens when looking through the RazorEngine source. My initial thought was that the TextWriter must be encoding the value but I have not been able to confirm this. How can I get @Html.BlahFor()
to render un-escaped html?
Antaris, author of RazorEngine, has supplied another interesting way for handling this issue, and explained by the way why it is not done by default (for reducing as much as possible RazorEngine dependencies).
Here is for your case the relevant part of his answer on the corresponding github issue:
Personally, I have switched
MvcHtmlString
forIHtmlString
before using his code. As of MVC 5,MvcHtmlString
does implement it too. (Beware, it was not the case in some older MVC version.)Thanks for the inspiration, I had my data stored in a xml and created a different workaround without overwriting the WriteTo method. I used a class that inherited from the TemplateBase and created 2 new methods.
I have found a workaround for the problem I was facing. RazorEngine's base Template will automatically encode a string (or object) if it doesn't cast to an
IEncodedString
. In my case, I solved this issue by overriding theWriteTo
method in my template class:I have yet to see if this change will cause any errors, but now that I found the method it should be relatively easy to change in the future.
EDIT: Checked to see Html helpers return an MvcHtmlString, which implements IHtmlString, so by adding a cast to this interface, we can avoid encoding the html returned by the helpers, while still having a safety in place for any other callers of this method.