使用Razor MVC3的条件HTML属性

ton*_*722 96 html razor asp.net-mvc-3

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

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

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

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

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

Eri*_*ter 155

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

<input type="text" id="@strElementID" class="@strCSSClass" />
Run Code Online (Sandbox Code Playgroud)

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

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

  • @ErikPorter请不要误解我的HTML!另请参阅http://stackoverflow.com/questions/9234467/razor-view-engine-automatically-applying-quotes/21126527#21126527以及其他不良行为 (4认同)
  • 您可以强制Razor通过在其周围放置pare来评估代码.ID = "轨道_ @(track.ID)" (2认同)

Aar*_*nLS 118

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

<td align="left" @(isOddRow ? "class=TopBorder" : "style=border:0px") >
Run Code Online (Sandbox Code Playgroud)

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

<td align="left" class="TopBorder" >
Run Code Online (Sandbox Code Playgroud)

要么

<td align="left" style="border:0px" >
Run Code Online (Sandbox Code Playgroud)

提供自己的报价有什么问题

如果你试图对嵌套引号使用一些通常的C#约定,你最终会得到比你讨价还价更多的引号,因为Razor试图安全地逃避它们.例如:

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

应该评估,<button type="button" style="border:0px">但Razor逃避C#的所有输出,从而产生:

style=&quot;border:0px&quot;
Run Code Online (Sandbox Code Playgroud)

如果您通过网络查看响应,则只会看到此信息.如果您使用HTML检查器,通常您实际上看到的是DOM,而不是原始HTML.浏览器将HTML解析为DOM,并且解析后的DOM表示已经应用了一些细节.在这种情况下,浏览器会看到属性值周围没有引号,添加它们:

style="&quot;border:0px&quot;"
Run Code Online (Sandbox Code Playgroud)

但是在DOM检查器中,HTML字符代码显示正确,因此您实际看到:

style=""border:0px""
Run Code Online (Sandbox Code Playgroud)

在Chrome中,如果右键单击并选择编辑HTML,它会切换回来,这样您就可以看到那些讨厌的HTML字符代码,清楚地表明您有真正的外部引号和HTML编码的内部引号.

所以试图自己引用的问题是Razor逃脱了这些.

如果您想完全控制报价

使用Html.Raw来防止引用转义:

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

呈现为:

<td rel='tooltip' title='Drilldown' data-container='.drillDown a'>
Run Code Online (Sandbox Code Playgroud)

以上是非常安全的,因为我没有从变量输出任何HTML.涉及的唯一变量是三元条件.但是,请注意,如果从用户提供的数据构建字符串,最后一种技术可能会使您遇到某些安全问题.例如,如果您从源自用户提供的数据的数据字段构建属性,则使用Html.Raw意味着字符串可能包含属性和标记的过早结束,然后开始代表当前登录的某个内容的脚本标记用户(可能与登录用户不同).也许您有一个包含所有用户图片列表的页面,并且您正在设置工具提示作为每个人的用户名,并且一个用户自己命名'/><script>$.post('changepassword.php?password=123')</script>,现在任何其他用户查看此页面的密码都会立即更改为密码恶意用户知道.


小智 11

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

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

@* ... *@

@Html.TextBox("somename", "", htmlAttr)
Run Code Online (Sandbox Code Playgroud)

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

  • -1,永远不建议有人在视图中放置逻辑.Thew视图应该只负责渲染.添加一个HtmlHelper示例,我会给你+1. (3认同)
  • 是的,但答案应该显示最佳实践,而不是使代码维护成为噩梦的快速而肮脏的版本。 (3认同)