Stop the tag builder escaping single quotes ASP.NET MVC 2

末鹿安然 提交于 2019-11-27 03:19:29

问题


I have the following HtmlHelper method that I want to create a button that does a redirect with 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();         
}

The problem is that the line that creates the onclick handler is getting escaped by the tagbuilder, the resulting html is:

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

Is there anyway I can stop this behaviour?


回答1:


This is actually an issue with .NET 4.0. To fix it you need to override the attribute encoding process.

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

Then put this in your web.config file under the <system.web> element:

<httpRuntime encoderType="HtmlAttributeNoEncoding"/>

I found this here.




回答2:


While the solution provided by Ryan may work, it is a little like using a hammer to swat a fly.

The issue is that TagBuilder encodes strings during calls to MergeAttributes(). For the required Javascript in a button link this affects single quotes and spaces.

The last step of the required extension method is the return of an MvcHtmlString (which receives no further encoding), so it is perfectly reasonable to make some simple text corrections to the string (to undo the encoding) before creating that object.

e.g.

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

A complete ActionLinkButton helper is shown below:

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

This does everything you need to add button links, has the most useful overloads you use with ActionLink and does not potentially cause unexpected application-wide changes by changing the attribute encoding process.




回答3:


The TagBuilder does not encode the string during MergeAttribute as directly manipulating the Attributes property and then getting the string representation with ToString() is also escaping the characters. Most probably the encoding happens during ToString().

The class below solves the problem with 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:


I'm a little late to the disco but you could decode the HTML before returning it:

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


来源:https://stackoverflow.com/questions/3924861/stop-the-tag-builder-escaping-single-quotes-asp-net-mvc-2

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!