Atribut HTML Bersyarat menggunakan Razor MVC3

100

Variabel strCSSClass sering kali memiliki nilai tetapi terkadang kosong.

Saya tidak ingin menyertakan class = "" yang kosong dalam HTML elemen masukan ini, yang berarti jika strCSSClass kosong, saya tidak ingin atribut class = sama sekali.

Berikut ini adalah salah satu cara untuk melakukan atribut HTML bersyarat:

<input type="text" id="@strElementID" @(CSSClass.IsEmpty() ? "" : "class=" + strCSSClass) />

Apakah ada cara yang lebih elegan untuk melakukan ini? Khususnya di mana saya bisa mengikuti sintaks yang sama seperti yang digunakan di bagian lain dari elemen: class = "@ strCSSClass"?

tony722
sumber

Jawaban:

160

Anda tidak mendengarnya dari saya, PM untuk Razor, tetapi di Razor 2 (Halaman Web 2 dan MVC 4) kami akan memiliki atribut bersyarat yang dibangun ke dalam Razor (sejak MVC 4 RC berhasil diuji), jadi Anda bisa mengatakan hal-hal seperti ini ...

<input type="text" id="@strElementID" class="@strCSSClass" />

Jika strCSSClass bernilai null maka atribut class tidak akan dirender sama sekali.

SSSHHH ... jangan bilang. :)

Erik Porter
sumber
1
Yup, Anda pasti tidak harus menerima jawaban saya. Karena itu, saat ini tidak ada cara yang lebih bersih untuk melakukannya (karena itu kami menciptakan cara yang lebih bersih untuk melakukannya). Mungkin cara terbersih untuk melakukannya adalah dengan menggunakan Html.TextBox, tetapi itu memiliki serangkaian hal yang kurang diinginkan yang berbeda. :( Senang Anda menyukai apa yang kami tambahkan. :)
Erik Porter
1
Tetapi bagaimana saya dapat menggabungkan atribut Razor dengan teks lain? Saya perlu membuat yang berikut ini: ... id = "[email protected]". Saya mengharapkan sesuatu seperti ... id = "track_2", tetapi menghasilkan keluaran berikut: ... id = "[email protected]" ...
Laserson
2
Anda dapat memaksa Razor untuk mengevaluasi kode dengan meletakkan tanda kurung di sekitarnya. id = "track _ @ (track.ID)"
Erik Porter
1
Menambahkan catatan yang menunjukkan ini bekerja dengan sukses dengan MVC 4. Jika Anda menggunakan MVC 3 lihat jawaban saya di bawah ini.
AaronLS
4
@ErikPorter TOLONG JANGAN MESS DENGAN HTML SAYA !! lihat juga stackoverflow.com/questions/9234467/… ini juga untuk perilaku buruk lainnya
eaglestorm
126

Perhatikan Anda dapat melakukan sesuatu seperti ini (setidaknya di MVC3):

<td align="left" @(isOddRow ? "class=TopBorder" : "style=border:0px") >

Apa yang saya yakini adalah menambahkan tanda kutip pisau cukur sebenarnya adalah browser. Seperti yang ditunjukkan Rism ketika menguji dengan MVC 4 (saya belum menguji dengan MVC 3 tetapi saya menganggap perilaku tidak berubah), ini sebenarnya menghasilkan class=TopBordertetapi browser dapat mengurai ini dengan baik. Pengurai HTML agak memaafkan jika ada kutipan atribut yang hilang, tapi ini dapat rusak jika Anda memiliki spasi atau karakter tertentu .

<td align="left" class="TopBorder" >

ATAU

<td align="left" style="border:0px" >

Apa yang salah dengan memberikan kutipan Anda sendiri

Jika Anda mencoba menggunakan beberapa konvensi C # yang biasa untuk kutipan bertingkat, Anda akan mendapatkan lebih banyak kutipan daripada yang Anda tawar karena Razor mencoba melarikan diri dengan aman. Sebagai contoh:

<button type="button" @(true ? "style=\"border:0px\"" : string.Empty)>

Ini harus bernilai<button type="button" style="border:0px"> tetapi Razor lolos dari semua output dari C # dan dengan demikian menghasilkan:

style=&quot;border:0px&quot;

Anda hanya akan melihat ini jika Anda melihat tanggapan melalui jaringan. Jika Anda menggunakan inspektur HTML, seringkali Anda benar-benar melihat DOM, bukan HTML mentah. Browser mengurai HTML ke dalam DOM, dan representasi DOM setelah penguraian sudah menerapkan beberapa hal bagus. Dalam hal ini, Browser melihat tidak ada tanda kutip di sekitar nilai atribut, tambahkan:

style="&quot;border:0px&quot;"

Namun dalam pemeriksa DOM kode karakter HTML ditampilkan dengan benar sehingga Anda benar-benar melihat:

style=""border:0px""

Di Chrome, jika Anda mengklik kanan dan memilih Edit HTML, itu akan beralih kembali sehingga Anda dapat melihat kode karakter HTML yang menjijikkan itu, memperjelas bahwa Anda memiliki tanda kutip luar yang sebenarnya, dan tanda kutip dalam yang dikodekan HTML.

