Компоненты представлений в ASP.NET Core MVC. Вывод результатов компонента (IViewComponentResult)

До сих пор мы использовали компоненты представлений, которые в качестве результата выводили обычную строку string, что, строго говоря, не совсем корректно. Обычно, в качестве результата метода Invoke()/InvokeAsync() возвращается объект, реализующий интерфейс IViewComponentResult или, в случае использования асинхронного метода, Task<IViewComponentResult>. Здесь можно провести аналогию с контроллерами — технически, действие контроллера может возвращать и обычные строки, однако на практике контроллеры всё же возвращают один из объектов, реализующих IActionResult.  Сегодня рассмотрим варианты использования классов, реализующих этот интерфейс для вывода результатов компонента представлений.

IViewComponentResult

В ASP.NET Core MVC содержатся три готовых класса, реализующих интерфейс IViewComponentResult:

  • ViewComponentResult этот класс используется для генерации представления Razor с возможностью передачи модели. Этот класс мы рассмотрим отдельно в одной из следующих частей.
  • ContentViewComponentResult— используется для отправки обычного текста, а для создания объекта этого класса может использоваться метод Content()
  • HtmlContentViewComponentResult— используется для вставки HTML-кода в веб-станицу.

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

namespace AspNetMvcComponents.Components
{
    public class DayInfoOptions
    {
        public string StartString { get; set; } = string.Empty;
        public bool FullName {  get; set; } = true;
    }

    public class DayInfoViewComponent
    {
        readonly ILogger<DayInfoViewComponent> _logger;
        
        public DayInfoViewComponent(ILogger<DayInfoViewComponent> logger)
        {
            _logger = logger;
        }
        public string Invoke(DayInfoOptions options)
        {
            _logger.LogInformation($"Вызван метод Invoke компонента DayInfo");
            
            string content = options?.StartString ?? string.Empty;
            if ((options != null)&&(options.FullName == false))
            {
                return $"{content} {DateTime.Now:ddd}";
            }
            else
            {
                return $"{content} {DateTime.Now:dddd}";
            }
            
        }
    }
}

ViewComponentResult

Объекты этого класса возвращают обычный текст. Чтобы им воспользоваться внесем в класс компонента следующие изменения:

public class DayInfoViewComponent
{
    readonly ILogger<DayInfoViewComponent> _logger;

    public DayInfoViewComponent(ILogger<DayInfoViewComponent> logger)
    {
        _logger = logger;
    }
    public IViewComponentResult Invoke(DayInfoOptions options)
    {
        _logger.LogInformation($"Вызван метод Invoke компонента DayInfo");

        string content = options?.StartString ?? string.Empty;
        if ((options != null) && (options.FullName == false))
        {
            content = $"{content} {DateTime.Now:ddd}";
        }
        else
        {
            content = $"{content} {DateTime.Now:dddd}";
        }
        return new ContentViewComponentResult(content);
    }
}

Здесь мы, по ути, поменяли только тип возвращаемого результата методом Invoke() со string на IViewComponentResult. Соответственно, и в самом методе мы передаем не строку, а новый объект типа ContentViewComponentResult:

return new ContentViewComponentResult(content);

В остальном, работа компонента будет такая же, как и была раньше — на главной странице приложения появится информация о дне недели:

@addTagHelper *, AspMvcComponents
@using AspMvcComponents.Components

<vc:day-info options="@(new DayInfoOptions(){StartString="День недели:", FullName=true})">
</vc:day-info>

 

Для того, чтобы воспользоваться методом Content() для создания объекта типа ContentViewComponentResult необходимо, чтобы наш компонент был наследником класса ViewComponent. Воспользуемся этим методом, а, заодно, немного сократим код нашего компонента:

public class DayInfo: ViewComponent
{
    readonly ILogger<DayInfo> _logger;

    public DayInfo(ILogger<DayInfo> logger)
    {
        _logger = logger;
    }
    public IViewComponentResult Invoke(DayInfoOptions options)
    {
        _logger.LogInformation($"Вызван метод Invoke компонента DayInfo");

        string content = options?.StartString ?? string.Empty;
        if ((options != null) && (options.FullName == false))
        {
            content = $"{content} {DateTime.Now:ddd}";
        }
        else
        {
            content = $"{content} {DateTime.Now:dddd}";
        }
        return Content(content);
    }
}

В принципе, можно было бы не менять название компонента, но зачем нам лишний текст? ASP.NET Core MVC и так прекрасно поймет, что DayInfo — это компонент ViewComponent. Опять же, на результат вызова компонента в приложении это никак не повлияет.

HtmlContentViewComponentResult

Объекты этого класса возвращают HTML-содержимое. В отличие от предыдущего класса, для создания объектов типа HtmlContentViewComponentResult у базового класса ViewComponent не предусмотрено специальных методов. Однако, проблем из-за этого не возникает. Перепишем код метода Invoke() следующим образом:

public class DayInfo: ViewComponent
{
    readonly ILogger<DayInfo> _logger;

    public DayInfo(ILogger<DayInfo> logger)
    {
        _logger = logger;
    }
    public IViewComponentResult Invoke(DayInfoOptions options)
    {
        _logger.LogInformation($"Вызван метод Invoke компонента DayInfo");

        string content = options?.StartString ?? string.Empty;
        if ((options != null) && (options.FullName == false))
        {
            content = $"<b>{content}</b> <span style=\"color:red\">{DateTime.Now:ddd}</span>";
        }
        else
        {
            content = $"<b>{content}</b> <span style=\"color:red\">{DateTime.Now:dddd}</span>";
        }
        return new HtmlContentViewComponentResult(new HtmlString(content));
    }
}

Конструктор HtmlContentViewComponentResult в качестве параметра принимает объект класса, реализующего интерфейс IHtmlContent. Одним из таких классов является класс HtmlString, объект которого мы и передаем в конструктор. В итоге, после запуска приложения мы увидим следующий результат:

Итого

Несмотря на то, что методы Invoke() и InvokeAsync() могут возвращать результат любого типа, для генерации контента желательно использовать классы, реализующие интерфейс IViewComponentResult. В ASP.NET Core MVC такими классами являются ViewComponentResult , ContentViewComponentResult и HtmlContentViewComponentResult.

Подписаться
Уведомить о
guest
0 Комментарий
Старые
Новые Популярные
Межтекстовые Отзывы
Посмотреть все комментарии