【问题标题】:Razor View Engine: Complex looping and HTMLRazor 视图引擎:复杂的循环和 HTML
【发布时间】:2011-01-24 12:22:00
【问题描述】:

在我当前的项目中,我有很多复杂的 HTML 报告,在那里我们使用行跨度和列跨度对 TR 和 TD 执行大量条件渲染。

它有时可能看起来像这样(这是非常简化的):

<tr>
@foreach (var ourItem in ourList) {
   if (ourItem != ourList.First()) {
      <tr>                
   }
   <td></td>
   </tr>
}

但是,Razor 声称:“foreach 循环缺少一个结束“}”字符”。 (在 Visual Studio 中)

我试图将&lt;tr&gt; 包装在&lt;text&gt;&lt;/text&gt; 中,这使得结束 } 问题消失了,只是在运行时发现这个问题:“遇到结束标签“tr”没有匹配的开始标签。你的开始/结束标签适当平衡”。

如何在说服 Razor 完全不关心 HTML 的同时进行这种条件渲染,因为当所有循环完成时 HTML 是平衡的。或者至少在使用 ASP.NET 视图引擎时是这种情况。

【问题讨论】:

  • 从您的代码看来,整个 tr 和 /tr 片段不应该在相同的 if 条件内。我没有使用剃须刀,但您所显示的内容似乎令人困惑。如果不满足条件,则 /tr 标签将第一个 tr 作为起始标签,如果满足条件,则它用于第二个 tr 标签,而第一个标签没有相应的 /tr 标签。只是我观察到的。
  • 上面的代码可能很笨,但它是有效的。无论如何呈现为 HTML 时。我在这里试图证明的一点是,即使呈现的结果是有效的 HTML,Razor 也会进入并破坏它,因为它无法接受它认为会产生的奇怪语义。
  • @sassyboy 如果 ourList 非空,那么应该总是有匹配的 trs。打开的 tr 要么是列表中第一项的循环外的一个,要么是后续项的条件内的一个。
  • 为了将事情保持在最低限度,这是我们必须关注的代码。让我们假设列表是非空的。鉴于此,我想制作 Razor 来渲染它。

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


【解决方案1】:

Visual Studio Intellisense 和语法突出显示不是最好的之一,但在这种情况下,它会警告您,如果不满足条件,您可能会得到无效的标记,您不应该为此责备它。

重要的是您的项目运行良好,但您可能会考虑将此逻辑外部化到 HTML 帮助程序中,因为如果您所说的是真的,这是您在视图中的简化版本,我什至不想想象一下您的实际代码的外观。

恕我直言,在视图中有这么多条件逻辑是一种滥用。您绝对应该考虑使用 HTML 帮助程序或控件,例如 MVCContrib Grid


更新:

您可以尝试以下 hack:

<tr>
@foreach (var ourItem in ourList) {
   if (ourItem != ourList.First()) {
      @:<tr>                
   }
   @:<td></td>
   @:</tr>
}

【讨论】:

  • 哦,我在 Cassini 中运行时遇到了完全相同的错误。基本上问题是 Razor 负责渲染 HMTL。我真的想把它关掉。
  • 我同意你的看法。在 SP1 中,它们没有标签折叠功能,这可能是我们使用 CTRL M + T。有时它们会显示错误,即使代码也可以正常工作,至少没问题,但 VS 说缺少语法。
  • 对您更新中的@: 选项投了赞成票,我认为这不是黑客行为。
  • @DarinDimitrov: @: 对我不起作用。它会引发解析器错误。
  • 它不工作的可能原因是什么?我在结束 标记之前有一个 for 循环和一个 if 循环。
【解决方案2】:

Razor 依赖于匹配的标签来确定代码和标记之间的自动转换。您不能“禁用” Razor 的此功能(至少在不重写大部分 Razor 解析器的情况下不能)。

您可以使用 Darin 的建议来解决它,但我不明白(至少不是从您的简化示例中)为什么您的视图需要如此复杂。为什么不写下面的代码:

@foreach (var ourItem in ourList) {
   <tr>
   <td>...</td>
   </tr>
}

虽然标签可能会在生成的标记中平衡,但您提供的来源很难推断其正确性。

【讨论】:

    【解决方案3】:

    当尝试使用 rowspan 并尝试获得类似的结构时

    <table>
       <tr>
           <td rowspan=2>1:st col</td>
           <td>2:nd col</td>
       </tr>
       <tr>
           <td>2:nd col</td>
       </tr>
    </table>
    

    你可以试试:

    @{ 
        var ourList = new List<string> { "1", "2", "3" };
    }
    
    <table border=1>
    @foreach(var ourItem in ourList){
        <tr>
        @if (ourItem == ourList.First())
        {
            <td rowspan="@ourList.Count()">@ourItem</td>
        }
        <td>@ourItem</td>
        </tr>
    }
    </table>
    

    【讨论】:

      【解决方案4】:

      我有一个类似的问题 - 我的解决方案 Html.Raw("");

          if (isTrue)
          {
              <text><div></text> }
         ...
      
          if(isTrue) {
              @Html.Raw("</div>"); // <-- closing tag!
              }
      

      【讨论】:

        猜你喜欢
        相关资源
        最近更新 更多
        热门标签