Jadi masalah dengan mencoba melakukan kutipan sendiri adalah Razor lolos dari ini.

Jika Anda ingin kontrol penuh atas kutipan

Gunakan Html.Raw untuk mencegah pelolosan kutipan:

<td @Html.Raw( someBoolean ? "rel='tooltip' data-container='.drillDown a'" : "" )>

Ditampilkan sebagai:

<td rel='tooltip' title='Drilldown' data-container='.drillDown a'>

Di atas sangat aman karena saya tidak mengeluarkan HTML apa pun dari variabel. Satu-satunya variabel yang terlibat adalah kondisi terner. Namun, dan sekarang setiap pengguna lain yang melihat halaman ini memiliki kata sandinya langsung berubah menjadi kata sandi yang diketahui oleh pengguna jahat. berhati - hatilah karena teknik terakhir ini dapat membuat Anda terkena masalah keamanan tertentu jika membuat string dari data yang disediakan pengguna. Misalnya, jika Anda membuat atribut dari bidang data yang berasal dari data yang disediakan pengguna, gunakan Html. Raw berarti string dapat berisi akhir yang prematur dari atribut dan tag, kemudian mulai tag skrip yang melakukan sesuatu atas nama yang saat ini masuk pengguna (mungkin berbeda dari pengguna yang masuk). Mungkin Anda memiliki halaman dengan daftar semua gambar pengguna dan Anda menyetel keterangan alat menjadi nama pengguna setiap orang, dan satu pengguna menamai dirinya sendiri'/><script>$.post('changepassword.php?password=123')</script>

AaronLS
sumber
Itu adalah poin yang sangat bagus! Dan sebenarnya, itu membuatnya dapat dibaca dan digunakan dalam banyak situasi.
Dmytro Shevchenko
Itulah yang saya lakukan dalam contoh di pertanyaan saya. Terima kasih atas penjelasan dan contoh yang lebih rumit. :)
tony722
1
Waspadalah terhadap spasi. "style = display: none;" dirender sebagai tidak ada; = "": = "" style = "display"
wmcainsh
1
Jadi mengapa ini tidak berfungsi re: magic double quotes <span @ (true? "Class = logo-owner": string.Empty) /> Ini hanya menghasilkan <span class = logo-owner />
rism
1
@AaronLS Ya, begitulah tepatnya mereka. Tidak dapat memahami bagaimana browser (Chrome 40 / FF33.1 / IE 10) akan mempengaruhi apa pun karena ini adalah markup yang dihasilkan server dan jika demikian kenapa hanya dua atribut kelas itu tetapi tidak untuk atribut kelas dari tombol tanya atau bahkan tipe = atribut "tombol" dari ketiga tombol. Jelas merupakan hal server IMHO karena saya juga dapat RDP ke beberapa mesin virtual Azure yang tersebar di seluruh dunia untuk hasil yang sama yaitu IE / Firefox / Chrome.
rism
12

Saya kira cara yang sedikit lebih nyaman dan terstruktur adalah dengan menggunakan helper Html. Dalam pandangan Anda, ini bisa terlihat seperti:

@{
 var htmlAttr = new Dictionary<string, object>();
 htmlAttr.Add("id", strElementId);
 if (!CSSClass.IsEmpty())
 {
   htmlAttr.Add("class", strCSSClass);
 }
}

@* ... *@

@Html.TextBox("somename", "", htmlAttr)

Jika cara ini berguna untuk Anda, saya sarankan untuk mendefinisikan kamus htmlAttrdalam model Anda sehingga tampilan Anda tidak memerlukan @{ }blok logika (lebih jelas).

Yaschur
sumber
4
-1, jangan pernah merekomendasikan seseorang untuk meletakkan logika di view. Tampilan hanya bertanggung jawab untuk rendering. Tambahkan contoh HtmlHelper sebagai gantinya dan saya akan memberi Anda +1.
jgauffin
1
Untuk menguji hal-hal saya dapat menggunakan blok kode dalam tampilan - itu lebih cepat. Dan rekomendasi saya adalah memindahkan blok ini ke dalam model.
Yaschur
3
ya, tetapi jawaban harus menunjukkan praktik terbaik dan bukan versi cepat dan kotor yang membuat pemeliharaan kode menjadi mimpi buruk.
jgauffin
@jgauffin Saya pikir pembantu Html di sini tidak perlu. lihat jawabanku.
gdoron mendukung Monica
+1 @Yaschur Jawaban Anda menginspirasi. Pertahankan kerja bagus. yaitu. dengan fitur konversi eksplisit C #, kami dapat meningkatkan jawaban ini lebih banyak lagi. Tidak semua kode harus dibentuk dengan cara tertentu. Selalu ada cara yang lebih baik yang tidak kita sadari. Dan beberapa proyek mendukung organisasi kode. Organisasi kode adalah dengan praktik, bukan konsep!
Bambu