Что такое MvcHtmlString и когда я должен его использовать?

221

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

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

Мне не ясно, каковы именно последствия этого. Кажется, что некоторые вспомогательные методы HTML возвращают MvcHtmlString, но несколько примеров пользовательских помощников, которые я видел в Интернете, просто возвращают обычную строку.

Вопросы:

Что такое MvcHtmlString?

Когда я должен выбрать MvcHtmlStringболее , stringи наоборот? Зачем?

devuxer
источник

Ответы:

246

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

Однако это создает проблему, заключающуюся в том, что если слепок кода уже кодирует свой результат, <%: %>синтаксис перекодирует его. Это решается введением интерфейса IHtmlString (впервые в .NET 4). Если foo () in <%: 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 - нет значимой разницы.
Леви
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, используя один <%: ... %>или <%= ... %>оба будут работать правильно.

mattmc3
источник
7

Вы можете использовать, MvcHtmlStringесли вы хотите передать необработанный HTML-код вспомогательному методу MVC и не хотите, чтобы вспомогательный метод кодировал HTML-код.

SLaks
источник
Хм ... Я думал, что весь смысл вспомогательного метода HTML заключается в кодировании HTML. Что бы я сделал иначе с помощью вспомогательного метода HTML?
devuxer
И, кроме того, когда я хочу , чтобы вернутьMvcHtmlString из вспомогательного метода HTML?
devuxer
Пройдите или вернитесь из. Вы захотите вернуть его, если ваш помощник по HTML генерирует предварительно экранированный HTML, и вы не хотите, чтобы кто-нибудь еще экранировал его.
SLaks
1
Хорошо, я думаю, что это немного сближает меня, но (рискуя оказаться умной задницей), как мне решить, хочу ли я, чтобы кто-нибудь еще сбежал от него? Является ли вообще хорошей / плохой практикой давать кому-то возможность связываться с избежавшим html? Я никогда не видел такую ​​конструкцию раньше. «Это как струна, но, пожалуйста, не трогай ее… не то, чтобы что-то мешало тебе дотронуться до нее, но мы бы предпочли, чтобы ты этого не делал». О чем это?
devuxer
1
Дело в том, что в отличие от обычной строки, эта строка уже закодирована. Поэтому нет необходимости прикасаться к нему.
SLaks