RazorEngine @Html帮助工作,但逃避Html

时间:2013-10-17 15:47:05

标签: c# razor razorengine

我正在使用RazorEngine来解析网页上html代码段的模板。 (这是一个遗留系统,切换到Mvc Razor视图是不可能的,因此我们将小部分切换到使用RazorEngine,这是有意义的)。有很多关于SO和互联网的问题试图让Mvc的Html和Url助手与Razor引擎一起工作。为了使@Html语法有效,我修改了一些代码here,以便将Html添加到基本模板中:

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;
    }
}

经过对Html源代码的大量调试后,我认为我已经设法实例化了Html帮助程序所需的所有内容,并且它成功运行@Html.Label ...问题是生成的html是:

&lt;label for=&quot;MyNumber&quot;&gt;MyNumber&lt;/label&gt;

显然应该是:

<label for="MyNumber">MyNumber</label>

我很难过如何解决这个问题。通过RazorEngine源查看时,我无法找到编码的结果。我最初的想法是TextWriter必须对值进行编码,但我无法确认这一点。如何让@Html.BlahFor()呈现未转义的html?

3 个答案:

答案 0 :(得分:2)

我找到了解决我遇到的问题的方法。 RazorEngine的基本模板将自动编码一个字符串(或对象),如果它不转换为IEncodedString。就我而言,我通过覆盖模板类中的WriteTo方法解决了这个问题:

public override void WriteTo(TextWriter writer, object value)
{
    if (writer == null)
        throw new ArgumentNullException("writer");

    if (value == null) return;

    var encodedString = value as IEncodedString;
    if (encodedString != null)
    {
        writer.Write(encodedString);
    }
    else
    {
        var htmlString = value as IHtmlString;
        if(htmlString != null) 
            writer.Write(htmlString.ToHtmlString());
        else
        {
            //This was the base template's implementation:
            encodedString = TemplateService.EncodedStringFactory.CreateEncodedString(value);
            writer.Write(encodedString);
        }
    }
}

我还没有看到这种变化是否会导致任何错误,但现在我发现这种方法将来相对容易改变。

编辑:选中查看Html帮助程序返回MvcHtmlString,它实现了IHtmlString,因此通过向此接口添加强制转换,我们可以避免对助手返回的html进行编码,同时仍然具有安全性适用于此方法的任何其他呼叫者。

答案 1 :(得分:2)

RazorEngine的作者Antaris提供了另一种处理这个问题的有趣方法,并解释了为什么默认情况下没有这样做(为了尽可能减少RazorEngine依赖性)。

以下是您answer on the corresponding github issue的相关部分:

  

我认为最简单   这里要做的事情,就是实现自定义   处理IEncodedStringFactory的{​​{1}}。类似的东西:

MvcHtmlString
     

这将使现有的public class MvcHtmlStringFactory : IEncodedStringFactory { public IEncodedString CreateEncodedString(string rawString) { return new HtmlEncodedString(rawString); } public IEncodedString CreateEncodedString(object obj) { if (obj == null) return new HtmlEncodedString(string.Empty); var htmlString = obj as HtmlEncodedString; if (htmlString != null) return htmlString; var mvcHtmlString = obj as MvcHtmlString; if (mvcHtmlString != null) return new MvcHtmlStringWrapper(mvcHtmlString); return new HtmlEncodedString(obj.Tostring()); } } public MvcHtmlStringWrapper : IEncodedString { private readonly MvcHtmlString _value; public MvcHtmlStringWrapper(MvcHtmlString value) { _value = value; } public string ToEncodedString() { return _value.ToString(); } public override string ToString() { return ToEncodedString(); } } 个实例绕过   RazorEngine的内置编码机制。这不属于   基础库因为我们不依赖于它   MvcHtmlStringSystem.Web

     

您需要通过配置进行连线:

System.Web.Mvc

就个人而言,在使用他的代码之前,我已将var config = new TemplateServiceConfiguration() { BaseTemplateType = typeof(MvcTemplateBase<>), EncodedStringFactory = new MvcHtmlStringFactory() }; 切换为MvcHtmlString。从MVC 5开始,IHtmlString也实现了它。 (请注意,在一些较旧的MVC版本中并非如此。)

答案 2 :(得分:0)

感谢您的灵感,我将数据存储在xml中,并创建了一个不同的解决方法,而不会覆盖WriteTo方法。我使用了一个继承自TemplateBase的类,并创建了两个新方法。

    public IEncodedString HtmlOf(NBrightInfo info, String xpath)
    {
        var strOut = info.GetXmlProperty(xpath);
        strOut = System.Web.HttpUtility.HtmlDecode(strOut);
        return new RawString(strOut);
    }

    public IEncodedString BreakOf(NBrightInfo info, String xpath)
    {
        var strOut = info.GetXmlProperty(xpath);
        strOut = System.Web.HttpUtility.HtmlEncode(strOut);
        strOut = strOut.Replace(Environment.NewLine, "<br/>");
        strOut = strOut.Replace("\t", "&nbsp;&nbsp;&nbsp;");
        strOut = strOut.Replace("'", "&apos;");
        return new RawString(strOut);
    }