Модели представления View Model

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

В зависимости от сложности проекта можно использовать одну и ту же модель для хранения данных в базе данных, для передачи данных в представление и получения данных из представления. Однако нередко все же модели могут не совпадать. Например, нам не надо передавать в представление все данные определенной модели или надо передать в представление объекты сразу двух моделей. И в этом случае мы можем воспользоваться моделями представления.

Рассмотрим простейший пример работы с моделями. Допустим, в проекте в папке Model у нас есть следующие модели Person и Company.

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

Модель Person представляет пользователей, а модель Company - компанию, где они работают.

И, допустим, нам надо выводить на страницу список пользователей и фильтровать их по компаниям. Наподобие следующего:

Модели представления view models в ASP.NET Core MVC и C#

Очевидно, что этих двух моделей - Person и Company для решения поставленной задачи нам недостаточно. И нам надо создать специальную модель для передачи данных в представление или модель представления (иными словами View Model). Для этого вначале добавим в проект новую папку ViewModels. В принципе модели представлений не обязательно определять именно в папке ViewModels, это может быть любая папка, в том числе и имеющаяся по умолчанию папка Models. Далее в каталог ViewModels поместим модель CompanyModel:

namespace MvcApp.ViewModels
{
    public record class CompanyModel(int Id, string Name);
}

Эта модель упрощает передачу списка компаний в представление.

И также добавим в папку ViewModels собственно модель представления, которую назовем IndexViewModel:

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

namespace MvcApp.ViewModels
{
    public class IndexViewModel
    {
        public IEnumerable<Person> People { get; set; } = new List<Person>();
        public IEnumerable<CompanyModel> Companies { get; set; } = new List<CompanyModel>();
    }
}

С помощью этой модели мы сможем передать в представление сразу и список компаний, и список пользователей.

Далее в проекте в папке Controllers определим следующий контроллер HomeController:

using Microsoft.AspNetCore.Mvc;
using MvcApp.Models; // пространство имен модели Person и Company
using MvcApp.ViewModels;    // пространство имен модели IndexViewModel и CompanyModel

namespace MvcApp.Controllers
{
    public class HomeController : Controller
    {
        List<Person> people;
        List<Company> companies;
        public HomeController()
        {
            Company microsoft = new Company(1, "Microsoft", "USA");
            Company google = new Company(2, "Google", "USA");
            Company jetbrains = new Company(3, "JetBrains", "Czech Republic");
            companies = new List<Company> { microsoft, google, jetbrains};

            people = new List<Person>
            {
                new Person(1, "Tom", 37, microsoft),
                new Person(2, "Bob", 41, microsoft),
                new Person(3, "Sam", 28, google),
                new Person(4, "Bill", 32, google),
                new Person(5, "Kate", 33, jetbrains),
                new Person(6, "Alex", 25, jetbrains),
            };
        }
        public IActionResult Index(int? companyId)
        {
            // формируем список компаний для передачи в представление
            List<CompanyModel> compModels = companies
                .Select(c => new CompanyModel(c.Id, c.Name)).ToList();
            // добавляем на первое место
            compModels.Insert(0, new CompanyModel(0, "Все"));

            IndexViewModel viewModel = new() { Companies = compModels, People = people };

            // если передан id компании, фильтруем список
            if (companyId != null && companyId > 0)
                viewModel.People = people.Where(p => p.Work.Id == companyId);

            return View(viewModel);
        }
    }
}

В метод Index передается опциональный параметр companyId, который передает идентификатор выбранной компании. Если он не равен 0 и определен, то производим фильтрацию по компаниям.

И в конце определим в проекте в папке Views/Home представление Index.cshtml, которое будет выводить все объекты:

@using MvcApp.ViewModels
@using MvcApp.Models
@model IndexViewModel

<style>
td{padding:5px;}
tr:nth-child(even) {background: #CCC}
tr:nth-child(odd) {background: #FFF}
</style>

<form>
    <label>Выберите компанию:</label>
    <select name="companyId" >
        @foreach(CompanyModel comp in Model.Companies)
        {
            <option value="@comp.Id">@comp.Name</option>
        }
    </select>
    <input type="submit" />
</form>
<br />
<table>
    <tr><td>Name</td><td>Company</td><td>Age</td></tr>
    @foreach (Person p in Model.People)
    {
        <tr><td>@p.Name</td><td>@p.Work.Name</td><td>@p.Age</td></tr>
    }
</table>

В итоге проект будет иметь следующую структуру:

Добавление моделей представлений в ASP.NET Core MVC и C#

И теперь у нас получится веб-страница, как на первом скриншоте, на которой используется фильтрация.

В данном случае продемонстрирован наглядный пример, где с помощью только одной простой моделей типа Person и Company было бы сложно передать данные. И поэтому было бы более оптимально прибегнуть к комплексной модели представления (IndexViewModel).

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