Was ist ein MvcHtmlString und wann sollte ich ihn verwenden?

221

Die Dokumentation für MvcHtmlStringist nicht besonders aufschlussreich:

Stellt eine HTML-codierte Zeichenfolge dar, die nicht erneut codiert werden sollte.

Mir ist nicht klar, was genau die Auswirkungen davon sind. Es scheint, dass einige HTML-Hilfsmethoden eine zurückgebenMvcHtmlString , aber einige Beispiele, die ich online von benutzerdefinierten Helfern gesehen habe, geben nur eine reguläre Zeichenfolge zurück.

Fragen:

Was ist ein MvcHtmlString ?

Wann soll ich wählen MvcHtmlStringüber , stringund umgekehrt? Warum?

Devuxer
quelle

Antworten:

246

ASP.NET 4 führt eine neue Code-Nugget-Syntax ein <%: %>. Im Wesentlichen <%: foo %>übersetzt zu <%= HttpUtility.HtmlEncode(foo) %>. Das Team versucht, Entwickler dazu zu bringen, XSS zu verwenden, <%: %>anstatt es <%= %>wo immer möglich zu verhindern.

Dies führt jedoch zu dem Problem, dass wenn ein Code-Nugget sein Ergebnis bereits codiert, die <%: %>Syntax es neu codiert . Dies wird durch die Einführung der IHtmlString-Schnittstelle (neu in .NET 4) gelöst. Wenn foo () in <%: foo() %>einen IHtmlString zurückgibt, wird er von der <%: %>Syntax nicht neu codiert.

Die Helfer von MVC 2 geben MvcHtmlString zurück, das unter ASP.NET 4 die Schnittstelle IHtmlString implementiert. Wenn Entwickler <%: Html.*() %>in ASP.NET 4 verwenden, wird das Ergebnis daher nicht doppelt codiert.

Bearbeiten:

Ein unmittelbarer Vorteil dieser neuen Syntax besteht darin, dass Ihre Ansichten etwas sauberer sind. Zum Beispiel können Sie <%: ViewData["anything"] %>statt schreiben <%= Html.Encode(ViewData["anything"]) %>.

Levi
quelle
Ich würde hinzufügen, dass MVC 2 gegen .Net 3.5 kompiliert wird, nicht gegen 4. Dies bedeutet, dass MvcHtmlStringdies nicht implementiert wird, IHtmlStringda dies nur in 4 vorhanden ist. Die <%:Syntax muss vom Typ duck-type sein - sie wird unabhängig von der Schnittstelle immer .ToHtmlString()vorher aufgerufen .ToString().
Keith
2
Ich stehe korrigiert da - tatsächlich MvcHtmlString.Createerkennt die Methode, ob sie IHtmlStringverfügbar ist, und erstellt dynamisch die zurückgegebene Klasse, um sie zu unterstützen, wenn dies der Fall
Keith
Follow-up: Gibt es einen bedeutenden Unterschied zwischen MvcHtmlString und HtmlString? Nachdem ich die oben verlinkten Dokumente gelesen hatte, wusste ich immer noch nicht, was MvcHtmlString mir gibt, was HtmlString nicht tut.
Flipdoubt
@flipdoubt - Es gibt keinen bedeutenden Unterschied.
Levi
2
Es gibt einen sehr kleinen Unterschied zwischen den beiden. MvcHtmlString gibt String.Empty in ToString () oder ToHtmlString () zurück, wenn Sie ihm eine Nullzeichenfolge übergeben. HtmlString gibt jedoch weiterhin null zurück.
Rossisdead
87

Dies ist eine späte Antwort, aber wenn jemand, der diese Frage liest, Rasiermesser verwendet, sollten Sie sich daran erinnern, dass Rasiermesser standardmäßig alles codiert. Wenn Sie jedoch MvcHtmlStringin Ihren HTML-Helfern verwenden, können Sie Rasiermesser mitteilen, dass es nicht codiert werden muss .

Wenn Sie möchten, dass der Rasierer keine Zeichenfolge codiert, verwenden Sie

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

Das Dekompilieren von Raw () zeigt uns, dass die Zeichenfolge in einen HtmlString eingeschlossen wird

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

" HtmlString ist nur in ASP.NET 4 vorhanden.

MvcHtmlString war ein Kompatibilitäts-Shim, der MVC 2 hinzugefügt wurde, um sowohl .NET 3.5 als auch .NET 4 zu unterstützen. Da MVC 3 nur .NET 4 ist, ist es aus Gründen der Quellkompatibilität eine ziemlich triviale Unterklasse von HtmlString, vermutlich für MVC 2-> 3. " Quelle

Torbjörn Nomell
quelle
11

Eine gute praktische Anwendung ist, wenn Sie Ihre eigenen HtmlHelperErweiterungen erstellen möchten . Ich hasse es beispielsweise, mich an die <link>Tag-Syntax zu erinnern , deshalb habe ich meine eigene Erweiterungsmethode erstellt, um ein <link>Tag zu erstellen:

<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

Ich hätte Stringvon dieser Methode zurückkehren können, aber wenn ich Folgendes hätte, würde es kaputt gehen:

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

Mit MvcHtmlStringeinem <%: ... %>oder <%= ... %>beiden funktionieren beide korrekt.

mattmc3
quelle
7

Sie würden ein verwenden, MvcHtmlStringwenn Sie Roh-HTML an eine MVC-Hilfsmethode übergeben möchten und Sie nicht möchten, dass die Hilfsmethode den HTML-Code codiert.

SLaks
quelle
Hmm ... Ich dachte, der Sinn einer HTML-Hilfsmethode besteht darin, HTML zu codieren. Was würde ich sonst mit einer HTML-Hilfsmethode tun?
Devuxer
Und außerdem , dass, wenn würde ich möchte zurückkehren ein MvcHtmlStringaus einem HTML - Helfer - Methode?
Devuxer
Weitergeben oder zurückkehren von. Sie möchten einen zurückgeben, wenn Ihr HTML-Helfer vorab Escape-HTML generiert und Sie nicht möchten, dass andere ihn erneut maskieren.
SLaks
1
Okay, ich denke, das bringt mich ein bisschen näher, aber (auf die Gefahr hin, wie ein kluger Arsch rüberzukommen) wie entscheide ich, ob ich möchte, dass jemand anderes ihm entkommt? Ist es im Allgemeinen eine gute / schlechte Praxis, jemandem die Möglichkeit zu geben, sich mit entkommenem HTML zu beschäftigen? Ich habe noch nie ein solches Konstrukt gesehen. "Es ist wie eine Schnur, aber bitte fass sie nicht an ... nicht, dass dich irgendetwas daran hindert, sie zu berühren, aber wir würden es vorziehen, wenn du es nicht tust." Worum geht es?
Devuxer
1
Der Punkt ist, dass diese Zeichenfolge im Gegensatz zu einer regulären Zeichenfolge bereits codiert wurde. Daher besteht keine Notwendigkeit, es zu berühren.
SLaks