O que é um MvcHtmlString e quando devo usá-lo?

221

A documentação para MvcHtmlStringnão é terrivelmente esclarecedora:

Representa uma seqüência de caracteres codificada em HTML que não deve ser codificada novamente.

Não está claro para mim quais são exatamente as implicações disso. Parece que alguns métodos auxiliares de HTML retornam um MvcHtmlString, mas vários exemplos que eu vi on-line de auxiliares personalizados retornam uma sequência regular.

Questões:

O que é um MvcHtmlString?

Quando devo escolher MvcHtmlStringmais stringe vice-versa? Por quê?

devuxer
fonte

Respostas:

246

O ASP.NET 4 apresenta uma nova sintaxe de nugget de código <%: %>. Essencialmente, <%: foo %>traduz para <%= HttpUtility.HtmlEncode(foo) %>. A equipe está tentando fazer com que os desenvolvedores usem, em <%: %>vez de, <%= %>sempre que possível, impedir o XSS.

No entanto, isso introduz o problema de que, se um nugget de código já codificar seu resultado, a <%: %>sintaxe o codificará novamente . Isso é resolvido com a introdução da interface IHtmlString (nova no .NET 4). Se o foo () em <%: foo() %>retornos uma IHtmlString, a <%: %>sintaxe não vai voltar a codificar ele.

Os ajudantes do MVC 2 retornam MvcHtmlString, que no ASP.NET 4 implementa a interface IHtmlString. Portanto, quando os desenvolvedores usam <%: Html.*() %>no ASP.NET 4, o resultado não será codificado duas vezes.

Editar:

Um benefício imediato dessa nova sintaxe é que suas visualizações são um pouco mais limpas. Por exemplo, você pode escrever em <%: ViewData["anything"] %>vez de <%= Html.Encode(ViewData["anything"]) %>.

Levi
fonte
Eu acrescentaria que o MVC 2 é compilado no .Net 3.5, não no 4. Isso significa que MvcHtmlStringnão é implementado IHtmlStringporque existe apenas no 4. A <%:sintaxe deve ser do tipo pato - sempre será chamada .ToHtmlString()antes, .ToString()independentemente da interface.
Keith
2
Eu estou corrigido - na verdade, o MvcHtmlString.Createmétodo detecta se IHtmlStringestá disponível e cria dinamicamente a classe retornada para suportá-lo, se for: windowsitpro.com/article/net-framework/Encoding-and-Strings/…
Keith
Acompanhamento: Existe uma diferença significativa entre MvcHtmlString e HtmlString? Depois de ler os documentos vinculados acima, eu ainda não sabia o que o MvcHtmlString me fornece que o HtmlString não.
flipdoubt
@flipdoubt - Não há diferença significativa.
Levi
2
Há uma diferença muito pequena entre os dois. MvcHtmlString retornará String.Empty em ToString () ou ToHtmlString () se você passar uma string nula. HtmlString continuará retornando nulo, no entanto.
Rossisdead 6/03/2013
87

Esta é uma resposta tardia, mas se alguém que está lendo esta pergunta estiver usando o razor, o que você deve lembrar é que o razor codifica tudo por padrão, mas, usando MvcHtmlStringseus auxiliares html, você pode dizer ao razor que ele não precisa codificá-lo .

Se você deseja que o barbeador não codifique uma string, use

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

Descompilar Raw (), mostra que está quebrando a string em um HtmlString

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

"O HtmlString existe apenas no ASP.NET 4.

MvcHtmlString foi um calço de compatibilidade adicionado ao MVC 2 para oferecer suporte ao .NET 3.5 e .NET 4. Agora que o MVC 3 é apenas o .NET 4, é uma subclasse bastante trivial do HtmlString, presumivelmente para o MVC 2-> 3, para compatibilidade de origem. " fonte

Torbjörn Nomell
fonte
11

Um bom uso prático disso é se você deseja criar suas próprias HtmlHelperextensões. Por exemplo, eu odeio tentar lembrar a <link>sintaxe da tag, então criei meu próprio método de extensão para criar uma <link>tag:

<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

Eu poderia ter retornado Stringdeste método, mas se eu tivesse o seguinte quebraria:

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

Com MvcHtmlString, usar um <%: ... %>ou <%= ... %>ambos funcionará corretamente.

mattmc3
fonte
7

Você usaria um MvcHtmlStringse quiser passar o HTML bruto para um método auxiliar do MVC e não desejar que o método auxiliar codifique o HTML.

SLaks
fonte
Hmm ... eu pensei que o objetivo de um método auxiliar de HTML era codificar HTML. O que eu faria de outra forma com um método auxiliar de HTML?
Devuxer
Além disso, quando eu gostaria de retornar um MvcHtmlStringmétodo auxiliar de HTML?
Devuxer
Passe para ou retorne de. Você gostaria de retornar um se o seu auxiliar HTML gerar HTML pré-escapado e não desejar que mais ninguém o escape novamente.
Slaks
1
Ok, acho que isso me aproxima um pouco mais, mas (com o risco de parecer um espertinho) como decido se quero que mais alguém escape dela? É geralmente uma boa / má prática dar a alguém a capacidade de mexer com html de escape? Eu nunca vi uma construção como essa antes. "É como uma corda, mas por favor, não toque nela ... não que exista algo impedindo você de tocá-la, mas nós preferimos que você não toque." O que é isso?
Devuxer
1
O ponto é que, diferentemente de uma sequência regular, essa sequência já foi codificada. Portanto, não há necessidade de tocá-lo.
SLaks