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

Данное руководство устарело. Актуальное руководство: Руководство по ASP.NET Core 7

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

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

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

Модели в ASP.NET MVC Core

Возьмем проект из прошлой темы, где создавались модели 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; }
}

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

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

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

Теперь изменим код в 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).

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