Умовні атрибути HTML за допомогою Razor MVC3


100

Змінна strCSSClass часто має значення, але іноді порожня.

Я не хочу включати порожній клас = "" в HTML цього вхідного елемента, це означає, що якщо strCSSClass порожній, я взагалі не хочу атрибут class =.

Ось один із способів зробити умовний атрибут HTML:

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

Чи є більш елегантний спосіб зробити це? Зокрема, там, де я міг би дотримуватися того самого синтаксису, який використовується в інших частинах елемента: class = "@ strCSSClass"?

Відповіді:


160

Ви цього не чули від мене, прем’єр-міністра для Razor, але в Razor 2 (Веб-сторінки 2 та MVC 4) у нас будуть вбудовані умовні атрибути (на MVC 4 RC успішно перевірено), тож ви можете просто сказати такі речі ...

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

Якщо strCSSClass недійсний, то атрибут класу взагалі не відображатиметься.

SSSHHH ... не кажи. :)


1
Так, ти точно не повинен сприймати моє як відповідь. Однак, сьогодні немає більш чіткого способу зробити це (отже, ми створюємо більш чистий спосіб зробити це). Напевно, найчистіший спосіб зробити це - використовувати Html.TextBox, але це має інший набір менш бажаних речей. :( Радий, що вам подобається те, що ми додаємо. :)
Ерік Портер

1
Але як я можу поєднувати атрибути Razor з іншим текстом? Мені потрібно зробити наступне: ... id = "track_@track.ID". Я очікував щось на кшталт ... id = "track_2", але він створив такий результат: ... id = "track_@track.ID" ...
Laserson

2
Ви можете змусити Razor оцінити код, поставивши навколо нього паролі. id = "track _ @ (track.ID)"
Ерік Портер

1
Додана примітка із зазначенням, що це успішно працює з MVC 4. Якщо ви перебуваєте на MVC 3, дивіться мою відповідь нижче.
AaronLS

4
@ErikPorter, МОЛУЙТЕ НЕ МУЖТЕ З МОЇМ HTML !! також див. stackoverflow.com/questions/9234467/… це також і для інших поганих поведінок
орлан

126

Зауважте, що ви можете зробити щось подібне (принаймні в MVC3):

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

Те, що я вважав, що бритви додають котирування, - це насправді браузер. Як вказував Rism під час тестування на MVC 4 (я не тестував MVC 3, але я припускаю, що поведінка не змінилася), це фактично призводить до отримання, class=TopBorderале браузери можуть розбирати цей штраф. 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> і тепер будь-який інший користувач, який переглядає цю сторінку, свій пароль миттєво змінив на пароль, який знає шкідливий користувач.


Це дуже вдалий момент! І насправді це робить його читабельним та корисним у більшості ситуацій.
Дмитро Шевченко

Ось що я робив на прикладі у своєму запитанні. Дякую за більш детальне пояснення та приклад. :)
tony722

1
Однак остерігайтеся місця. "стиль = дисплей: немає;" відображається як жоден; = "": = "" style = "display"
wmcainsh

1
То чому б ця робота не повторювалась: магічні подвійні цитати <span @ (правда? "Class = logo-owner": string.Empty) /> Він просто створює <span class = logo-owner />
rism

1
@AaronLS Так, саме так вони і є. Не можу зрозуміти, як браузер (Chrome 40 / FF33.1 / IE 10) впливатиме на що-небудь, оскільки це розмітка, створена сервером, і якщо так, то як тільки ці два атрибути класу, але не атрибут класу кнопки запиту або навіть type = атрибути "кнопки" всіх трьох кнопок. Безумовно, серверна річ IMHO, оскільки я також можу ввімкнути пару віртуальних машин 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, ніколи не рекомендуй комусь вкладати логіку у погляди. Ця подання повинна відповідати лише за візуалізацію. Натомість додайте приклад HtmlHelper, і я дам вам +1.
jgauffin

1
Для тестування речей я можу використовувати блок коду з огляду - це швидше. І моя рекомендація полягала в тому, щоб перемістити цей блок у модель.
Ящур

3
так, але відповіді повинні показувати найкращу практику, а не швидку та брудну версію, яка робить підтримку коду кошмаром.
jgauffin

@jgauffin Я думаю, що помічник Html тут непотрібний. дивіться мою відповідь.
gdoron підтримує Моніку

+1 @Yaschur Ваша відповідь надихає. Продовжуй гарно працювати. тобто. за допомогою функції явного перетворення C # ми можемо ще більше покращити цю відповідь. Не всі коди мали формуватися певним чином. Завжди є кращий спосіб, про який ми не усвідомлюємо. І якийсь проект виступає за організацію коду. Організація коду - це не поняття!
Бамбук
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.