แอตทริบิวต์ HTML แบบมีเงื่อนไขโดยใช้ Razor MVC3


100

ตัวแปร strCSSClass มักมีค่า แต่บางครั้งก็ว่างเปล่า

ฉันไม่ต้องการรวม class = "" ที่ว่างเปล่าไว้ใน HTML ขององค์ประกอบอินพุตนี้ซึ่งหมายความว่าถ้า strCSSClass ว่างเปล่าฉันไม่ต้องการแอตทริบิวต์ class = เลย

ต่อไปนี้เป็นวิธีหนึ่งในการสร้างแอตทริบิวต์ HTML แบบมีเงื่อนไข:

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

มีวิธีที่หรูหรากว่านี้หรือไม่? โดยเฉพาะอย่างยิ่งที่ฉันสามารถทำตามไวยากรณ์เดียวกันกับที่ใช้ในส่วนอื่น ๆ ขององค์ประกอบ: class = "@ strCSSClass"?

คำตอบ:


160

คุณไม่ได้ยินจากฉัน PM สำหรับ Razor แต่ใน Razor 2 (หน้าเว็บ 2 และ MVC 4) เราจะมีแอตทริบิวต์ที่มีเงื่อนไขใน Razor (เมื่อทดสอบ MVC 4 RC เรียบร้อยแล้ว) ดังนั้นคุณสามารถพูดได้ว่า ของแบบนี้ ...

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

ถ้า strCSSClass เป็นโมฆะแอตทริบิวต์คลาสจะไม่แสดงผลเลย

SSSHHH ... ไม่บอก. :)


1
ใช่คุณไม่ควรยอมรับคำตอบของฉันอย่างแน่นอน ที่กล่าวว่าวันนี้ไม่มีวิธีที่สะอาดกว่านี้แล้ว (ดังนั้นเราจึงสร้างวิธีที่สะอาดกว่านี้) อาจเป็นวิธีที่สะอาดที่สุดคือใช้ Html.TextBox แต่มีชุดของสิ่งที่ไม่ต้องการน้อยกว่าที่แตกต่างกัน :( ดีใจที่คุณชอบสิ่งที่เรากำลังเพิ่ม :)
Erik Porter

1
แต่ฉันจะรวมคุณสมบัติของ Razor กับข้อความอื่น ๆ ได้อย่างไร? ฉันต้องดำเนินการดังต่อไปนี้: ... id = "track_@track.ID" ฉันคาดหวังบางอย่างเช่น ... id = "track_2" แต่มันสร้างผลลัพธ์ต่อไปนี้: ... id = "track_@track.ID" ...
Laserson

2
คุณสามารถบังคับให้ Razor ประเมินโค้ดได้โดยวาง parens ไว้รอบ ๆ id = "track _ @ (track.ID)"
Erik Porter

1
เพิ่มหมายเหตุระบุว่าทำงานได้สำเร็จกับ MVC 4 หากคุณใช้ MVC 3 ดูคำตอบของฉันด้านล่าง
AaronLS

4
@ErikPorter โปรดอย่าส่งข้อความถึง HTML ของฉัน !! นอกจากนี้โปรดดูstackoverflow.com/questions/9234467/…นี้เช่นกันสำหรับพฤติกรรมที่ไม่ดีอื่น ๆ
eaglestorm

126

โปรดทราบว่าคุณสามารถทำสิ่งนี้ได้ (อย่างน้อยใน MVC3):

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

สิ่งที่ฉันเชื่อคือการเพิ่มเครื่องหมายคำพูดคือเบราว์เซอร์จริงๆ ดังที่ Rism ชี้ให้เห็นเมื่อทดสอบกับ MVC 4 (ฉันยังไม่ได้ทดสอบกับ MVC 3 แต่ฉันคิดว่าพฤติกรรมไม่เปลี่ยนแปลง) สิ่งนี้เกิดขึ้นจริงclass=TopBorderแต่เบราว์เซอร์สามารถแยกวิเคราะห์ได้ดี parsers HTML จะค่อนข้างให้อภัยในคำพูดที่ขาดหายไปแอตทริบิวต์ แต่นี้สามารถทำลายถ้าคุณมีช่องว่างหรือตัวอักษรบางอย่าง

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

