4.3. Partial View или Встраиваемые представления

Я долго ломал голову, как лучше перевести выражение Partial View. Если попытаться дословно, то будет "частичные представления". Если попытаться чуть с большим смыслом, то у меня родился вариант "маленькие представления". Смысл Partial View – это возможность отрисовать часть страницы. У меня прямо ступор был минут на 10, потому что не мог начать писать эту главу и все думал, как же назвать ее.

Поломав немного голову, я решил не переводить термин Partial View дословно, а назвать его по смыслу – встраиваемые представления.

В MVC мы уже знаем, что есть такое понятие шаблона. Внутри шаблона мы можем вызвать RenderBody(), чтобы отрисовать текущую страницу. А что если на странице будет еще какой-то повторяющийся элемент? Например, у меня на сайте в разделе блога, в разделе статей и в книгах (в отдельных главах пока еще не сделал) можно оставлять комментарии. Это совершенно разные страницы, но они используют один и тот же функционал – отображение страниц и отображение формы для сохранения комментариев. Это как-бы регион, внутри страницы, который желательно было бы реализовать отдельно и просто потом вставлять в нужные страницы.

Вот именно это и делают встраиваемые страницы (Partial View). Они не предназначены для того, чтобы отрисовывать все содержимое. Вместо этого такие представления отвечают за логику какой-то части на страницы, и вы это частичное представление встраиваете куда-угодно. Получается, что термин частичное представление тоже верный и можно было перевести дословно? Да! Но мне все же встраиваемое представление почему-то нравится больше. Моя книга, что хочу, то и делаю, поэтому буду использовать такой термин.

Частичные представления – это такие же представления, как и у страниц, только когда фреймворк рендерит их, он не отображает шаблон, потому что он там не нужен.

Как мы уже определились, представления встраиваемые и встраиваться они могут как в файл шаблона, так и в файл представления страницы. Да даже в файл другого встраиваемого представления. В любой cshtml файл (а встраиваемые представления тоже будут иметь такое же расширение) вы можете встроить другое представление. И делается это командой:

@Html.Partial("ИмяФайла", Модель)

Еще один вариант использования частичных представлений – отображение элементов списка. Опять же вернемся к моему сайту. В разделах Блог можно увидеть постранично в 10 элементов мои заметки. Каждая заметка – это отдельное частично представление, поэтому если бы сайт был написан на C#, то страница блога могла выглядит так:

foreach (var blogItem in blogItems) {
@Html.Partial("blog.cshtml", blogitem)
}

Так как у меня сайт написан на PHP, то он так не выглядит, но идея все же такая же.

Но здесь мы говорим про C# и .NET Core поэтому примерно то же самое накидаем на этом фреймворке.

Сначала создадим встраиваемое представление. Его можно поместить в папку Shared, или в ту же папку, из которой мы будем рисовать этот файл. Я помещу его в Views/razortest. Для этого щелкаем правой кнопкой мышки по этой папке и создаем новый файл. Раньше в VS кажется был специальный шаблон, но в версии для Mac я его не увидел. Ну и фиг с ним, это всего лишь шаблоны, мы можем выбрать тут совершенно любой тип файла, главное дать правильное расширение и правильный контент.

Для partial view рекомендуется ставить вначале имени префикс в виде символа подчеркивания. Это не обязательно, а рекомендация, чтобы визуально отличить файлы полноценных представлений от частичных или каких-либо системных, как мы уже делали с _Layout.cshtml.

Итак, в окне выбора шаблона для файла я выбрал MVC View Page (просто захотелось так) и в качестве имени файла указал: _Item.cshtml. VS создаст для нас файл, содержимое которого можно очистить на фиг.

Вместо этого напишем следующий код:

@model MyWebSite.Model.Person
    @Model.FirstName
    

Если вы внимательно читали предыдущие главы, то в этом файле для вас нет совершенно ничего нового. В самом начале мы задаем тип модели, который ожидаем во время вызова представления, а потом идет микс HTML и C# кода, в котором я просто отображаю имя и фамилию.

