RazorEngine @Html助手工作,但转义 Html

本文关键字:转义 Html 工作 @Html RazorEngine | 更新日期: 2023-09-27 18:35:52

我正在使用RazorEngine从网页上的html片段中解析模板。(这是一个旧系统,无法切换到 Mvc Razor 视图,因此我们将小部分切换到有意义的使用 RazorEngine)。关于SO和互联网上有很多问题试图让Mvc的HTML和URL助手与Razor引擎一起工作。为了使@Html语法正常工作,我修改了一些在此处找到的代码,以将 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源代码时,我无法找到编码是如何发生的。我最初的想法是文本编写器必须对值进行编码,但我无法确认这一点。如何让@Html.BlahFor()呈现未转义的 html?

RazorEngine @Html助手工作,但转义 Html

我已经找到了解决我面临的问题的解决方法。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 帮助程序返回实现 IHtmlString 的 MvcHtmlString,因此通过向此接口添加强制转换,我们可以避免对帮助程序返回的 html 进行编码,同时仍然为此方法的任何其他调用者提供安全性。

RazorEngine的

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

以下是他关于相应 github 问题的回答的相关部分:

我认为最简单的 这里要做的事情是实现自定义 IEncodedStringFactory处理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();
  }
}

这将使现有的MvcHtmlString实例能够绕过 RazorEngine的内置编码机制。这不会是 基础库,因为我们不依赖任何依赖 System.Web,或System.Web.Mvc

您需要通过配置将其连接起来:

var config = new TemplateServiceConfiguration()
{
  BaseTemplateType = typeof(MvcTemplateBase<>),
  EncodedStringFactory = new MvcHtmlStringFactory()
};

就个人而言,在使用他的代码之前,我已经将MvcHtmlString切换为IHtmlString。从MVC 5开始,MvcHtmlString也实现了它。(请注意,在某些较旧的 MVC 版本中并非如此。

感谢您的启发,我将数据存储在 xml 中,并在不覆盖 WriteTo 方法的情况下创建了一个不同的解决方法。 我使用了一个继承自 TemplateBase 的类并创建了 2 个新方法。

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