หรือ

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

เกิดอะไรขึ้นกับการเสนอราคาของคุณเอง

หากคุณพยายามใช้รูปแบบ C # ทั่วไปสำหรับคำพูดที่ซ้อนกันคุณจะได้ราคามากกว่าที่คุณต่อรองเพราะ Razor พยายามที่จะหลบหนีอย่างปลอดภัย ตัวอย่างเช่น:

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

สิ่งนี้ควรประเมิน<button type="button" style="border:0px">แต่ Razor หลบหนีเอาต์พุตทั้งหมดจาก C # และทำให้เกิด:

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

คุณจะเห็นสิ่งนี้ก็ต่อเมื่อคุณดูการตอบกลับผ่านเครือข่าย หากคุณใช้ตัวตรวจสอบ HTML คุณมักจะเห็น DOM ไม่ใช่ HTML ดิบ เบราว์เซอร์แยกวิเคราะห์ HTML ลงใน DOM และการแสดง DOM หลังการแยกวิเคราะห์ก็มีการใช้เฉพาะบางอย่างแล้ว ในกรณีนี้เบราว์เซอร์จะเห็นว่าไม่มีเครื่องหมายคำพูดรอบค่าแอตทริบิวต์ให้เพิ่ม:

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

แต่ในโค้ดอักขระ HTML ของตัวตรวจสอบ DOM จะแสดงอย่างถูกต้องดังนั้นคุณจึงเห็น:

style=""border:0px""

ใน Chrome หากคุณคลิกขวาและเลือกแก้ไข HTML ระบบจะเปลี่ยนกลับเพื่อให้คุณเห็นรหัสอักขระ HTML ที่น่ารังเกียจเหล่านั้นทำให้ชัดเจนว่าคุณมีเครื่องหมายคำพูดภายนอกจริงและเครื่องหมายคำพูดภายในที่เข้ารหัส HTML

ดังนั้นปัญหาในการพยายามยกคำพูดด้วยตัวเองคือ Razor หนีสิ่งเหล่านี้

หากคุณต้องการควบคุมคำพูดที่สมบูรณ์

ใช้ Html.Raw เพื่อป้องกันการหลุดของใบเสนอราคา:

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

แสดงผลเป็น:

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

ข้างต้นปลอดภัยอย่างสมบูรณ์เพราะฉันไม่ได้ส่งออก HTML ใด ๆ จากตัวแปร ตัวแปรเดียวที่เกี่ยวข้องคือเงื่อนไขที่สาม อย่างไรก็ตามโปรดระวังว่าเทคนิคสุดท้ายนี้อาจทำให้คุณพบปัญหาด้านความปลอดภัยหากสร้างสตริงจากข้อมูลที่ผู้ใช้ให้มา เช่นหากคุณสร้างแอตทริบิวต์จากช่องข้อมูลที่มาจากข้อมูลที่ผู้ใช้ให้มาการใช้ Html.Raw หมายความว่าสตริงอาจมีการสิ้นสุดก่อนกำหนดของแอตทริบิวต์และแท็กจากนั้นเริ่มแท็กสคริปต์ที่ทำอะไรบางอย่างในนามของผู้ที่ล็อกอินอยู่ ผู้ใช้ (อาจแตกต่างจากผู้ใช้ที่เข้าสู่ระบบ) บางทีคุณอาจมีหน้าที่มีรายชื่อรูปภาพของผู้ใช้ทั้งหมดและคุณกำลังตั้งคำแนะนำเครื่องมือให้เป็นชื่อผู้ใช้ของแต่ละคนและผู้ใช้หนึ่งคนตั้งชื่อตัวเองว่า'/><script>$.post('changepassword.php?password=123')</script> และตอนนี้ผู้ใช้รายอื่นที่ดูหน้านี้ได้เปลี่ยนรหัสผ่านเป็นรหัสผ่านที่ผู้ใช้ประสงค์ร้ายทราบทันที


