Razor MVC3 kullanan Koşullu HTML Nitelikleri


100

StrCSSClass değişkeni genellikle bir değere sahiptir, ancak bazen boştur.

Bu girdi öğesinin HTML'sine boş bir class = "" eklemek istemiyorum, yani strCSSClass boşsa, class = özniteliğini hiç istemiyorum.

Aşağıdakiler, koşullu bir HTML niteliği oluşturmanın bir yoludur:

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

Bunu yapmanın daha zarif bir yolu var mı? Özellikle öğenin diğer bölümlerinde kullanılan aynı sözdizimini izleyebileceğim bir yer: class = "@ strCSSClass"?

Yanıtlar:


160

Bunu benden duymadınız, Razor için Başbakan, ancak Razor 2'de (Web Sayfaları 2 ve MVC 4) Razor'da yerleşik koşullu özniteliklere sahip olacağız (MVC 4 RC başarıyla test edildiğinden beri), bu nedenle şunu söyleyebilirsiniz: böyle şeyler...

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

StrCSSClass null ise, sınıf özniteliği hiç işlenmez.

SSSHHH ... söyleme. :)


1
Evet, kesinlikle benimkini cevap olarak kabul etmemelisin. Bununla birlikte, bugün bunu yapmanın daha temiz bir yolu yok (dolayısıyla bunu yapmanın daha temiz bir yolunu yaratıyoruz). Muhtemelen bunu yapmanın en temiz yolu, Html.TextBox'ı kullanmaktır, ancak bu, daha az istenen şeylerin farklı bir kümesine sahiptir. :( Yine de eklediklerimizi beğendiğinize sevindim. :)
Erik Porter

1
Ancak Razor niteliklerini diğer metinlerle nasıl birleştirebilirim? Aşağıdakileri yapmam gerekiyor: ... id = "track_@track.ID". ... id = "track_2" gibi bir şey bekliyordum, ancak şu çıktıyı oluşturdu: ... id = "track_@track.ID" ...
Laserson

2
Razor'u, etrafına parantez koyarak kodu değerlendirmeye zorlayabilirsiniz. id = "track _ @ (track.ID)"
Erik Porter

1
Bunun MVC 4 ile başarılı bir şekilde çalıştığını belirten not eklendi. MVC 3'teyseniz aşağıdaki cevabıma bakın.
AaronLS

4
@ErikPorter LÜTFEN HTML'İMLE MESAJ YAPMAYIN !! ayrıca diğer kötü davranışlar için de stackoverflow.com/questions/9234467/… sayfasına bakın
eaglestorm

126

Bunun gibi bir şey yapabileceğinizi unutmayın (en azından MVC3'te):

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

Jilet eklemeye inandığım şey aslında tarayıcıydı. Rism'in MVC 4 ile test ederken belirttiği gibi (MVC 3 ile test etmedim, ancak davranışın değişmediğini varsayıyorum), bu aslında üretiyor class=TopBorderancak tarayıcılar bu sorunu çözebiliyor . HTML ayrıştırıcıları, eksik öznitelik tırnaklarını biraz affederler, ancak boşluklarınız veya belirli karakterleriniz varsa bu durum bozulabilir .

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

VEYA

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

Kendi alıntılarınızı vermenin nesi yanlış?

İç içe alıntılar için olağan C # kurallarından bazılarını kullanmaya çalışırsanız, pazarlık ettiğinizden daha fazla alıntı elde edersiniz çünkü Razor onlardan güvenli bir şekilde kaçmaya çalışıyor. Örneğin:

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

Bu gerektiğini değerlendirmek <button type="button" style="border:0px">ancak Razor C # tüm çıkışlarını kaçar ve böylece üretir:

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

Bunu yalnızca yanıtı ağ üzerinden görüntülerseniz göreceksiniz. Bir HTML denetçisi kullanıyorsanız, genellikle ham HTML'yi değil, aslında DOM'u görürsünüz. Tarayıcılar HTML'yi DOM'a ayrıştırır ve ayrıştırma sonrası DOM gösteriminin bazı özellikleri zaten uygulanmıştır. Bu durumda Tarayıcı, öznitelik değerinin etrafında alıntı olmadığını görür ve bunları ekler:

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

Ancak DOM denetçisinde HTML karakter kodları doğru şekilde görüntülendiğinden şunları gerçekten görürsünüz:

style=""border:0px""

Chrome'da, sağ tıklayıp HTML'yi Düzenle'yi seçerseniz, bu iğrenç HTML karakter kodlarını görebilmeniz için geri dönerek gerçek dış tırnaklara ve HTML kodlu iç tırnaklara sahip olduğunuzu açıkça gösterir.

Yani alıntı yapmayı kendiniz yapmaya çalışmanın sorunu Razor'un bunlardan kaçmasıdır.

Tekliflerin tam kontrolünü istiyorsanız

Alıntı kaçışını önlemek için Html.Raw kullanın:

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

Oluşturma şekli:

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

Yukarıdakiler tamamen güvenlidir çünkü bir değişkenden herhangi bir HTML çıktısı almıyorum. İlgili tek değişken üçlü koşuldur. Ancak, bu son tekniğin, kullanıcı tarafından sağlanan verilerden dizeler oluşturuyorsanız sizi belirli güvenlik sorunlarına maruz bırakabileceğine dikkat edin . Örneğin, kullanıcı tarafından sağlanan verilerden kaynaklanan veri alanlarından bir öznitelik oluşturduysanız, Html.Raw kullanımı, dizenin öznitelik ve etiketin erken bir sonunu içerebileceği anlamına gelir, ardından o anda oturum açmış olan adına bir şeyler yapan bir komut dosyası etiketi başlatır. kullanıcı (muhtemelen oturum açmış kullanıcıdan farklı). Belki de tüm kullanıcıların resimlerinin bir listesini içeren bir sayfanız vardır ve her bir kişinin kullanıcı adı olacak bir araç ipucu ayarlıyorsunuz ve bir kullanıcı kendi adını verdi'/><script>$.post('changepassword.php?password=123')</script> ve şimdi bu sayfayı görüntüleyen herhangi bir kullanıcının şifresi anında kötü niyetli kullanıcının bildiği bir şifreye dönüştü.


Bu çok güzel bir nokta! Ve aslında, çoğu durumda okunabilir ve kullanılabilir hale getirir.
Dmytro Shevchenko

Sorumdaki örnekte bunu yapıyordum. Daha ayrıntılı bir açıklama ve örnek için teşekkürler. :)
tony722

