【问题标题】:.Net 4.0 is encoding single quote when using Attributes.Add.Net 4.0 在使用 Attributes.Add 时对单引号进行编码
【发布时间】:2025-12-29 19:00:18
【问题描述】:

.Net 4.0 在我使用 Attributes.Add 将客户端事件添加到我的 asp.net 对象时对单引号进行编码。在以前的版本中,这并没有发生。

例如:

<asp:Image runat="server" ID="imgTest" ImageUrl="~/DateControl/cal.gif" />

 imgTest.Attributes.Add("onmouseover", "alert('Hello')");

当我查看客户端输出时,我得到了

 <img id="ctl00_MainContent_calFromTimeStamp1_imgTest" onmouseover="alert(&#39;Hello&#39;)" src="../DateControl/cal.gif" style="border-width:0px;" />

我通过创建自定义编码器找到了解决方法:creating custom encoding routines,但我不想仅仅因为这个问题而停止整个网站的编码。任何人有解决方法或想法如何解决这个问题?

【问题讨论】:

    标签: c# asp.net encoding .net-4.0 asp.net-4.0


    【解决方案1】:

    根据 Microsoft 的说法,您不应该使用 WebControl.Attributes.Add() 将 JavaScript 添加到 HTML 属性,因为它会对属性值进行编码:

    您不能使用 属性集合。要添加客户端脚本,请使用 ClientScript Page 控件上的属性。

    Source

    建议使用Page.ClientScript.RegisterExpandoAttribute(string controlId, string attributeName, string attributeValue, bool encode) method。在您的情况下,它看起来像这样:

    Page.ClientScript.RegisterExpandoAttribute(
      imgTest.ClientID, 
      "onmouseover", 
      "alert('Hello')", 
      false /* Do not encode */
    );
    

    这将在您的页面中生成一段 JavaScript,用于设置属性客户端。

    【讨论】:

    • 有设置属性客户端的java脚本,但是事件没有触发,我在Chrome和IE上试过
    • 这里相同 - 我可以看到添加属性的脚本 - 但它不会触发。
    【解决方案2】:

    在 .NET 中设置事件属性的最佳方法是调用单个函数:

    imgTest.Attributes("message") = "Hello";
    imgTest.Attributes("onmouseover") = "showMessage(this);"
    

    并在您的页面上,或注册脚本:

    function showMessage(ctrl) 
    {
      alert(ctrl.getAttribute('message'));
    }
    

    【讨论】:

    • 您给出的示例并没有真正显示解决方案,因为您使用的文本不包含引号。考虑一下:link.Attributes["my_command"] = "myfunc('hello world')"; link.Attributes["onclick"] = "eval(this.my_command)";。新属性my_command 确实被编码,但由eval() 方法解码。
    【解决方案3】:

    imgTest.Attributes.Add("onmouseover", "alert(\'Hello\')");

    【讨论】:

      【解决方案4】:

      感谢 Franzo 的link,复制粘贴以下答案:

      您可以通过创建这样的类来关闭属性编码:

      public class HtmlAttributeEncodingNot : System.Web.Util.HttpEncoder
      {
          protected override void HtmlAttributeEncode(string value, System.IO.TextWriter output)
          {
              output.Write(value);
          }
      }
      

      并将其添加到 web.config 下:

      <httpRuntime encoderType="HtmlAttributeEncodingNot"/>
      

      这给了我所需的控制权。

      但是,现在我们必须担心新控件可能依赖于新控件 标准 4.0 行为并且不编码单引号,所以它仍然是 不完美,不,比不完美更糟糕:安全性更糟糕,因为 我们不知道发生了什么,所以这不是一个很好的解决方法 真的。

      我认为只有 Microsoft 才能正确解决此问题。其他人建议 这里需要一个 HtmlAttributeString 类:link 如果有 是这样一个类和 Attributes.Add 可以采用这样的对象 对于它的 value 参数,我们将拥有我们需要的控制权 再次。

      【讨论】:

        【解决方案5】:

        不建议关闭属性编码。如果您尝试默认阻止编码,那么您的代码将来会出现许多奇怪的行为,您必须为不良做法付出代价。

        .NET 总是对任何属性进行编码以阻止注入恶意脚本。所以你应该按照这个默认做法来保护你的程序。

        【讨论】:

          【解决方案6】:

          您可以在任何引号字符之前使用转义字符:

          来源:

          this.Attributes.Add("onmouseover", string.Format("$(this).attr(\'src\',\'{0}\')",this.Page.ClientScript.GetWebResourceUrl(typeof(SwapImage), urlenabledkey)));
          

          渲染:

          onmouseover="$(this).attr('src','/WebResource.axd?d=kHY3FE9nMsUOvDU-pPthg4KQvVrnXlcASyA7dFf6L
          

          【讨论】: