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