1
Yine de boşluklara dikkat edin. "style = display: yok;" yok olarak oluşturulur; = "": = "" style = "display"
wmcainsh

1
Öyleyse neden bu re: magic çift tırnak <span @ (true? "Class = logo-owner": string.Empty) /> çalışmıyor <span class = logo-owner />
rism

1
@AaronLS Evet, aynen böyleler. Tarayıcının (Chrome 40 / FF33.1 / IE 10) herhangi bir şeyi nasıl etkileyeceğini anlayamıyorum, çünkü bu sunucu tarafından oluşturulan işaretlemedir ve eğer öyleyse, nasıl olur da sor düğmesinin sınıf özelliği için değil, hatta type = Her üç düğmenin de "düğme" özellikleri. Kesinlikle bir sunucu işi IMHO çünkü aynı sonuç IE / Firefox / Chrome için dünya çapında noktalı birkaç Azure sanal makinesine de RDP yapabilirim.
rism

12

Sanırım biraz daha uygun ve yapılandırılmış bir yol Html yardımcısını kullanmaktır. Size göre şöyle görünebilir:

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

@* ... *@

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

Bu yol sizin için yararlı olacaksa htmlAttr, modelinizde sözlük tanımlamanızı öneririm, böylece görünümünüzün herhangi bir @{ }mantık bloğuna ihtiyaç duymaz (daha net olun).


4
-1, görüşlere mantık koymasını asla önermeyin. Yeni görünümler yalnızca sunumdan sorumlu olmalıdır. Bunun yerine bir HtmlHelper örneği ekleyin, size +1 vereceğim.
jgauffin

1
Bir şeyleri test etmek için görünümde kod bloğunu kullanabilirim - daha hızlı. Ve tavsiyem bu bloğu modele taşımaktı.
Yaschur

3
evet, ancak cevaplar kod bakımını bir kabusa dönüştüren hızlı ve kirli versiyonu değil, en iyi uygulamayı göstermelidir.
jgauffin

@jgauffin Burada Html yardımcısının gereksiz olduğunu düşünüyorum. cevabımı gör.
gdoron,

+1 @Yaschur Cevabınız ilham verici. İyi çalışmaya devam edin. yani. C # açık dönüştürme özelliği ile bu yanıtı daha da geliştirebiliriz. Tüm kodun belirli bir şekilde şekillendirilmesi gerekmiyordu. Her zaman farkında olmadığımız daha iyi bir yol vardır. Ve bazı projeler kod organizasyonundan yanadır. Kod organizasyonu pratikte kavram değildir!
Bamboo
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.