У нас есть частичное представление, которое мы можем куда-нибудь внедрить, так давайте это и сделаем. Из предыдущих примеров у меня остался контроллер RazortestController и в нем есть метод List, который отображал список людей. Иы использовали этот пример, когда я показывал различные варианты циклов в представлениях. Давайте перепишем этот пример с использованием встраиваемого представления. Контроллер остается тем же, меняем только отображение, поэтому открываем файл List.cshtml и в нем все содержимое заменяем на следующее:

@model MyWebSite.Model.Person[]

Покажем список с помощью Partial View:

@foreach (var p in Model)
{
    @Html.Partial("_Item", p);
}

Теперь весь код сводиться к циклу, который перебирает всех людей из модели и для каждого человека вызывается отображение частичного представления – мы встраиваем его в текущую позицию с помощью:

@Html.Partial("_Item", p);

Первый параметр – это имя файла, а второй – модель типа Person. Именно ее же ожидает наше представление.

Преимущество заключается в том, что теперь _Item работает как виджет. Мы можем отображать его на любой странице сайта, вызывать его откуда угодно. И если в определенный момент захочется поменять внешний вид этого виджета (карточки человека), то достаточно поменять ее в файле _Item.cshtml и изменения вступят в силу везде.

Кстати, использование метода Partial немного старый подход и сейчас MS рекомендует использовать асинхронную версию PartialAsync, которая защищена от блокировок.

@await Html.PartialAsync("_Item", p) 

Первая версия тоже будет работать, просто во время компиляции будет отображаться предупреждение и это предупреждение дается не просто так, используйте асинхронную версию.

Есть еще пара методов RenderPartial и RenderPartialAsync. Отличие этих двух версий в том, что они вызывают отрисовку представления, но при этом не возвращают его в качестве результата, а отображают его.

Посмотрим на следующие два примера:

    @await Html.PartialAsync("_Item",  new MyWebSite.Model.Person()  {  FirstName = "Михаил",  LastName = "Фленов"  })     @{         await Html.RenderPartialAsync("_Item",  new MyWebSite.Model.Person()  {  FirstName = "Михаил",  LastName = "Фленов"  });     }

В первом случае вызывается метод PartialAsync, который возвращает результат отрисовки и мы его отображаем за счет того, что ставим впереди символ @. Точно так же мы отображаем и имя, когда пишем @Model.FirstName. Одиночный символ @ как раз используется для отображения.

Второй метод RenderPartialAsync ничего не возвращает, поэтому нельзя написать:

@await Html.RenderPartialAsync(. . . . 

Этот финт закончится ошибкой. Вместо этого я перехожу в режим кода @{, потом вызываю RenderPartialAsync который ничего не вернет, но зато отобразит.

Как можно использовать эту разницу? Допустим, что вы хотите вызвать представление, но не хотите его отображать в текущей позиции, а сохранить результат и потом еще и обработать. Такое возможно:

    @{
        var result = Html.Partial("_Item", 
           new MyWebSite.Model.Person() 
           { 
             FirstName = "Михаил", 
             LastName = "Фленов" 
           });
    }

Здесь мы не отображаем представление, а вызываем его и результат рендеринга сохраняем в переменной result. Теперь эту переменную можно как-то еще обработать, передать кому-нибудь или даже просто отобразить, если написать @result.

Мне сначала казалось, что тема достаточно простая и я ее раскидаю быстро, но получилось уже аж на три страницы Word, поэтому закругляюсь до следующей главы, постараюсь написать на следующей неделе.

Скачать исходники этой главы

Предыдущая глава

4.2. Специальные файлы _ViewStart

О блоге

Программист, автор нескольких книг серии глазами хакера и просто блогер. Интересуюсь безопасностью, хотя хакером себя не считаю

Обратная связь

Без проблем вступаю в неразборчивые разговоры по e-mail. Стараюсь отвечать на письма всех читателей вне зависимости от страны проживания, вероисповедания, на русском или английском языке.

Пишите мне