【问题标题】:Stop the tag builder escaping single quotes ASP.NET MVC 2停止标签生成器转义单引号 ASP.NET MVC 2
【发布时间】:2010-10-13 14:39:58
【问题描述】:

我有以下 HtmlHelper 方法,我想创建一个使用 JavaScript 进行重定向的按钮:

public static string JavaScriptButton(this HtmlHelper helper, string value,
                        string action, string controller, object routeValues = null, object htmlAttributes = null)
{
    var a = (new UrlHelper(helper.ViewContext.RequestContext))
                            .Action(action, controller, routeValues);

    var builder = new TagBuilder("input");
    builder.Attributes.Add("type", "submit");
    builder.Attributes.Add("value", value);
    builder.Attributes.Add("class", "button");
    builder.Attributes.Add("onclick", string.Format("javascript:location.href='{0}'", a));
    builder.MergeAttributes(new RouteValueDictionary(htmlAttributes));

    return MvcHtmlString.Create(builder.ToString(TagRenderMode.SelfClosing)).ToString();         
}

问题是创建 onclick 处理程序的行被标记生成器转义,生成的 html 是:

<input class="button" onclick="javascript:location.href=&#39;&#39;" type="submit" value="Return to All Audits" />

无论如何我可以阻止这种行为吗?

【问题讨论】:

  • 你不能简单地使用一个链接 (&lt;a href=...&gt;) 吗?我一直想知道为什么人们会在他们的 HTML 中使用 javascript 并使用表单提交按钮来执行重定向,当有为此目的设计的锚元素时。
  • 可能是因为他想要按钮的视觉风格?但是他应该使用type=button 而不是提交。
  • 你是对的,它应该使用按钮类型,我确实想要一个可视按钮。我确实创建了另一个按钮,该按钮使用标签生成器将表单包裹在提交中,但我遇到了样式问题和表单中嵌套表单的问题,这就是我走这条路的原因。

标签: asp.net asp.net-mvc-2


【解决方案1】:

这实际上是 .NET 4.0 的一个问题。要修复它,您需要覆盖属性编码过程。

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

然后将其放入您的 web.config 文件中的 &lt;system.web&gt; 元素下:

<httpRuntime encoderType="HtmlAttributeNoEncoding"/>

我找到了这个here

【讨论】:

    【解决方案2】:

    虽然 Ryan 提供的解决方案可能有效,但它有点像用锤子拍苍蝇。

    问题在于 TagBuilder 在调用 MergeAttributes() 期间对字符串进行编码。对于按钮链接中所需的 Javascript,这会影响单引号和空格。

    所需扩展方法的最后一步是返回MvcHtmlString(它不会接收进一步的编码),因此在创建字符串之前对字符串进行一些简单的文本更正(以撤消编码)是完全合理的目的。

    例如

    return new MvcHtmlString(tb.ToString(TagRenderMode.Normal).Replace("&#39;", "\'").Replace("&#32;"," "));
    

    一个完整的 ActionLinkBut​​ton 助手如下所示:

    public static class ActionLinkButtonHelper
    {
        public static MvcHtmlString ActionLinkButton(this HtmlHelper htmlHelper, string buttonText, string actionName, object routeValuesObject = null, object htmlAttributes = null)
        {
            return ActionLinkButton(htmlHelper, buttonText, actionName, "", routeValuesObject, htmlAttributes);
        }
        public static MvcHtmlString ActionLinkButton(this HtmlHelper htmlHelper, string buttonText, string actionName, string controllerName, object routeValuesObject = null, object htmlAttributes = null)
        {
            if (string.IsNullOrEmpty(controllerName))
            {
                controllerName = HttpContext.Current.Request.RequestContext.RouteData.Values["controller"].ToString();
            }
            RouteValueDictionary routeValues = new RouteValueDictionary(routeValuesObject);
            RouteValueDictionary htmlAttr = HtmlHelper.AnonymousObjectToHtmlAttributes(htmlAttributes);
            TagBuilder tb = new TagBuilder("button");
            tb.MergeAttributes(htmlAttr, false);
            string href = UrlHelper.GenerateUrl("default", actionName, controllerName, routeValues, RouteTable.Routes, htmlHelper.ViewContext.RequestContext, false);
    
            tb.MergeAttribute("type", "button");
            tb.SetInnerText(buttonText);
            tb.MergeAttribute("value", buttonText);
            tb.MergeAttribute("onclick", "location.href=\'"+ href +"\';return false;");
            return new MvcHtmlString(tb.ToString(TagRenderMode.Normal).Replace("&#39;", "\'").Replace("&#32;"," "));
        }
    }
    

    这可以完成您添加按钮链接所需的一切,具有与ActionLink 一起使用的最有用的重载,并且不会通过更改属性编码过程潜在地导致应用程序范围的意外更改。

    【讨论】:

      【解决方案3】:

      TagBuilder 不会在MergeAttribute 期间对字符串进行编码,因为直接操作 Attributes 属性然后使用ToString() 获取字符串表示也是对字符进行转义。编码很可能发生在ToString() 期间。

      下面的类解决了 JavaScript 的问题:

      public class JavaScriptTagBuilder : TagBuilder
      {
          public string OnClick { get; set; }
      
          public JavaScriptTagBuilder(string tagName)
              : base(tagName)
          {
          }
      
          public override string ToString()
          {
              string openingTag = "<" + TagName;
              return base.ToString().Replace(openingTag, string.Format("{0} onclick=\"{1}\"", openingTag, OnClick));
          }
      }
      

      【讨论】:

        【解决方案4】:

        我去迪斯科有点晚了,但您可以在返回 HTML 之前对其进行解码:

        return new MvcHtmlString(System.Web.HttpUtility.HtmlDecode(tb.ToString(TagRenderMode.Normal));
        

        【讨论】:

          猜你喜欢
          • 2016-01-08
          • 1970-01-01
          • 2012-04-07
          • 2017-01-08
          • 2011-09-20
          • 1970-01-01
          • 2015-07-07
          • 2013-01-15
          相关资源
          最近更新 更多