Подтвердить что ты не робот

Остановить построитель тегов, избегая одиночных кавычек ASP.NET MVC 2

У меня есть следующий метод 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, получает escape-код от tagbuilder, получившийся html:

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

В любом случае я могу остановить это поведение?

4b9b3361

Ответ 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 под элементом <system.web>:

<httpRuntime encoderType="HtmlAttributeNoEncoding"/>

Я нашел здесь здесь.

Ответ 2

В то время как решение, предоставленное Райаном, может работать, это немного похоже на использование молотка, чтобы намазать муху.

Проблема заключается в том, что TagBuilder кодирует строки во время вызовов MergeAttributes(). Для требуемого Javascript в ссылке на кнопку это влияет на одиночные кавычки и пробелы.

Последним шагом требуемого метода расширения является возврат MvcHtmlString (который не получает никакой дополнительной кодировки), поэтому вполне разумно сделать некоторые простые текстовые исправления для строки (чтобы отменить кодировку) до создания этого объект.

например.

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

Полный помощник ActionLinkButton показан ниже:

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