【问题标题】:Conditional HTML Attributes using Razor MVC3使用 Razor MVC3 的条件 HTML 属性
【发布时间】:2011-12-25 02:06:48
【问题描述】:

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

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

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

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

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

【问题讨论】:

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


    【解决方案1】:

    请注意,您可以这样做(至少在 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)>
    

    应该评估为&lt;button type="button" style="border:0px"&gt;,但 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 意味着该字符串可能包含属性和标记的过早结束,然后开始一个脚本标记,该标记代表当前登录的用户执行某些操作(可能与登录用户不同)。也许您有一个包含所有用户图片列表的页面,并且您正在将工具提示设置为每个人的用户名,并且一个用户将自己命名为'/&gt;&lt;script&gt;$.post('changepassword.php?password=123')&lt;/script&gt;,现在查看此页面的任何其他用户的密码都会立即更改为恶意用户知道的密码。

    【讨论】:

    • 这是一个非常好的观点!实际上,它使它在大多数情况下都具有可读性和可用性。
    • 这就是我在问题示例中所做的。感谢您提供更详细的解释和示例。 :)
    • 但请注意空格。 “风格=显示:无;”呈现为 none;="" :="" style="display"
    • 那么为什么这不起作用 re: 魔法双引号 它只是产生
    • @AaronLS 是的,他们就是这样。无法理解浏览器(Chrome 40/FF33.1/IE 10)会如何影响任何事情,因为这是服务器生成的标记,如果是这样,为什么只有这两个类属性而不是询问按钮的类属性甚至 type=所有三个按钮的“按钮”属性。恕我直言,绝对是服务器的事情,因为我还可以 RDP 到遍布全球的几个 Azure 虚拟机中获得相同的结果 IE/Firefox/Chrome。
    【解决方案2】:

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

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

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

    SSHHH...别说。 :)

    【讨论】:

    • 是的,你绝对不应该接受我的答案。也就是说,今天没有更清洁的方式来做到这一点(因此我们正在创造一种更清洁的方式来做到这一点)。可能最干净的方法是使用 Html.TextBox,但这有一组不同的不太理想的东西。 :( 很高兴你喜欢我们添加的内容。:)
    • 但是如何将 Razor 属性与其他文本结合起来?我需要做以下事情:... id="track_@track.ID"。我期待像 ...id="track_2" 这样的东西,但它生成了以下输出:...id="track_@track.ID"...
    • 您可以强制 Razor 通过在代码周围放置括号来评估代码。 id="track_@(track.ID)"
    • 添加了说明这与 MVC 4 成功配合的说明。如果您使用的是 MVC 3,请参阅下面的答案。
    • @ErikPorter 请不要乱用我的 HTML!另请参阅stackoverflow.com/questions/9234467/…this 以及其他不良行为
    【解决方案3】:

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

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

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

    【讨论】:

    • -1,永远不要推荐某人将逻辑放入视图中。 Thew 视图应该只负责渲染。添加一个 HtmlHelper 示例,我会给你 +1。
    • 为了测试我可以在视图中使用代码块 - 它更快。我的建议是将这个块移到模型中。
    • 是的,但答案应该显示最佳实践,而不是让代码维护成为噩梦的快速而肮脏的版本。
    • @jgauffin 我认为这里的 Html 助手是不必要的。看我的回答。
    • +1 @Yaschur 您的回答令人鼓舞。保持良好的工作。 IE。使用 C# 显式转换功能,我们可以进一步增强这个答案。并非所有代码都必须以某种方式进行塑造。总有一种我们不知道的更好的方法。一些项目支持代码组织。代码组织是实践而非概念!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-04-29
    相关资源
    最近更新 更多