Как объединить несколько экземпляров MvcHtmlString

У меня есть некоторые сомнения относительно того, как объединить экземпляры MvcHtmlString из-за этой информации, найденной в MSDN :

Класс MvcHtmlString Представляет строку в кодировке HTML, которую не следует кодировать повторно.

Рискую ли я, что строки дважды кодируются в HTML при использовании такого кода:

var label = Html.LabelFor(model => model.Email);
var textbox = Html.TextBoxFor(model => model.Email);
var validation = Html.ValidationMessageFor(model => model.Email);

var result = MvcHtmlString.Create(
  label.ToString() + textbox.ToString() + validation.ToString());

(примечание: это должно войти в метод расширения HtmlHelper, чтобы уменьшить дублирование кода в представлениях).


person M4N    schedule 11.08.2010    source источник


Ответы (4)


Ваш код правильный.

Этот фрагмент из MSDN означает, что механизм представления кодирования (например, механизм представления Aspx в .NET 4 при использовании <%: %> или механизм представления Razor в MVC 3) не должен повторно кодировать строковое значение объекта.

Так, например:

string s = "<tag>";
var hs = MvcHtmlString.Create(s);

<%: s %>  -- outputs "&lt;tag&gt;"
<%: hs %> -- outputs "<tag>"
person marcind    schedule 11.08.2010

Жаль, что C# не позволяет нам переопределить здесь оператор +! Как насчет использования метода расширения?

public static MvcHtmlString Concat(this MvcHtmlString first, params MvcHtmlString[] strings)
{
    return MvcHtmlString.Create(first.ToString() + string.Concat(strings.Select(s => s.ToString())));
}

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

Пример использования:

label.Concat(textbox, validation)   

А теперь бессовестный плагин для моего блога: Используйте TagBuilder или HtmlTags для очистки вашего HTML

person Ryan    schedule 12.08.2010
comment
Это не компилируется для меня, я изменил его: public static MvcHtmlString Concat (сначала этот MvcHtmlString, params MvcHtmlString [] strings) { return MvcHtmlString.Create (first.ToString () + string.Concat (strings.Select (s) =› s.ToString()).ToArray())); } - person Charlie; 13.04.2012
comment
есть ли причина, по которой входные параметры не IHtmlString? - person Maslow; 09.12.2013
comment
IHtmlString не существовало в .NET 3.5. - person Ryan; 11.12.2013

Я пошел на этот подход:

    private static MvcHtmlString Concat(params MvcHtmlString[] items)
    {
        var sb = new StringBuilder();
        foreach (var item in items.Where(i => i != null))
            sb.Append(item.ToHtmlString());
        return MvcHtmlString.Create(sb.ToString());
    }

Это просто служебный метод, который я использую внутри классов с методами расширения для HtmlHelper.

person miguelv    schedule 05.12.2010

Я знаю, что это очень старо, но еще один способ (который я считаю более элегантным) заключается в использовании перегрузки метода String Concat, определение метаданных которого

public static String Concat(params object[] args);

что в основном ToStrings каждый из переданных объектов, а затем объединяет результаты и возвращает объединенную строку.

Таким образом, окончательный результат будет:

var result = MvcHtmlString.Create(
    string.Concat(
        label, textbox, validation
    )
);
person Nahuel Prieto    schedule 05.01.2018