使用Razor MVC3的条件HTML属性


100

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

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

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

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

有没有更优雅的方式做到这一点?具体来说,我可以遵循与元素其他部分中使用的相同的语法:class =“ @ strCSSClass”?

Answers:


160

您没有从Razor的PM那里得到我的消息,但是在Razor 2(网页2和MVC 4)中,我们将在Razor中内置条件属性(自MVC 4 RC成功测试以来),所以您可以说这样的事情...

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

如果strCSSClass为null,则class属性将完全不呈现。

SSSHHH ...不要告诉。:)


1
是的,您绝对不应该接受我的回答。也就是说,今天没有更清洁的方法可以这样做(因此我们正在创建一种更清洁的方法)。可能最干净的方法是使用Html.TextBox,但这具有另一组不太理想的东西。:(很高兴您喜欢我们正在添加的内容。:)
Erik Porter

1
但是如何将Razor属性与其他文本结合起来?我需要进行以下操作:... id =“ track_@track.ID”。我曾期望像... id =“ track_2”这样的东西,但是它生成了以下输出:... id =“ track_@track.ID” ...
Laserson 2012年

2
您可以通过在其周围放置括号来强制Razor评估代码。id =“ track _ @(track.ID)”
埃里克·波特

1
添加了说明,指出该功能可在MVC 4上成功使用。如果您使用的是MVC 3,请在下面查看我的答案。
AaronLS 2012年

4
@ErikPorter请不要使用我的HTML !!另请参见stackoverflow.com/questions/9234467/…对于其他不良行为也是如此
eaglestorm 2014年

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

但是在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> 现在,所有其他访问该页面的用户的密码都会立即更改为恶意用户知道的密码。


这是非常好的一点!实际上,它使它在大多数情况下可读和可用。
Dmytro Shevchenko

这就是我在问题示例中所做的事情。感谢您提供更详尽的解释和示例。:)
tony722

1
提防空间。“样式=显示:无;” 呈现为none; =“”:=“” style =“ display”
wmcainsh 2013年

1
那么,为什么这样不起作用:魔术双引号<span @(true?“ class = logo-owner”:string.Empty)/>它只是产生<span class = logo-owner />
rism

1
@AaronLS是的,这就是事实。不能理解浏览器(Chrome 40 / FF33.1 / IE 10)会如何影响任何东西,因为这是服务器生成的标记,如果是这样,怎么会只出现这两个类属性,而不是问按钮的类属性甚至type =所有三个按钮的“按钮”属性。绝对是服务器的恕我直言,因为我还可以将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视图仅应负责渲染。而是添加一个HtmlHelper示例,我将给您+1。
jgauffin

1
为了测试,我可以在视图中使用代码块-更快。我的建议是将此模块移入模型。
Yaschur

3
是的,但是答案应该显示最佳实践,而不是快速而肮脏的版本,这会使代码维护成为一场噩梦。
jgauffin

@jgauffin我认为这里的HTML帮助程序是不必要的。看我的答案。
gdoron支持Monica 2011年

+1 @Yaschur您的回答鼓舞人心。保持良好的工作。即。借助C#显式转换功能,我们可以进一步增强此答案。并非所有的代码都必须以某种特定的方式进行调整。总会有我们不知道的更好的方法。一些项目支持代码组织。代码组织实际上不是概念!
Bamboo
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.