Условные атрибуты HTML с использованием Razor MVC3

Переменная strCSSClass часто имеет значение, но иногда пусто.

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

Ниже приведен один из способов сделать условный атрибут HTML:

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

Есть ли более элегантный способ сделать это? В частности, я мог бы следовать тому же синтаксису, который используется в других частях элемента: class= "@strCSSClass"?

Ответ 1

Вы не слышали об этом от меня, PM для Razor, но в Razor 2 (Web Pages 2 и MVC 4) у нас будут условные атрибуты, встроенные в Razor (как из MVC 4 RC успешно протестированы), так что вы можно просто сказать такие вещи...

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

Если strCSSClass имеет значение null, атрибут класса не будет отображаться вообще.

SSSHHH... не говорите.:)

Ответ 2

Заметьте, что вы можете сделать что-то вроде этого (по крайней мере, в MVC3):

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

То, что я считал, - это цитата из бритвы, которая была на самом деле браузером. Как заметил Рисс при тестировании с MVC 4 (я не тестировал с MVC 3, но я предполагаю, что поведение не изменилось), это фактически создает class=TopBorder, но браузеры могут разобрать этот тон. Парсеры HTML несколько прощают отсутствующие атрибуты кавычек, но это может сломаться, если у вас есть пробелы или определенные символы.

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

ИЛИ

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

Что не так с предоставлением собственных котировок

Если вы попытаетесь использовать некоторые обычные С# -конвенции для вложенных кавычек, вы получите больше кавычек, чем вы рассчитывали, потому что Razor пытается безопасно избежать их. Например:

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

Это должно оцениваться до <button type="button" style="border:0px">, но Razor избегает всего вывода из С# и, таким образом, производит:

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

Вы увидите это только в том случае, если вы просмотрите ответ по сети. Если вы используете инспектор HTML, часто вы видите DOM, а не необработанный HTML. Браузеры анализируют HTML в DOM, и представление DOM после парсинга уже имеет некоторые тонкости. В этом случае браузер видит, что вокруг значения атрибута нет кавычек, добавляет их:

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

Но в инспекторе DOM коды символов HTML отображаются правильно, поэтому вы действительно видите:

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, который делает что-то от имени текущего журнала в пользователе (возможно, отличается от зарегистрированного пользователя). Возможно, у вас есть страница со списком всех фотографий пользователей, и вы устанавливаете всплывающую подсказку как имя пользователя для каждого человека, а один пользователь назвал себя '/><script>$.post('changepassword.php?password=123')</script>, и теперь любой другой пользователь, просматривающий эту страницу, мгновенно изменяет свой пароль на пароль, который злонамеренный пользователь знает.

Ответ 3

Я думаю, что более удобный и структурированный способ - использовать хелпер-хелпер. На ваш взгляд это может выглядеть так:

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

@* ... *@

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

Если этот способ будет полезен для вас, я рекомендую определить словарь htmlAttr в вашей модели, чтобы ваше представление не нуждалось в каких-либо логических блоках @{ } (более понятно).