Apa itu MvcHtmlString dan kapan saya harus menggunakannya?

221

The dokumentasi untuk MvcHtmlStringtidak terlalu mencerahkan:

Merupakan string yang dikodekan HTML yang seharusnya tidak dikodekan lagi.

Tidak jelas bagi saya apa implikasi sebenarnya dari ini. Tampaknya beberapa metode HTML helper mengembalikan sebuah MvcHtmlString, tetapi beberapa contoh yang saya lihat online dari custom helpers hanya mengembalikan string biasa.

Pertanyaan:

Apa itu MvcHtmlString?

Ketika saya harus memilih MvcHtmlStringlebih stringdan sebaliknya? Mengapa?

penjahat
sumber

Jawaban:

246

ASP.NET 4 memperkenalkan sintaks nugget kode baru <%: %>. Pada dasarnya, <%: foo %>diterjemahkan menjadi <%= HttpUtility.HtmlEncode(foo) %>. Tim berusaha membuat pengembang menggunakan <%: %>alih-alih <%= %>sedapat mungkin untuk mencegah XSS.

Namun, ini menimbulkan masalah bahwa jika kode nugget sudah meng-encode hasilnya, <%: %>sintaks akan mengkodekan ulang itu. Ini diselesaikan dengan pengenalan antarmuka IHtmlString (baru dalam. NET 4). Jika foo () dalam <%: foo() %>mengembalikan IHtmlString, <%: %>sintaks tidak akan menyandikan ulang.

Pembantu MVC 2 mengembalikan MvcHtmlString, yang pada ASP.NET 4 mengimplementasikan antarmuka IHtmlString. Karenanya ketika pengembang menggunakan <%: Html.*() %>ASP.NET 4, hasilnya tidak akan dikodekan ganda.

Edit:

Manfaat langsung dari sintaks baru ini adalah bahwa pandangan Anda sedikit lebih bersih. Misalnya, Anda dapat menulis <%: ViewData["anything"] %>alih-alih <%= Html.Encode(ViewData["anything"]) %>.

Retribusi
sumber
Saya akan menambahkan bahwa MVC 2 dikompilasi melawan. Net 3.5, bukan 4. Ini berarti bahwa MvcHtmlStringtidak mengimplementasikan IHtmlStringkarena hanya ada di 4. <%:Sintaks harus tipe bebek - itu akan selalu memanggil .ToHtmlString()sebelumnya .ToString()terlepas dari antarmuka.
Keith
2
Saya berdiri dikoreksi - sebenarnya MvcHtmlString.Createmetode ini mendeteksi apakah IHtmlStringtersedia dan secara dinamis membuat kelas yang dikembalikan untuk mendukungnya jika: windowsitpro.com/article/net-framework/Encoding-and-Strings/…
Keith
Tindak Lanjut: Apakah ada perbedaan yang berarti antara MvcHtmlString dan HtmlString? Setelah membaca dokumen yang ditautkan di atas, saya masih tidak tahu apa yang MvcHtmlString berikan kepada saya bahwa HtmlString tidak.
flipdoubt
@ flipdoubt - Tidak ada perbedaan yang berarti.
Levi
2
Ada satu perbedaan yang sangat kecil antara keduanya. MvcHtmlString akan mengembalikan String.Empty di ToString () atau ToHtmlString () jika Anda memberikannya string nol. HtmlString akan terus mengembalikan nol.
rossisdead
87

Ini adalah jawaban yang terlambat tetapi jika ada orang yang membaca pertanyaan ini menggunakan pisau cukur, yang harus Anda ingat adalah bahwa pisau cukur mengkodekan semuanya secara default, tetapi dengan menggunakan MvcHtmlStringbantuan html Anda, Anda dapat memberi tahu pisau cukur bahwa itu tidak perlu dikodekan .

Jika Anda ingin pisau cukur tidak mengkodekan penggunaan string

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

Decompiling Raw (), menunjukkan kepada kita bahwa itu membungkus string dalam HtmlString

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

" HtmlString hanya ada di ASP.NET 4.

MvcHtmlString adalah shim kompatibilitas ditambahkan ke MVC 2 untuk mendukung keduanya. NET 3.5 dan .NET 4. Sekarang MVC 3 adalah .NET 4 saja, itu adalah subkelas HtmlString yang cukup sepele mungkin untuk MVC 2-> 3 untuk kompatibilitas sumber. " sumber

Torbjörn Nomell
sumber
11

Penggunaan praktis yang baik dari ini adalah jika Anda ingin membuat HtmlHelperekstensi sendiri . Misalnya, saya benci mencoba mengingat <link>sintaks tag, jadi saya telah membuat metode ekstensi saya sendiri untuk membuat <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

Saya bisa saja kembali Stringdari metode ini, tetapi jika saya memiliki yang berikut ini akan rusak:

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

Dengan MvcHtmlString, menggunakan salah satu <%: ... %>atau <%= ... %>keduanya akan bekerja dengan benar.

mattmc3
sumber
7

Anda akan menggunakan MvcHtmlStringjika Anda ingin meneruskan HTML mentah ke metode bantuan MVC dan Anda tidak ingin metode bantuan untuk menyandikan HTML.

Slaks
sumber
Hmm ... Saya pikir inti dari metode HTML helper adalah menyandikan HTML. Apa yang akan saya lakukan dengan metode pembantu HTML?
devuxer
Dan, selain itu, ketika akan saya ingin kembali suatu MvcHtmlStringdari metode pembantu HTML?
devuxer
Lewati atau kembali dari. Anda ingin mengembalikannya jika helper HTML Anda menghasilkan HTML yang telah lolos sebelumnya dan Anda tidak ingin orang lain menghindarinya kembali.
SLaks
1
Oke, saya pikir itu membuat saya sedikit lebih dekat, tetapi (dengan risiko dianggap sebagai orang yang pintar), bagaimana saya memutuskan apakah saya ingin orang lain melarikan diri lagi? Apakah itu praktik yang baik / buruk secara umum untuk memberi seseorang kemampuan untuk mengacaukan html yang lolos? Saya belum pernah melihat konstruk seperti ini sebelumnya. "Ini seperti tali, tapi tolong jangan menyentuhnya ... tidak ada yang mencegahmu menyentuhnya, tapi kami lebih suka kamu tidak menyentuhnya." Tentang apa itu?
devuxer
1
Intinya adalah bahwa tidak seperti string biasa, ini string yang telah dikodekan. Karena itu, tidak perlu menyentuhnya.
SLaks