View Component

Определение компонента представлений

Последнее обновление: 06.04.2022

View Component или компонент представлений представляет код, который объединяет логику на языке C# и связанную с ней разметку razor и который решает какую-то определенную задачу, например, создание динамических меню, облако тегов, панель входа на сайт, корзина покупок и так далее.

View Component состоит из двух частей: класса на C# и частичного представления, которое вызывает методы этого класса. При этом View Component не может обрабатывать HTTP-запросы, а генерируемый им контент включается в код родительского представления, в котором вызывается компонент.

View Component поддерживает внедрение зависимостей, поэтому в коде view component можно получить зависимости из провайдера сервисов. В то же время комопонент не является частью жизненного цикла контроллера, поэтому к нему нельзя применять фильтры.

Есть три способа определения компонента:

  • определение компонента как обычного класса (класс POCO)

  • наследование от базового класса ViewComponent

  • применение к классу атрибута [ViewComponent]

Для работы с компонентами представлений создадим новый проект ASP.NET Core по типу ASP.NET Core Web App (Model-View-Controller).

Определение View Component

Компонент как обычный класс

Теоретически классы компонентов могут размещаться в любой папке проекта. Однако как правило, для компонентов создается отдельная папка Components или ViewComponents. Поэтому добавим в проект папку с названием Components. Далее добавим в нее новый класс, который назовем TimerViewComponent:

namespace MvcApp.Components
{
    public class TimerViewComponent
    {
        public string Invoke()
        {
            
            return $"Текущее время: {DateTime.Now.ToString("hh:mm:ss")}";
        }
    }
}

Подобно контроллерам view component должен представлять класс с модификатором public. Кроме того, класс компонента не должен быть вложенным или абстрактным.

При определении компонента в виде обычного класса C# название этого класса должно оканчиваться на суффикс ViewComponent, плюс в самом классе должен быть определен метод Invoke() (если он должен выполнять действия в синхронном режиме) или InvokeAsync (если он должен выполнять действия асинхронно).

В данном случае в коде компонента в методе Invoke возвращается текущее время в виде простой строки.

Наследование класса ViewComponent

Второй способ создания компонента связан с наследованием от базового класса ViewComponent из пространства имен Microsoft.AspNetCore.Mvc. Так, перепишем предыдущий код компонента следующим образом:

using Microsoft.AspNetCore.Mvc;
namespace MvcApp.Components
{
    public class Timer : ViewComponent
    {
        public string Invoke()
        {
            return $"Текущее время: {DateTime.Now.ToString("hh:mm:ss")}";
        }
    }
}

Фактически здесь только было добавлено наследование, а в названии класса убран суффикс "ViewComponent". Остальной код остался прежним.

Применение атрибута ViewComponent

Третий способ представляет применение атрибута ViewComponent. Для его использования уберем наследование и добавим атрибут:

using Microsoft.AspNetCore.Mvc;
namespace MvcApp.Components
{
    [ViewComponent]
    public class Timer
    {
        public string Invoke()
        {
            return $"Текущее время: {DateTime.Now.ToString("HH:mm:ss")}";
        }
    }
}

Применение View Component

Теперь мы можем использовать компонент. При этом его использование не зависит от способа его определения. Есть два способа применения компонента в представлении.

Метод Component.InvokeAsync

Пусть у нас в проекте в папке Controllers есть контроллер HomeController. И, кроме того, в проекте для представлений этого контроллера определена папка Views/Home, в котором находится представление Index.cshtml.

view components в asp.net core mvc и c#

Теперь добавим в представление Index.cshtml вызов определенного выше компонента TimerViewComponent:

@await Component.InvokeAsync("Timer")

В качестве параметра в метод InvokeAsync() передается название компонента. В нашем случае это "Timer". При этом не важно, какой из трех вышеописанных способов определения компонента мы используем. Если компонент определен как класс TimerViewComponent, то именем считается так часть названия класса, которая идет до суффикса ViewComponent, то есть "Timer". В осталных случаях используется имя класса.

В итоге при запуске приложения вместо кода компонента мы увидим его вывод - текущее время:

Определение и вызов компонента представлений ViewComponent в ASP.NET Core MVC и C#

Tag-хелпер vc

Также мы можем встраивать комопонент с помощью тег-хелпера vc в формате

<vc:[имя_компонента]></vc:[имя_компонента]>

В нашем случае имя комопонента - "Timer", поэтому чтобы обратиться к компоненту в представлении, можно использовать следующую разметку

<vc:timer></vc:timer>

или так

<vc:timer />

Однако перед использованием тега нобходимо зарегистрировать наш компонент в представлении качестве tag-хелпера с помощью директивы @addTagHelper:

@addTagHelper *, [Название_сборки_проекта]

Название сборки проекта как правило совпадает с названием самого проекта. То есть в моем случае применение компонента в представлении выглядело бы следующим образом:

@addTagHelper *, MvcApp

<vc:timer />

Чтобы подключить компонент сразу во все представления, можно добавить данную директиву в в файл _ViewImports.cshtml

Асинхронные операции и метод InvokeAsync

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

Для примера возьмем асинхронное считывание из файла. Для этого определим в проекте папку Files, а в нее добавим текстовый файл header.txt с каким-нибудь простеньким кодом:

Hello METANIT.COM

Далее добавим в проект в папку Components новый компонент Header со следующим кодом:

using Microsoft.AspNetCore.Mvc;

namespace MvcApp.Components
{
    public class Header : ViewComponent
    {
        public async Task<string> InvokeAsync()
        {
            using (StreamReader reader = new StreamReader("Files/header.txt"))
            return await reader.ReadToEndAsync();
        }
    }
}
асинхронные операции в View Component в ASP.NET Core MVC и C#

Метод InvokeAsync() помечается с помощью ключевого слова async и содержит выражение await - await reader.ReadToEndAsync(). Считанное содержимое затем возвращается из метода в виде строки.

Определим вызов компонента Header в представлении Index.cshtml:

<h2>@await Component.InvokeAsync("Header")</h2>

или так

@addTagHelper *, MvcApp

<h2><vc:header /></h2>

Запустим на выполнение и увидим вставку на веб-станицу кода из файла header.txt:

асинхронные операции и метод InvokeAsync в ViewComponent в ASP.NET Core MVC и C#

При определении метода надо учитывать, что в компоненте должен быть только один метод, который называется Invoke или InvokeAsync. Если в дополнение к InvokeAsync мы определим синхронный метод Invoke, то в этом случае мы получим ошибку, так как движок представлений не будет знать, какой метод выбрать для обработки.

Помощь сайту
Юмани:
410011174743222
Перевод на карту
Номер карты:
4048415020898850