Передача данных во View Component

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

View Component может извне получаит различные данные. Во-первых, View Component может принимать некоторые параметры, которые ему передаются при вызове компонента. Во-вторых, класс View Component, также как и другие классы в ASP.NET Core, может получать зависимости из провайдера сервисов через механизм dependency injection. Рассмотрим, оба случая передачи данных.

Передача параметров в View Component

Через параметры метода Invoke/InvokeAsync мы можем получать извне некоторые данные. Например, определим следующий компонент:

using Microsoft.AspNetCore.Mvc;

namespace MvcApp.Components
{
    [ViewComponent]
    public class Timer
    {
        public string Invoke(bool includeSeconds)
        {
            if (includeSeconds)
                return $"Текущее время: {DateTime.Now.ToString("hh:mm:ss")}";
            else
                return $"Текущее время: {DateTime.Now.ToString("hh:mm")}";
        }
    }
}

В методе Invoke компонент принимает один параметр - includeSeconds, который представляет тип bool. Если этот параметр равен true, то строка со временем также содерджит секунды, если параметр равен false - секунды опускаются.

Теперь обратимся к этому компоненту в представлении:

@addTagHelper *, MvcApp

<p>С секундами: <br />
    @await Component.InvokeAsync("Timer", new { includeSeconds=true})
</p>

<p>Без секунд: <br />
    <vc:timer include-seconds="false"></vc:timer>
</p>

Для передачи значений параметрам метода Invoke/InvokeAsync в методе Component.InvokeAsync() в качестве второго аргумента указывается анонимный объект, который устанавливает значения всех параметров.

При использовании тег-хелпера параметры компонента определяются как атрибуты тега, которым присваивается необходимое значение. Причем если у нас исползуется camelcase, при котором каждое подслово в составе составного слова пишется с большой буквы, например, includeSeconds, то в названии атрибута все подслова разделяются дефисом и начинаются со строчной буквы.

Результат выполнения:

Параметры в View Component в ASP.NET Core MVC и C#

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

using Microsoft.AspNetCore.Mvc;

namespace MvcApp.Components
{
    [ViewComponent]
    public class Timer
    {
        public string Invoke(bool includeSeconds, bool format24)
        {
            string time;
            DateTime now = DateTime.Now;

            if (format24)   // если 24-часовой формат
                time = now.ToString("HH:mm");
            else           // если 12-часовой формат
                time = now.ToString("hh:mm");

            if (includeSeconds) // если надо добавить секунды
                time = $"{time}:{now.Second}";

            return $"Текущее время: {time}";
        }
    }
}

Новый параметр format24 указывает в каком формате будет выводиться время - в 24-часовом или в 12 часовом.

Обратимся к компоненту в представлении:

@addTagHelper *, MvcApp

<p>24 часовой формат с секундами: <br />
    @await Component.InvokeAsync("Timer", new { includeSeconds=true, format24=true})
</p>

<p>12 часовой формат без секунд: <br />
    <vc:timer include-seconds="false"  format24="false"></vc:timer>
</p>
<p>
    24 часовой формат без секунд: <br />
    <vc:timer include-seconds="false" format24="true"></vc:timer>
</p>
Передача параметров в компонент представления View Component в ASP.NET Core MVC и C#

При необходимости для параметров во View Component можно устанавить значения по умолчанию:

using Microsoft.AspNetCore.Mvc;

namespace MvcApp.Components
{
    [ViewComponent]
    public class Timer
    {
        public string Invoke(bool includeSeconds = false, bool format24 = true)
        {
            string time;
            DateTime now = DateTime.Now;

            if (format24)   // если 24-часовой формат
                time = now.ToString("HH:mm");
            else           // если 12-часовой формат
                time = now.ToString("hh:mm");

            if (includeSeconds) // если надо добавить секунды
                time = $"{time}:{now.Second}";

            return $"Текущее время: {time}";
        }
    }
}

То есть по умолчанию применяется 24-часовой формат, а секунды не включаются.

Попробуем при обращении к компоненту опустить некоторые параметры (ведь теперь они имеют значения по умолчанию):

<p>
    Все значения по умолчанию: <br />
    @await Component.InvokeAsync("Timer")
</p>
<p>
    12-часовой формат: <br />
    @await Component.InvokeAsync("Timer", new { format24 = false })
</p>
<p>
    С секундами: <br />
    @await Component.InvokeAsync("Timer", new { includeSeconds = true })
</p>
Значения по умолчанию для параметров в View Component в ASP.NET Core

Передача сложных данных в View Component

При этом View Component может принимать более сложные данные. Например, определим в проекте папку Models следующий класс Person:

namespace MvcApp.Models
{
    public record class Person(string Name, int Age);
}

В папке Components определим новый View Component - класс PersonInfoViewComponent:

using MvcApp.Models; // пространство имен класса Person

namespace MvcApp.Components
{
    public class PersonInfoViewComponent
    {
        public string Invoke(Person Person)
        {
            return $"Name: {Person.Name}  Age: {Person.Age}";
        }
    }
}

Данный компонент принимает объкт Person и возвращает его данные в виде строки.

Теперь применим данный компонент в представлении:

@addTagHelper *, MvcApp

@using MvcApp.Models <!-- пространство имен модели Person-->
 
@{
    Person tom = new("Tom", 37);
    Person alice = new("Alice", 32);
}
<p>
    @await Component.InvokeAsync("PersonInfo", new { person = tom})
</p>
<p>
    <vc:person-info person="alice"></vc:person-info>
</p>

Результат работы приложения:

Передача сложных данных в View Component в ASP.NET Core MVC и C#

Внедрение зависимостей

Как и другие классы, View Component может получать внеденные в приложение зависимости.

Например, в файле Program.cs определен следующий код:

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddTransient<ITimeService, SimpleTimeService>();

builder.Services.AddControllersWithViews();
var app = builder.Build();
app.MapControllerRoute(
	name: "default",
	pattern: "{controller=Home}/{action=Index}/{id?}");

app.Run();

public interface ITimeService
{
    string GetTime();
}
public class SimpleTimeService : ITimeService
{
    public string GetTime() => DateTime.Now.ToString("HH:mm:ss");
}

Здесь добавляется сервис ITimeService в виде класса SimpleTimeService.

Используем этот сервис и для этого изменим код компонента Timer:

using Microsoft.AspNetCore.Mvc;

namespace MvcApp.Components
{
    [ViewComponent]
    public class Timer
    {
        ITimeService timeService;
        public Timer(ITimeService service)
        {
            timeService = service;
        }
        public string Invoke()
        {
            return $"Текущее время: {timeService.GetTime()}";
        }
    }
}

При запуске приложения и вызове компонента ему автоматически будет передаваться нужный объект ITimeService. И также в представлении мы сможем его использовать:

@addTagHelper *, MvcApp

<div>
    @await Component.InvokeAsync("Timer")
</div>
<div>
    <vc:timer />
</div>
Помощь сайту
Юмани:
410011174743222
Перевод на карту
Номер карты:
4048415020898850