Razor View Engine: сложный цикл и HTML

В моем текущем проекте есть много сложных HTML-отчетов, где мы выполняем много условного рендеринга TR и TD с помощью рядов и colspans.

Иногда это может выглядеть (это очень упрощено):

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

Однако, Razor утверждает: "В цикле foreach отсутствует закрывающий" } "символ". (в Visual Studio)

Я попытался обернуть <tr> в <text></text>, из-за чего проблема закрытия закрывается, только чтобы найти это при запуске: "Encounted end tag" tr "без соответствующего начального тега. теги должным образом сбалансированы".

Как бы я сделал такой условный рендеринг, убеждая Razor вообще не беспокоиться о HTML, потому что HTML сбалансирован, когда все петли завершены. Или, по крайней мере, это было так, когда использовался ASP.NET View Engine.

Ответ 1

Visual Studio Intellisense и подсветка синтаксиса не одна из лучших, но в этом случае она предупреждает вас, что если условие не выполняется, вы можете получить недопустимую разметку, и вы не должны обвинять ее в этом.

Важно то, что ваш проект работает нормально, но вы можете рассмотреть вопрос об экстернализации этой логики в HTML-помощниках, потому что, если вы говорите правду, это упрощенная версия того, что у вас есть в представлениях, которые я даже не хочу представьте, как выглядит ваш реальный код.

ИМХО, имеющее так много условной логики в представлении, является злоупотреблением. Вы определенно должны рассмотреть возможность использования HTML-помощников или элементов управления, таких как MVCContrib Grid.


ОБНОВЛЕНИЕ:

Вы можете попробовать следующий взлом:

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

Ответ 2

Бритва зависит от совпадающих тегов, чтобы определить автоматические переходы между кодом и разметкой. Вы не можете "отключить" эту функцию Razor (по крайней мере, не переписывая большие части анализатора Razor).

Вы можете обойти это, используя предложение Дарина, хотя я не понимаю (по крайней мере, не из вашего упрощенного примера), почему ваше мнение должно быть настолько запутанным. Почему бы не написать следующий код вместо этого:

@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!
        }