Що таке MvcHtmlString і коли я повинен його використовувати?


221

Документація для MvcHtmlStringне надто просвіщаючи:

Представляє HTML-кодований рядок, який не слід кодувати знову.

Мені не ясно, які саме наслідки це. Здається, що деякі допоміжні методи HTML повертають MvcHtmlString, але декілька прикладів, які я бачив в Інтернеті, користувацьких помічників просто повертають звичайну рядок.

Запитання:

Що таке MvcHtmlString?

Коли я повинен вибрати MvcHtmlStringбільше stringі навпаки? Чому?

Відповіді:


246

ASP.NET 4 представляє новий синтаксис саморізу коду <%: %>. По суті, <%: foo %>перекладається на <%= HttpUtility.HtmlEncode(foo) %>. Команда намагається змусити розробників використовувати <%: %>замість того, <%= %>де це можливо, для запобігання XSS.

Однак це вводить проблему, що якщо кодовий саморіз вже кодує його результат, <%: %>синтаксис повторно кодує його. Це вирішується впровадженням інтерфейсу IHtmlString (новий у .NET 4). Якщо Foo () в <%: foo() %>повертає IHtmlString, то <%: %>синтаксис НЕ буде перекодувати його.

Помічники MVC 2 повертають MvcHtmlString, який на ASP.NET 4 реалізує інтерфейс IHtmlString. Тому, коли розробники використовують <%: Html.*() %>в ASP.NET 4, результат не буде подвійним кодуванням.

Редагувати:

Безпосередньою перевагою цього нового синтаксису є те, що ваші погляди трохи чистіші. Наприклад, ви можете писати <%: ViewData["anything"] %>замість <%= Html.Encode(ViewData["anything"]) %>.


Я додам, що MVC 2 компілюється проти. Net 3.5, а не 4. Це означає, що MvcHtmlStringвін не реалізується, IHtmlStringоскільки існує лише у 4. <%:Синтаксис повинен мати тип качки - він завжди буде викликати .ToHtmlString()раніше, .ToString()незалежно від інтерфейсу.
Кіт

2
Я виправлений - фактично MvcHtmlString.Createметод виявляє, чи IHtmlStringє доступний, і динамічно створює повернений клас для його підтримки, якщо це: windowsitpro.com/article/net-framework/Encoding-and-Strings/…
Кіт

Продовження : Чи є змістовна різниця між MvcHtmlString та HtmlString? Прочитавши документи, зв'язані вище, я все ще не знав, що дає мені MvcHtmlString, що HtmlString цього не робить.
flipdoubt

@flipdoubt - Суттєвої різниці немає.
Леві

2
Є одна дуже незначна різниця між ними. MvcHtmlString поверне String.Empty в ToString () або ToHtmlString (), якщо ви передасте це нульовий рядок. Хоча HtmlString продовжить повертати нульове значення.
rossisdead

87

Це пізня відповідь, але якщо хтось, хто читає це питання, використовує бритву, то вам слід пам’ятати, що бритва кодує все за замовчуванням, але, використовуючи MvcHtmlStringу своїх html-помічниках, ви можете сказати бритві, що не потрібно її кодувати .

Якщо ви хочете, щоб бритва не кодувала рядок

@Html.Raw("<span>hi</span>")

Декомпілюючи Raw (), показує нам, що він загортає рядок у HtmlString

public IHtmlString Raw(string value) {
    return new HtmlString(value); 
}

" HtmlString існує лише в ASP.NET 4.

MvcHtmlString - це суміс сумісності, доданий до MVC 2 для підтримки .NET 3.5 та .NET 4. Тепер, коли MVC 3 є тільки .NET 4, це досить тривіальний підклас HtmlString, імовірно, для MVC 2-> 3 для сумісності з джерелами. " джерело


11

Приємне практичне використання цього, якщо ви хочете зробити власні HtmlHelperрозширення. Наприклад, я ненавиджу намагатися запам'ятати <link>синтаксис тегів, тому я створив власний метод розширення, щоб зробити <link>тег:

<Extension()> _
Public Function CssBlock(ByVal html As HtmlHelper, ByVal src As String, ByVal Optional ByVal htmlAttributes As Object = Nothing) As MvcHtmlString
    Dim tag = New TagBuilder("link")
    tag.MergeAttribute("type", "text/css")
    tag.MergeAttribute("rel", "stylesheet")
    tag.MergeAttribute("href", src)
    tag.MergeAttributes(New RouteValueDictionary(htmlAttributes))
    Dim result = tag.ToString(TagRenderMode.Normal)
    Return MvcHtmlString.Create(result)
End Function

Я міг би повернутися Stringз цього методу, але якби у мене було таке, я б порушив:

<%: Html.CssBlock(Url.Content("~/sytles/mysite.css")) %>

З MvcHtmlString, використовуючи або обидва, <%: ... %>або <%= ... %>обидва будуть працювати правильно.


7

Ви б використовували, MvcHtmlStringякщо хочете передати необроблений HTML до допоміжного методу MVC, і ви не хочете, щоб метод помічника кодував HTML.


Хм ... Я подумав, що вся суть методу помічника HTML полягає в кодуванні HTML. Що я б робив інакше з методом помічника HTML?
devuxer

І, крім того, коли я хочу , щоб повернутиMvcHtmlString з допоміжного методу HTML?
devuxer

Перехід до або повернення з. Ви хочете повернути його, якщо ваш помічник HTML генерує попередньо уникнути HTML, і ви не хочете, щоб хто-небудь ще повторював його.
СЛак

1
Гаразд, я думаю, що це мене трохи зближує, але (ризикуючи натрапити на розумну дупу), як я вирішую, чи хочу я, щоб хто-небудь ще його втік? Це взагалі добра / погана практика давати комусь можливість возитися з втеченим html? Я ніколи раніше не бачив такої конструкції. "Це як струна, але, будь ласка, не чіпайте її ... не те, що щось заважає вам торкатися її, але ми вважаємо за краще, щоб ви цього не робили". Про що це?
devuxer

1
Справа в тому, що на відміну від звичайного рядка, ця рядок вже закодована. Тому торкатися не потрібно.
СЛАкс
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.