使用Razor MVC3的条件HTML属性

时间:2011-11-09 07:29:51

标签: html asp.net-mvc-3 razor

变量strCSSClass通常具有值,但有时为空。

我不想在这个输入元素的HTML中包含一个空的class =“”,这意味着如果strCSSClass为空,我根本不需要class =属性。

以下是执行条件HTML属性的一种方法:

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

有更优雅的方式吗?特别是我可以遵循与元素的其他部分使用相同的语法:class =“@ strCSSClass”?

3 个答案:

答案 0 :(得分:154)

你没有听到我,Razor的PM,但在Razor 2(网页2和MVC 4)中我们将内置Razor的条件属性(从MVC 4 RC测试成功),所以你可以这么说......

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

如果strCSSClass为null,那么class属性根本不会呈现。

SSSHHH ......不要说。 :)

答案 1 :(得分:116)

注意你可以做这样的事情(至少在MVC3中):

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

我认为剃须刀添加引号实际上是浏览器。正如Rism在使用MVC 4进行测试时指出的那样(我没有使用MVC 3进行测试,但我认为行为没有改变),这实际上产生了class=TopBorder,但是浏览器能够解析这个问题。 HTML解析器对丢失的属性引号有些宽容,但如果你有空格或某些字符,会破坏。

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

OR

<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;"

但是在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>$.post('changepassword.php?password=123')</script>,现在查看此页面的任何其他用户的密码都会立即更改到恶意用户知道的密码。

答案 2 :(得分:11)

我想更方便和结构化的方法是使用Html帮助器。在您看来,它可能看起来像:

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

@* ... *@

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

如果这种方式对您有用,我建议您在模型中定义字典htmlAttr,这样您的视图就不需要任何@{ }逻辑块(更清楚)。