В зависимости от сложности проекта можно использовать одну и ту же модель для хранения данных в базе данных, для передачи данных в представление и получения данных из представления. Однако нередко все же модели могут не совпадать. Например, нам не надо передавать в представление все данные определенной модели или надо передать в представление объекты сразу двух моделей. И в этом случае мы можем воспользоваться моделями представления.
Рассмотрим простейший пример работы с моделями. Допустим, в проекте в папке 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 - компанию, где они работают.
И, допустим, нам надо выводить на страницу список пользователей и фильтровать их по компаниям. Наподобие следующего:
Очевидно, что этих двух моделей - 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>
В итоге проект будет иметь следующую структуру:
И теперь у нас получится веб-страница, как на первом скриншоте, на которой используется фильтрация.
В данном случае продемонстрирован наглядный пример, где с помощью только одной простой моделей типа Person и Company было бы сложно передать данные. И поэтому было бы более оптимально прибегнуть к комплексной модели представления (IndexViewModel).