Данное руководство устарело. Актуальное руководство: Руководство по ASP.NET Core 7
Приложения на ASP.NET MVC бывают разными: маленькими, большими, простыми, либо со сложной логикой. И в зависимости от сложности проекта мы можем использовать одну и ту же модель для хранения данных в базе данных, для передачи данных в представление и получения данных из представления. Однако нередко все же модели могут не совпадать. Например, нам не надо передавать в представление все данные определенной модели или надо передать в представление объекты сразу двух моделей. И в этом случае мы можем воспользоваться моделями представления.
Рассмотрим простейший пример работы с моделями. Допустим, нам надо выводить на страницу список смартфонов и фильтровать их по компаниям. Наподобие следующего:
Возьмем проект из прошлой темы, где создавались модели Phone и Company.
public class Company { public int Id { get; set; } public string Name { get; set; } public string Country { get; set; } } public class Phone { public int Id { get; set; } public string Name { get; set; } public Company Manufacturer { get; set; } public decimal Price { get; set; } }
Но если вернуться к скриншоту веб-страницы, которую нам надо сделать, то там есть не просто список смартфонов, но и список компаний, причем в списке компаний имеется дополнительный элемент, позволяющий выбрать смартфоны всех компаний.
Очевидно, что этих двух моделей - Phone и Company для решения поставленной задачи нам недостаточно. И нам надо создадить специальную модель для передачи данных в представление или модель представления (иными словами View Model). Для этого вначале добавим в проект новую папку ViewModels. В принципе модели представлений не обязательно определять именно в папке ViewModels, это может быть любая папка, в том числе и имеющаяся по умолчанию папка Models. Далее в каталог ViewModels поместим модель CompanyModel:
public class CompanyModel { public int Id { get; set; } public string Name { get; set; } }
Эта модель упрощает передачу списка компаний в представление.
И также добавим в ViewModels собственно модель представления, которую назовем IndexViewModel:
using ModelsApp.Models; using System.Collections.Generic; public class IndexViewModel { public IEnumerable<Phone> Phones { get; set; } public IEnumerable<CompanyModel> Companies { get; set; } }
С помощью этой модели мы сможем передать в представление сразу и список компаний, и список смартфонов.
В итоге проект будет иметь следующую структуру:
Теперь изменим код в HomeController следующим образом:
using System.Collections.Generic; using System.Linq; using Microsoft.AspNetCore.Mvc; using ModelsApp.Models; // пространство имен моделей using ModelsApp.ViewModels; // пространство имен моделей представлений namespace ModelsApp.Controllers { public class HomeController : Controller { List<Phone> phones; List<Company> companies; public HomeController() { Company apple = new Company { Id = 1, Name = "Apple", Country = "США" }; Company microsoft = new Company { Id = 2, Name = "Samsung", Country = "Республика Корея" }; Company google = new Company { Id = 3, Name = "Google", Country = "США" }; companies = new List<Company> { apple, microsoft, google }; phones = new List<Phone> { new Phone { Id=1, Manufacturer= apple, Name="iPhone X", Price=56000 }, new Phone { Id=2, Manufacturer= apple, Name="iPhone XZ", Price=41000 }, new Phone { Id=3, Manufacturer= microsoft, Name="Galaxy 9", Price=9000 }, new Phone { Id=4, Manufacturer= microsoft, Name="Galaxy 10", Price=40000 }, new Phone { Id=5, Manufacturer= google, Name="Pixel 2", Price=30000 }, new Phone { Id=6, Manufacturer= google, Name="Pixel XL", Price=50000 } }; } public IActionResult Index(int? companyId) { // формируем список компаний для передачи в представление List<CompanyModel> compModels = companies .Select(c => new CompanyModel { Id = c.Id, Name = c.Name }) .ToList(); // добавляем на первое место compModels.Insert(0, new CompanyModel { Id = 0, Name = "Все" }); IndexViewModel ivm = new IndexViewModel { Companies = compModels, Phones = phones }; // если передан id компании, фильтруем список if (companyId != null && companyId > 0) ivm.Phones = phones.Where(p => p.Manufacturer.Id == companyId); return View(ivm); } } }
В метод Index передается опциональный параметр companyId
, который передает идентификатор выбранной компании. Если он не равен 0 и определен, то производим фильтрацию по компаниям.
И в конце изменим представление Index.cshtml, которое будет выводить все объекты:
@using ModelsApp.ViewModels @using ModelsApp.Models @model IndexViewModel @{ ViewData["Title"] = "Home Page"; } <form class="form-inline"> <label>Выберите компанию:</label> <select name="companyId" class="form-control"> @foreach(CompanyModel comp in Model.Companies) { <option value="@comp.Id">@comp.Name</option> } </select> <input type="submit" /> </form> <br /> <table class="table"> @foreach (Phone p in Model.Phones) { <tr><td>@p.Name</td><td>@p.Manufacturer?.Name</td><td>@p.Price</td></tr> } </table>
И теперь у нас получится веб-страница, как на первом скриншоте, на которой используется фильтрация.
В данном случае продемонстрирован наглядный пример, где с помощью только одной простой моделей типа Phone и Company было бы сложно передать данные. И поэтому было бы более оптимально прибегнуть к комплексной модели представления (IndexViewModel).