นั่นเป็นจุดที่ดีมาก! และที่จริงมันทำให้อ่านง่ายและใช้งานได้ในสถานการณ์ส่วนใหญ่
Dmytro Shevchenko

นั่นคือสิ่งที่ฉันทำในตัวอย่างในคำถามของฉัน ขอบคุณสำหรับคำอธิบายและตัวอย่างที่ละเอียดยิ่งขึ้น :)
tony722

1
ระวังช่องว่างแม้ว่า "style = display: none;" = "": = "" style = "display"
wmcainsh

1
แล้วทำไมไม่ใช้ re: magic double quotes <span @ (true? "class = logo-owner": string.Empty) /> มันเพิ่งสร้าง <span class = logo-owner />
rism

1
@AaronLS ใช่ว่าพวกเขาเป็นอย่างไร ไม่เข้าใจว่าเบราว์เซอร์ (Chrome 40 / FF33.1 / IE 10) จะส่งผลกระทบต่อสิ่งใดบ้างเนื่องจากนี่เป็นมาร์กอัปที่สร้างโดยเซิร์ฟเวอร์และถ้าเป็นเช่นนั้นจะมาเฉพาะแอตทริบิวต์คลาสทั้งสองนี้ได้อย่างไร แต่ไม่ใช่สำหรับแอตทริบิวต์คลาสของปุ่ม ask หรือแม้แต่ type = "ปุ่ม" แอตทริบิวต์ของทั้งสามปุ่ม แน่นอนว่าเซิร์ฟเวอร์คือ IMHO เนื่องจากฉันสามารถ RDP ไปยังเครื่องเสมือน Azure สองเครื่องที่มีอยู่ทั่วโลกเพื่อให้ได้ผลลัพธ์เดียวกันกับ IE / Firefox / Chrome
rism

12

ฉันเดาว่าวิธีที่สะดวกและมีแบบแผนกว่าเล็กน้อยคือการใช้ตัวช่วย Html ในมุมมองของคุณอาจมีลักษณะดังนี้:

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

@* ... *@

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

หากวิธีนี้เป็นประโยชน์สำหรับคุณฉันขอแนะนำให้กำหนดพจนานุกรมhtmlAttrในแบบจำลองของคุณเพื่อให้มุมมองของคุณไม่ต้องการ@{ }บล็อกตรรกะใด ๆ(ชัดเจนยิ่งขึ้น)


4
-1 ไม่แนะนำให้ใครใส่ตรรกะในมุมมอง Thew views ควรรับผิดชอบในการแสดงผลเท่านั้น เพิ่มตัวอย่าง HtmlHelper แทนแล้วฉันจะให้ +1
jgauffin

1
ในการทดสอบสิ่งต่างๆฉันสามารถใช้บล็อกโค้ดในมุมมอง - มันเร็วกว่า และคำแนะนำของฉันคือย้ายบล็อกนี้ไปเป็นโมเดล
Yaschur

3
ใช่ แต่คำตอบควรแสดงแนวทางปฏิบัติที่ดีที่สุดไม่ใช่เวอร์ชันที่รวดเร็วและสกปรกซึ่งทำให้การบำรุงรักษาโค้ดกลายเป็นฝันร้าย
jgauffin

@jgauffin ฉันคิดว่าตัวช่วย Html ที่นี่ไม่จำเป็น ดูคำตอบของฉัน
gdoron สนับสนุน Monica

+1 @Yaschur คำตอบของคุณสร้างแรงบันดาลใจ ดีแล้วทำต่อไป. กล่าวคือ. ด้วยคุณสมบัติการแปลง C # อย่างชัดเจนเราสามารถปรับปรุงคำตอบนี้ได้มากขึ้น รหัสทั้งหมดไม่จำเป็นต้องมีรูปร่างในลักษณะที่แน่นอน มีวิธีที่ดีกว่าที่เราไม่ทราบอยู่เสมอ และบางโครงการก็สนับสนุนการจัดระเบียบรหัส การจัดระเบียบรหัสเป็นไปตามแนวปฏิบัติไม่ใช่แนวคิด!
ไผ่
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.