Co to jest MvcHtmlString i kiedy powinienem go używać?

221

Dokumentacja dla MvcHtmlStringnie jest strasznie oświecania:

Reprezentuje ciąg zakodowany w formacie HTML, którego nie należy ponownie kodować.

Nie jest dla mnie jasne, jakie są tego konsekwencje. Wygląda na to, że niektóre metody pomocnicze HTML zwracają an MvcHtmlString, ale kilka przykładów, które widziałem online z niestandardowymi pomocnikami, zwraca zwykły ciąg.

Pytania:

Co to jest MvcHtmlString?

Kiedy należy wybrać MvcHtmlStringnad stringi vice versa? Czemu?

devuxer
źródło

Odpowiedzi:

246

ASP.NET 4 wprowadza nową składnię samorodków kodu <%: %>. Zasadniczo <%: foo %>przekłada się na <%= HttpUtility.HtmlEncode(foo) %>. Zespół stara się zachęcić programistów do używania <%: %>zamiast <%= %>tam, gdzie to możliwe, aby zapobiec XSS.

Jednak wprowadza to problem polegający na tym, że jeśli model użytkowy już koduje wynik, <%: %>składnia go ponownie zakoduje . Zostało to rozwiązane poprzez wprowadzenie interfejsu IHtmlString (nowego w .NET 4). Jeśli foo () w <%: foo() %>zwróci IHtmlString, <%: %>składnia go nie zakoduje ponownie.

Pomocnicy MVC 2 zwracają MvcHtmlString, który w ASP.NET 4 implementuje interfejs IHtmlString. Dlatego, gdy programiści używają <%: Html.*() %>w ASP.NET 4, wynik nie będzie podwójnie kodowany.

Edytować:

Bezpośrednią zaletą tej nowej składni jest to, że Twoje widoki są nieco bardziej przejrzyste. Na przykład możesz pisać <%: ViewData["anything"] %>zamiast <%= Html.Encode(ViewData["anything"]) %>.

Levi
źródło
Dodałbym, że MVC 2 jest kompilowany z .Net 3.5, a nie 4. Oznacza to, że MvcHtmlStringnie implementuje, IHtmlStringponieważ istnieje tylko w 4. <%:Składnia musi być typu kaczego - zawsze zadzwoni .ToHtmlString()wcześniej, .ToString()niezależnie od interfejsu.
Keith,
2
Stoję poprawiony - w rzeczywistości MvcHtmlString.Createmetoda wykrywa, czy IHtmlStringjest dostępna i dynamicznie tworzy zwróconą klasę, aby ją obsługiwać, jeśli jest: windowsitpro.com/article/net-framework/Encoding-and-Strings/…
Keith
Kontynuacja: Czy istnieje znacząca różnica między MvcHtmlString i HtmlString? Po przeczytaniu wyżej wymienionych dokumentów nadal nie wiedziałem, co daje MvcHtmlString, a nie HtmlString.
flipdoubt
@flipdoubt - Nie ma znaczącej różnicy.
Levi,
2
Jest jedna bardzo niewielka różnica między nimi. MvcHtmlString zwróci String.Empty w ToString () lub ToHtmlString (), jeśli przekażesz ciąg pusty. HtmlString będzie jednak nadal zwracał null.
rossisdead
87

To jest późna odpowiedź, ale jeśli ktoś czytający to pytanie używa brzytwy, powinieneś pamiętać, że brzytwa koduje wszystko domyślnie, ale używając MvcHtmlStringpomocników HTML możesz powiedzieć brzytwie, że nie musi go kodować .

Jeśli chcesz, aby brzytwy nie kodowały ciągu, użyj

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

Dekompilacja Raw () pokazuje, że owija ciąg znaków w HtmlString

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

HtmlString istnieje tylko w ASP.NET 4.

MvcHtmlString był podkładką kompatybilności dodaną do MVC 2, aby obsługiwać zarówno .NET 3.5, jak i .NET 4. Teraz, gdy MVC 3 to tylko .NET 4, jest to dość trywialna podklasa HtmlString przypuszczalnie dla MVC 2-> 3 dla kompatybilności źródła. źródło

Torbjörn Nomell
źródło
11

Dobrym praktycznym zastosowaniem tego jest, jeśli chcesz tworzyć własne HtmlHelperrozszerzenia. Na przykład nienawidzę próbować zapamiętać <link>składni znacznika, dlatego stworzyłem własną metodę rozszerzenia, aby utworzyć <link>znacznik:

<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

Mógłbym wrócić Stringz tej metody, ale gdybym miał, to by się zepsuło:

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

Za MvcHtmlStringpomocą jednego <%: ... %>lub <%= ... %>obu będzie działać poprawnie.

mattmc3
źródło
7

Przydałbyś się, MvcHtmlStringjeśli chcesz przekazać surowy kod HTML do metody pomocniczej MVC i nie chcesz, aby metoda pomocnicza kodowała HTML.

SLaks
źródło
Hmm ... Myślałem, że sedno metody pomocniczej HTML polega na kodowaniu HTML. Co zrobiłbym inaczej z metodą pomocniczą HTML?
devuxer
A poza tym, kiedy chciałbym wrócićMvcHtmlString z metody pomocnika HTML?
devuxer
Przekaż do lub wróć z. Chcesz go zwrócić, jeśli Twój pomocnik HTML generuje kod HTML poprzedzony kodem ucieczki i nie chcesz, aby ktokolwiek inny ponownie go unikał.
SLaks
1
Okej, myślę, że to mnie trochę przybliża, ale (ryzykując, że trafię na sprytnego tyłka) jak mam zdecydować, czy chcę, żeby ktokolwiek inny uciekł? Czy generalnie dobrą / złą praktyką jest umożliwienie komuś bałaganu za pomocą uciekającego HTML? Nigdy wcześniej nie widziałem takiej konstrukcji. „To jest jak sznurek, ale proszę go nie dotykać ... nie dlatego, że coś Cię powstrzymuje, ale wolelibyśmy, żebyś tego nie robił”. O czym to jest?
devuxer
1
Chodzi o to, że w przeciwieństwie do zwykłego ciągu, ten ciąg został już zakodowany. Dlatego nie trzeba go dotykać.
SLaks