Qu'est-ce qu'un MvcHtmlString et quand dois-je l'utiliser?

221

La documentation de MvcHtmlStringn'est pas très éclairante:

Représente une chaîne codée en HTML qui ne doit plus être codée.

Je ne sais pas exactement quelles sont les implications de cela. Il semble que certaines méthodes d'assistance HTML renvoient un MvcHtmlString, mais plusieurs exemples que j'ai vus en ligne d'assistants personnalisés renvoient simplement une chaîne régulière.

Des questions:

Qu'est-ce qu'un MvcHtmlString?

Quand dois - je choisir MvcHtmlStringplus stringet vice - versa? Pourquoi?

devuxer
la source

Réponses:

246

ASP.NET 4 introduit une nouvelle syntaxe de nugget de code <%: %>. Essentiellement, se <%: foo %>traduit par <%= HttpUtility.HtmlEncode(foo) %>. L'équipe essaie de faire en sorte que les développeurs utilisent <%: %>plutôt <%= %>que possible pour empêcher XSS.

Cependant, cela pose le problème que si un nugget de code code déjà son résultat, la <%: %>syntaxe le ré-encodera . Cela est résolu par l'introduction de l'interface IHtmlString (nouveau dans .NET 4). Si foo () dans <%: foo() %>renvoie un IHtmlString, la <%: %>syntaxe ne le réencodera pas.

Les assistants de MVC 2 renvoient MvcHtmlString, qui sur ASP.NET 4 implémente l'interface IHtmlString. Par conséquent, lorsque les développeurs utilisent <%: Html.*() %>dans ASP.NET 4, le résultat ne sera pas codé en double.

Éditer:

Un avantage immédiat de cette nouvelle syntaxe est que vos vues sont un peu plus propres. Par exemple, vous pouvez écrire à la <%: ViewData["anything"] %>place de <%= Html.Encode(ViewData["anything"]) %>.

Levi
la source
J'ajouterais que MVC 2 est compilé avec .Net 3.5, pas 4. Cela signifie que MvcHtmlStringne met pas en œuvre IHtmlStringcar cela n'existe qu'en 4. La <%:syntaxe doit être de type canard - elle appellera toujours .ToHtmlString()avant .ToString()quelle que soit l'interface.
Keith
2
Je suis corrigé - en fait, la MvcHtmlString.Createméthode détecte si elle IHtmlStringest disponible et crée dynamiquement la classe retournée pour la prendre en charge si elle l'est: windowsitpro.com/article/net-framework/Encoding-and-Strings/…
Keith
Suivi: Y a - t-il une différence significative entre MvcHtmlString et HtmlString? Après avoir lu les documents liés ci-dessus, je ne savais toujours pas ce que MvcHtmlString me donne que HtmlString ne fait pas.
flipdoubt
@flipdoubt - Il n'y a pas de différence significative.
Levi
2
Il y a une très légère différence entre les deux. MvcHtmlString renverra String.Empty dans ToString () ou ToHtmlString () si vous lui passez une chaîne nulle. HtmlString continuera cependant de renvoyer null.
rossisdead
87

C'est une réponse tardive, mais si quelqu'un qui lit cette question utilise un rasoir, vous devez vous rappeler que le rasoir code tout par défaut, mais en utilisant MvcHtmlStringdans vos assistants html vous pouvez dire à rasoir qu'il n'a pas besoin de le coder .

Si vous voulez que le rasoir ne code pas une chaîne, utilisez

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

La décompilation de Raw (), nous montre qu'elle enveloppe la chaîne dans un HtmlString

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

" HtmlString n'existe que dans ASP.NET 4.

MvcHtmlString était une cale de compatibilité ajoutée à MVC 2 pour prendre en charge à la fois .NET 3.5 et .NET 4. Maintenant que MVC 3 est .NET 4 uniquement, il s'agit d'une sous-classe assez banale de HtmlString vraisemblablement pour MVC 2-> 3 pour la compatibilité avec la source. " source

Torbjörn Nomell
la source
11

Une bonne utilisation pratique de ceci est si vous voulez créer vos propres HtmlHelperextensions. Par exemple, je déteste essayer de me souvenir de la <link>syntaxe des balises, j'ai donc créé ma propre méthode d'extension pour créer une <link>balise:

<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

J'aurais pu revenir Stringde cette méthode, mais si j'avais eu ce qui suit se briserait:

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

Avec MvcHtmlString, l'utilisation de l'un <%: ... %>ou de l' autre <%= ... %>fonctionnera correctement.

mattmc3
la source
7

Vous utiliseriez un MvcHtmlStringsi vous voulez passer du HTML brut à une méthode d'assistance MVC et que vous ne voulez pas que la méthode d'assistance code le HTML.

SLaks
la source
Hmm ... Je pensais que l'intérêt d'une méthode d'assistance HTML était de coder du HTML. Que ferais-je autrement avec une méthode d'assistance HTML?
devuxer
Et, en plus de cela, quand voudrais-je retourner un à MvcHtmlStringpartir d'une méthode d'assistance HTML?
devuxer
Passer ou revenir de. Vous voudrez en renvoyer un si votre assistant HTML génère du code HTML prééchappé et que vous ne voulez pas que quelqu'un d'autre le rééchappe.
SLaks
1
D'accord, je pense que cela me rapproche un peu plus, mais (au risque de me faire passer pour un âne intelligent) comment puis-je décider si je veux que quelqu'un d'autre y échappe? Est-ce généralement une bonne / mauvaise pratique de donner à quelqu'un la possibilité de jouer avec le HTML échappé? Je n'ai jamais vu une telle construction auparavant. "C'est comme une ficelle, mais s'il te plait ne le touche pas ... pas que quelque chose t'empêche de le toucher, mais nous préférerions que tu ne le fasses pas." De quoi s'agit-il?
devuxer
1
Le fait est que contrairement à une chaîne régulière, cette chaîne a déjà été encodée. Par conséquent, il n'est pas nécessaire de le toucher.
SLaks