Вывод помощника в методе расширения проглатывается в представлении Razor

Следуя этому вопросу foreach с индексом, я пытался сделать что-то в следующем линии:

Используя метод расширения:

    public static void Each<T>(this IEnumerable<T> ie, Action<T, int> action)
    {
        var i = 0;
        foreach (var e in ie) action(e, i++);
    }

Сделайте итерацию в моем представлении с использованием индекса и вывода результата вспомогательного метода.

            <div class="col-md-12">
                @{ 
                    Model.Take(5).Each((item, n) =>
                    {
                           @RenderItem(item, n == 3);
                    });
                }
           </div

Со следующим помощником

@helper RenderItem(Item item, bool special = false)
{
      <p>Special rendeing for special items in here</p>
}

Однако вывод проглатывается, а не выводится. Есть ли уловка, чтобы заставить это работать?


person Tom    schedule 18.02.2014    source источник


Ответы (1)


Используя этот метод расширения, вы ничего не отправляете в представление. Возвращаемое значение @RenderItem никогда не отправляется в представление. Помощники Razor - это функции, которые просто возвращают HelperResult, но вам нужно отправить это HelperResult в представление. Когда вы вызываете помощник с помощью @MyHelper, он отображает HelperResult, потому что это то, что делает @: что-то визуализирует.

Но когда вы делаете:

Model.Take(5).Each((item, n) =>
      {
           @RenderItem(item, n == 3);
      });

Вы просто вызываете своего помощника, но не ничего выводите на экран (обратите внимание на окончание;). В этом случае @ не является оператором рендеринга, это просто переключатель «перейти к Razor». Вероятно, вы хотели бы отобразить результат .Each, но вы не можете, потому что каждый метод является недействительным.

Я немного поигрался с вашим кодом, просто чтобы показать вам эти концепции. Сначала я изменил ваш Each метод, чтобы он возвращал IEnumerable<HelperResult>:

    public static IEnumerable<HelperResult> Each<T>(this IEnumerable<T> ie, Func<T, HelperResult> action)
    {
        var i = 0;
        foreach (var e in ie) yield return action(e);
    }

Когда метод ожидает HelperResult в коде (как Func<T,HelperResult>), вы можете передать ему выражение Razor, поэтому, на мой взгляд, я могу:

 @Enumerable.Range(1, 10).Each(i => @RenderItem(i, i == 3))

Это вызовет мой помощник RenderItem, но результат будет следующим (обратите внимание, что если вы поместите точку останова в RenderItem, точка останова не будет достигнута из-за ленивого вызова Linq, просто добавьте .ToList () после вызова Each для принудительной оценки ):

WebApplication1.FOo+<Each>d__0`1[System.Int32]

(Если вы использовали .ToList (), это изменится на что-то вроде System.Collections.Generic.List1 [System.Web.WebPages.HelperResult] `)

Это потому, что Razor знает, как рендерить HelperResult, но не IEnumerable<HelperResult>, который у нас действительно есть.

Итак ... что нам нужно делать? Да, просто перебираем результат (используя стандартный foreach) и отображаем каждый результат:

@{
    var x = Enumerable.Range(1, 10).Each(i => @RenderItem(i, i == 3));
    foreach (var ix in x)
    {
        @ix
    }
}

Это будет работать, как ожидалось, теперь вы визуализируете свой HelperResult один за другим.

Конечно, этот код просто показывает, как работают шаблоны Razor :)

Надеюсь, поможет.

person eiximenis    schedule 18.02.2014