Che cos'è un MvcHtmlString e quando dovrei usarlo?


221

La documentazione per MvcHtmlStringnon è terribilmente illuminante:

Rappresenta una stringa con codifica HTML che non deve essere codificata nuovamente.

Non mi è chiaro quali siano esattamente le implicazioni di ciò. Sembra che alcuni metodi di supporto HTML restituiscano un MvcHtmlString, ma diversi esempi che ho visto online di helper personalizzati restituiscono solo una stringa normale.

Domande:

Che cos'è un MvcHtmlString?

Quando dovrei scegliere MvcHtmlStringoltre stringe viceversa? Perché?

Risposte:


246

ASP.NET 4 introduce una nuova sintassi del nugget di codice <%: %>. In sostanza, si <%: foo %>traduce in <%= HttpUtility.HtmlEncode(foo) %>. Il team sta cercando di indurre gli sviluppatori a utilizzare <%: %>invece che <%= %>dove possibile per impedire XSS.

Tuttavia, ciò introduce il problema che se un nugget di codice già codifica il suo risultato, la <%: %>sintassi lo ricodificherà . Ciò è stato risolto dall'introduzione dell'interfaccia IHtmlString (nuova in .NET 4). Se foo () in <%: foo() %>restituisce un IHtmlString, la <%: %>sintassi non lo ricodificherà.

Gli helper di MVC 2 restituiscono MvcHtmlString, che su ASP.NET 4 implementa l'interfaccia IHtmlString. Pertanto, quando gli sviluppatori utilizzano <%: Html.*() %>ASP.NET 4, il risultato non verrà codificato in doppio.

Modificare:

Un vantaggio immediato di questa nuova sintassi è che le tue viste sono un po 'più pulite. Ad esempio, puoi scrivere <%: ViewData["anything"] %>invece di <%= Html.Encode(ViewData["anything"]) %>.


Aggiungo che MVC 2 è compilato su .Net 3.5, non 4. Ciò significa che MvcHtmlStringnon si implementa IHtmlStringperché esiste solo in 4. La <%:sintassi deve essere di tipo anatra - chiamerà sempre .ToHtmlString()prima .ToString()indipendentemente dall'interfaccia.
Keith

2
Sono corretto - in realtà il MvcHtmlString.Createmetodo rileva se IHtmlStringè disponibile e crea dinamicamente la classe restituita per supportarla se è: windowsitpro.com/article/net-framework/Encoding-and-Strings/…
Keith

Follow-up: esiste una differenza significativa tra MvcHtmlString e HtmlString? Dopo aver letto i documenti collegati sopra, non sapevo ancora cosa MvcHtmlString mi dà che HtmlString non lo sa.
capovolgere il

@flipdoubt - Non c'è alcuna differenza significativa.
Levi,

2
C'è una leggera differenza tra i due. MvcHtmlString restituirà String.Empty in ToString () o ToHtmlString () se gli passi una stringa nulla. Tuttavia, HtmlString continuerà a restituire null.
Rossisdead,

87

Questa è una risposta tardiva ma se qualcuno che sta leggendo questa domanda sta usando il rasoio, quello che dovresti ricordare è che il rasoio codifica tutto per impostazione predefinita, ma usando i MvcHtmlStringtuoi aiutanti html puoi dire al rasoio che non è necessario codificarlo .

Se si desidera che il rasoio non codifichi una stringa, utilizzare

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

Decompilare Raw (), ci mostra che sta avvolgendo la stringa in un HtmlString

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

" HtmlString esiste solo in ASP.NET 4.

MvcHtmlString era uno shim di compatibilità aggiunto a MVC 2 per supportare sia .NET 3.5 che .NET 4. Ora che MVC 3 è solo .NET 4, è una sottoclasse abbastanza banale di HtmlString presumibilmente per MVC 2-> 3 per la compatibilità dei sorgenti. " fonte


11

Un buon uso pratico di questo è se vuoi creare le tue HtmlHelperestensioni. Ad esempio, odio provare a ricordare la <link>sintassi del tag, quindi ho creato il mio metodo di estensione per creare un <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

Avrei potuto tornare Stringda questo metodo, ma se avessi avuto il seguente si sarebbe rotto:

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

Con MvcHtmlString, usando uno <%: ... %>o <%= ... %>entrambi funzionerà correttamente.


7

Si userebbe un MvcHtmlStringse si desidera passare HTML grezzo a un metodo di supporto MVC e non si desidera che il metodo di supporto codifichi l'HTML.


Hmm ... Pensavo che il punto centrale di un metodo di supporto HTML fosse codificare HTML. Cosa farei altrimenti con un metodo di supporto HTML?
Devuxer,

E, a parte questo, quando vorrei restituire un MvcHtmlStringmetodo helper HTML?
Devuxer,

Passa o ritorna da. Si vorrebbe restituire uno se il proprio helper HTML genera HTML pre-escape e non si desidera che nessun altro lo riesca.
SLaks,

1
Okay, penso che mi avvicini un po 'di più, ma (a rischio di imbattermi in un asino intelligente) come faccio a decidere se voglio che qualcun altro lo riesca a fuggire? È generalmente buona / cattiva pratica dare a qualcuno la possibilità di pasticciare con HTML sfuggito? Non ho mai visto un costrutto come questo prima d'ora. "È come una corda, ma per favore non toccarla ... non che ci sia qualcosa che ti impedisce di toccarla, ma preferiremmo che non lo facessi." Di cosa si tratta?
Devuxer,

1
Il punto è che a differenza di una stringa normale, questa stringa è già stata codificata. Pertanto, non è necessario toccarlo.
SLaks,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.