Вопрос по asp.net-mvc, viewmodel – Что такое ViewModel в MVC?

379

Я новичок в ASP.NET MVC. У меня есть проблема в понимании цели ViewModel.

Что такое ViewModel и зачем нам нужна ViewModel для приложения ASP.NET MVC?

Будет лучше, если я приведу простой пример.

Этот пост - то, что вы ищете - & quot; Что такое ASP.NET MVC ViewModel? & Quot; EL Yusubov
возможный дубликатIn MVC, what is a ViewModel? rogerdeuce
Эта статья выглядит великолепно:rachelappel.com/… Andrew

Ваш Ответ

12   ответов
14

но в каждом ответе, похоже, отсутствует одна концепция, которая действительно помогла мне "получить ее" ...

Если модель похожа на базу данныхTableто ViewModel сродни базе данныхView - Представление обычно либо возвращает небольшие объемы данных из одной таблицы, либо сложные наборы данных из нескольких таблиц (объединений).

Я использую ViewModels для передачи информации в представление / форму, а затем переношу эти данные в допустимую модель, когда форма отправляет обратно в контроллер, что также очень удобно для хранения списков (IEnumerable).

73

Edit: I updated this answer on my Blog:

http://www.samwheat.com/Post/The-function-of-ViewModels-in-MVC-web-development

Мой ответ немного длинен, но я думаю, что важно сравнить модели представления с другими типами часто используемых моделей, чтобы понять, почему они отличаются и почему они необходимы.

Подводя итог, и прямо ответить на вопрос, который задают:

Вообще говоря, модель представления - это объект, который содержит все свойства и методы, необходимые для визуализации представления. Свойства модели представления часто связаны с объектами данных, такими как клиенты и заказы, и, кроме того, они также содержат свойства, связанные с страницей или самим приложением, такие как имя пользователя, имя приложения и т. Д. Модели представления предоставляют удобный объект для передачи в механизм рендеринга для создать HTML-страницу. Одна из многих причин использования модели представления заключается в том, что модели представления предоставляют способ для модульного тестирования определенных задач представления, таких как обработка пользовательского ввода, проверка данных, получение данных для отображения и т. Д.

Вот сравнение моделей Entity (например, моделей DTO и моделей), моделей презентаций и моделей представлений.

Data Transfer Objects a.k.a “Model”

Объект передачи данных (DTO) - это класс со свойствами, которые соответствуют схеме таблицы в базе данных. DTO-ы названы в честь их общего использования для передачи данных в и из хранилища данных.
Характеристики DTO-ов:

& # X2022; Являются ли бизнес-объектами & # x2013; их определение зависит от данных приложения.

& # X2022; Обычно содержат только свойства & # x2013; нет кода

& # X2022; В основном используется для передачи данных в базу данных и из нее.

& # X2022; Свойства точно или близко соответствуют полям определенной таблицы в хранилище данных.

Таблицы базы данных обычно нормализуются, поэтому обычно также нормализуются DTO. Это делает их ограниченным использованием для представления данных. Однако для некоторых простых структур данных они часто работают достаточно хорошо.

Вот два примера того, как могут выглядеть DTO:

public class Customer
{
    public int ID { get; set; }
    public string CustomerName { get; set; }
}


public class Order
{
    public int ID { get; set; }
    public int CustomerID { get; set; }
    public DateTime OrderDate { get; set; }
    public Decimal OrderAmount { get; set; }
}

& # X2003;

Presentation Models

Модель презентации - этоutility класс, который используется для отображения данных на экране или в отчете. Модели представления обычно используются для моделирования сложных структур данных, которые состоят из данных из нескольких DTO. Модели представления часто представляют денормализованное представление данных.

Характеристики презентационных моделей:

& # X2022; Являются ли бизнес-объектами & # x2013; их определение зависит от данных приложения.

& # X2022; Содержат в основном свойства. Код обычно ограничен форматированием данных или преобразованием в или из DTO. Модели презентаций не должны содержать бизнес-логики.

& # X2022; Часто присутствует денормализованное представление данных. То есть они часто объединяют свойства из нескольких DTO.

& # X2022; Часто содержат свойства другого базового типа, чем DTO. Например, суммы в долларах могут быть представлены в виде строк, поэтому они могут содержать запятые и символ валюты.

& # X2022; Часто определяется тем, как они используются, а также их объектными характеристиками. Другими словами, простой DTO, который используется в качестве вспомогательной модели для рендеринга сетки, фактически является также моделью представления в контексте этой сетки.

Презентационные модели используются & # x201C; при необходимости & # x201D; и & # x201C; при необходимости & # x201D; (тогда как DTO-ы обычно привязаны к схеме базы данных). Модель представления может использоваться для моделирования данных для всей страницы, сетки на странице или раскрывающегося списка сетки на странице. Модели презентаций часто содержат свойства, которые являются другими моделями презентаций. Модели презентаций часто создаются для одноразового использования, например, для визуализации конкретной сетки на одной странице.

Пример модели презентации:

public class PresentationOrder
{
    public int OrderID { get; set; }
    public DateTime OrderDate { get; set; }
    public string PrettyDate { get { return OrderDate.ToShortDateString(); } }
    public string CustomerName { get; set; }
    public Decimal OrderAmount { get; set; }
    public string PrettyAmount { get { return string.Format("{0:C}", OrderAmount); } }
}

View Models

Модель представления аналогична модели представления в том, что является базовым классом для визуализации представления. Однако это очень сильно отличается от модели представления или DTO в том, как она построена. Модели представлений часто содержат те же свойства, что и модели представления и DTO, и по этой причине их часто путают друг с другом.

Характеристики моделей просмотра:

& # X2022; Являются ли единственным источником данных, используемых для отображения страницы или экрана. Обычно это означает, что модель представления будет предоставлять все свойства, необходимые для правильной визуализации любого элемента управления на странице. Создание модели представления в качестве единственного источника данных для представления значительно улучшает его возможности и ценность для модульного тестирования.

& # X2022; Являютсяcomposite objects которые содержат свойства, которые состоят из данных приложения, а также свойств, которые используются кодом приложения. Эта характеристика имеет решающее значение при разработке модели представления для повторного использования и обсуждается в примерах ниже.

& # X2022; Содержит код приложения. Модели представления обычно содержат методы, которые вызываются во время рендеринга и когда пользователь взаимодействует со страницей. Этот код обычно относится к обработке событий, анимации, видимости элементов управления, стилям и т. Д.

& # X2022; Содержит код, который вызывает бизнес-сервисы с целью извлечения данных или отправки их на сервер базы данных. Этот код часто ошибочно помещается в контроллер. Вызов бизнес-сервисов из контроллера обычно ограничивает полезность модели представления для модульного тестирования. Чтобы было понятно, сами модели представлений не должны содержать бизнес-логику, а должны вызывать сервисы, которые содержат бизнес-логику.

& # X2022; Часто содержат свойства, которые являются другими моделями представления для других страниц или экранов.

& # X2022; Написаны & # x201C; на странице & # x201D; или & # x201C; на экран & # x201D ;. Уникальная модель представления обычно пишется для каждой страницы или экрана в приложении.

& # X2022; Обычно производные от базового класса, так как большинство страниц и экранов имеют общие свойства.

View Model Composition

Как указывалось ранее, модели представлений являются составными объектами в том смысле, что они объединяют свойства приложения и свойства бизнес-данных в одном объекте. Примеры часто используемых свойств приложения, которые используются в моделях представления:

& # X2022; Свойства, которые используются для отображения состояния приложения, такие как сообщения об ошибках, имя пользователя, состояние и т. Д.

& # X2022; Свойства, используемые для форматирования, отображения, стилизации или анимации элементов управления.

& # X2022; Свойства, используемые для привязки данных, такие как объекты списка и свойства, которые содержат промежуточные данные, вводимые пользователем.

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

Предположим, мы пишем веб-приложение. Одним из требований дизайна приложения является то, что заголовок страницы, имя пользователя и имя приложения должны отображаться на каждой странице. Если мы хотим создать страницу для отображения объекта порядка представления, мы можем изменить модель представления следующим образом:

public class PresentationOrder
{
    public string PageTitle { get; set; }
    public string UserName { get; set; }
    public string ApplicationName { get; set; }
    public int OrderID { get; set; }
    public DateTime OrderDate { get; set; }
    public string PrettyDate { get { return OrderDate.ToShortDateString(); } }
    public string CustomerName { get; set; }
    public Decimal OrderAmount { get; set; }
    public string PrettyAmount { get { return string.Format("{0:C}", OrderAmount); } }
}

Этот дизайн может работать & # x2026; но что если мы хотим создать страницу, которая будет отображать список заказов? Свойства PageTitle, UserName и ApplicationName будут повторяться и станут неудобными для работы. Кроме того, что, если мы хотим определить некоторую логику на уровне страницы в конструкторе класса? Мы больше не можем этого делать, если создадим экземпляр для каждого заказа, который будет отображаться.

Composition over inheritance

Вот способ, которым мы могли бы перефакторизовать модель представления заказа так, чтобы она стала истинной моделью представления и была бы полезна для отображения одного объекта PresentationOrder или коллекции объектов PresentationOrder:

public class PresentationOrderVM
{
    // Application properties
    public string PageTitle { get; set; }
    public string UserName { get; set; }
    public string ApplicationName { get; set; }

    // Business properties
    public PresentationOrder Order { get; set; }
}


public class PresentationOrderVM
{
    // Application properties
    public string PageTitle { get; set; }
    public string UserName { get; set; }
    public string ApplicationName { get; set; }

    // Business properties
    public List<PresentationOrder> Orders { get; set; }
}

Глядя на вышеупомянутые два класса, мы видим, что один из способов думать о модели представления - это то, что это модель представления, которая содержит другую модель представления в качестве свойства. Модель представления верхнего уровня (то есть модель представления) содержит свойства, которые относятся к странице или приложению, в то время как модель представления (свойство) содержит свойства, которые относятся к данным приложения.

Мы можем продвинуть наш дизайн дальше и создать класс модели базового представления, который можно использовать не только для PresentationOrders, но и для любого другого класса:

public class BaseViewModel
{
    // Application properties
    public string PageTitle { get; set; }
    public string UserName { get; set; }
    public string ApplicationName { get; set; }
}

Теперь мы можем упростить наш PresentationOrderVM следующим образом:

public class PresentationOrderVM : BaseViewModel
{
    // Business properties
    public PresentationOrder Order { get; set; }
}

public class PresentationOrderVM : BaseViewModel
{
    // Business properties
    public List<PresentationOrder> Orders { get; set; }
}

Мы можем сделать нашу BaseViewModel еще более пригодной для повторного использования, сделав ее универсальной:

public class BaseViewModel<T>
{
    // Application properties
    public string PageTitle { get; set; }
    public string UserName { get; set; }
    public string ApplicationName { get; set; }

    // Business property
    public T BusinessObject { get; set; }
}

Теперь наши реализации просты:

public class PresentationOrderVM : BaseViewModel<PresentationOrder>
{
    // done!
}

public class PresentationOrderVM : BaseViewModel<List<PresentationOrder>>
{
    // done!
}
Sam Благодарю вас!! это помогло мне полностью понять многогранную сущность: View-Model. Я студент колледжа, только изучающий архитектуру MVC, и это прояснило множество функциональных возможностей, которые предоставляет разработчик. Если бы я мог, я бы поставил звездочку рядом с вашим ответом.
@Сэм'View models often contain the same properties as presentation models and DTO’s and for this reason they are often confused one for the other.' Означает ли это, что они обычно используютсяinstead моделей презентации, или они должны содержать модели презентации / dtos?
Круто, Сэм! Спасибо
@Sam Предполагая, что объектами модели являются живые объекты, например nhibernate-модели ... поэтому, имея BusinessObject, мы не выставляем модели / живые объекты непосредственно на представление? то есть бизнес-объект может быть использован для непосредственного изменения состояния базы данных? Кроме того, как насчет моделей с вложенным представлением? Это потребует нескольких свойств бизнес-объекта, верно?
@AlexanderDerck Они используются для разных целей. Они перепутаны один за другим (по ошибке). Нет, вы обычно не будете использовать модель прес вместо модели вида. Гораздо более распространенным является то, что виртуальная машина "содержит" модель презентации, т.е.MyViewModel<MyPresModel>
11

у нее есть модель, представление и контроллер. Модель представления является частью MVVM (Model-View-Viewmodel). MVVM является производным от модели представления и популяризируется в WPF. В MVVM также должна быть модель, но большинство людей полностью упускают суть этого шаблона, и у них будет только представление и модель представления. Модель в MVC аналогична модели в MVVM.

В MVC процесс разделен на 3 разные обязанности:

View is responsible for presenting the data to the user A controller is responsible for the page flow A model is responsible for the business logic

MVC не очень подходит для веб-приложений. Это шаблон, представленный Smalltalk для создания настольных приложений. Веб-среда ведет себя совершенно иначе. Нет смысла копировать 40-летнюю концепцию из разработки для настольных компьютеров и вставлять ее в веб-среду. Однако многие люди считают, что это нормально, потому что их приложение компилирует и возвращает правильные значения. Это, на мой взгляд, недостаточно, чтобы объявить определенный выбор дизайна в порядке.

Примером модели в веб-приложении может быть:

public class LoginModel
{
    private readonly AuthenticationService authentication;

    public LoginModel(AuthenticationService authentication)
    {
        this.authentication = authentication;
    }

    public bool Login()
    {
        return authentication.Login(Username, Password);
    }

    public string Username { get; set; }
    public string Password { get; set; }
}

Контроллер может использовать это так:

public class LoginController
{
    [HttpPost]
    public ActionResult Login(LoginModel model)
    {
        bool success = model.Login();

        if (success)
        {
            return new RedirectResult("/dashboard");
        }
        else
        {
            TempData["message"] = "Invalid username and/or password";
            return new RedirectResult("/login");
        }
    }
}

Ваши методы контроллера и ваши модели будут небольшими, легко тестируемыми и точными.

@Sam Не все, что является частью веб-сайта, можно назвать частью MVC. Нет нового значения MVC. Существует правильное значение и «нечто совершенно не связанное, что люди путают с MVC». Сказать, что модель отвечает за бизнес-логику, не то же самое, что бизнес-логика закодирована в модели. В большинстве случаев модель выступает в роли фасада приложения.
Спасибо за понимание архитектуры MVVM, но почему MVC не в порядке? Ваши рассуждения сомнительны и подозревают в фаворитизме. Конечно, я ничего не знаю о MVVM, но если такая архитектура, как MVC, может имитировать поведение без необходимости писать 50 тыс. Строк кода, то в чём дело?
@Chef_Code: Это не вопрос или фаворитизм: просто прочитайте оригинальную статью о MVC. Возвращение к источнику гораздо лучше, чем слепое следование за стадом без вопросов (или «лучшие практики»). MVC предназначен для гораздо меньших единиц: например, Кнопка на экране состоит из модели, вида и контроллера. В Web-MVC вся страница имеет контроллер, модель и представление. Предполагается, что модель и вид связаны между собой, поэтому изменения в моделиimmediately отражается в представлении и наоборот. Подражание это очень большое дело. Архитектура не должна лгать разработчикам.
@jeroen Аббревиатура MVC была украдена и искалечена. Да, MVC не имеет виртуальной машины, но также не имеет репозитория или сервисного уровня, и эти объекты широко используются на веб-сайтах. Я полагаю, что ОП спрашивает, «как я могу ввести и использовать виртуальную машину в MVC». В новом значении MVC модель - это не то, к чему относится бизнес-логика. Бизнес-логика принадлежит сервисному слою для веб-приложений или приложений для настольных компьютеров, использующих MVC или MVVM. Термин модель описывает бизнес-объекты, которые передаются на уровень сервиса и обратно. Эти определения значительно отличаются от исходного описания MVC.
Основной недостаток, который я вижу в MVC от Microsoft, - это блокировка модели с представлением. Это само по себе противоречит всей цели всего этого разделения, которое происходило в проектах N-Tier в течение последних 20 лет. Они потратили впустую наше время, заставляя нас использовать & quot; WebForms & quot; в 2002 году, которая была еще одной вдохновленной десктопом моделью, поднятой в мир Интернета. Теперь они решили эту проблему, но снова подняли еще одну модель рабочего стола в этой новой парадигме для веб-разработчика. Тем временем Google и другие строят гигантские модели на стороне клиента, которые разделяют все это. Я думаю, что старый ASP VBScript 1998 года был их самой верной системой веб-разработки.
10

который может содержать более одного свойства класса. Мы используем его для наследования всех необходимых свойств, например, У меня есть два класса, студент и предмет

Public class Student
{
public int Id {get; set;}
public string Name {get; set;}
}  
Public class Subject
{
public int SubjectID {get; set;}
public string SubjectName {get; set;}
}

Теперь мы хотим отображать записи «Имя студента» и «Имя субъекта» в представлении (в MVC), но невозможно добавить более одного класса, такого как:

 @model ProjectName.Model.Student  
 @model ProjectName.Model.Subject

приведенный выше код выдаст ошибку ...

Теперь мы создаем один класс и можем дать ему любое имя, но этот формат & quot; XyzViewModel & quot; облегчит понять. Это концепция наследования. Теперь мы создаем третий класс со следующим именем:

public class StudentViewModel:Subject
{
public int ID {get; set;}
public string Name {get; set;}
}

Теперь мы используем эту ViewModel в View

@model ProjectName.Model.StudentViewModel

Теперь мы можем получить доступ ко всем свойствам StudentViewModel и унаследованного класса в View.

6

который исправляет концептуальную неуклюжесть инфраструктуры MVC. Он представляет 4-й уровень в 3-уровневой архитектуре Model-View-Controller. когда модель (модель предметной области) не подходит, слишком велика (больше, чем 2-3 поля) для представления, мы создаем меньшую модель представления для передачи ее в представление.

550

view model представляет данные, которые вы хотите отобразить на вашем представлении / странице, независимо от того, будут ли они использоваться для статического текста или для входных значений (таких как текстовые поля и раскрывающиеся списки), которые могут быть добавлены в базу данных (или отредактированы). Это что-то отличное от вашегоdomain model, Это модель для представления.

Допустим, у вас естьEmployee класс, представляющий модель домена вашего сотрудника и содержащий следующие свойства (уникальный идентификатор, имя, фамилия и дата создания):

public class Employee : IEntity
{
     public int Id { get; set; }

     public string FirstName { get; set; }

     public string LastName { get; set; }

     public DateTime DateCreated { get; set; }
}

Модели представлений отличаются от моделей доменов тем, что модели представлений содержат только те данные (представленные свойствами), которые вы хотите использовать в своем представлении. Например, предположим, что вы хотите добавить новую запись сотрудника, ваша модель представления может выглядеть следующим образом:

public class CreateEmployeeViewModel
{
     public string FirstName { get; set; }

     public string LastName { get; set; }
}

Как вы можете видеть, он содержит только два свойства. Эти два свойства также находятся в модели домена сотрудника. Почему это вы можете спросить?Id не может быть установлен из представления, он может быть автоматически сгенерирован таблицей Employee. А такжеDateCreated также может быть установлен в хранимой процедуре или на уровне обслуживания вашего приложения. ТакId а такжеDateCreated не нужны в представлении модели. Возможно, вы захотите отобразить эти два свойства при просмотре сведений о сотруднике (сотрудник, который уже был захвачен) в виде статического текста.

При загрузке представления / страницы метод create action в контроллере сотрудника создаст экземпляр этой модели представления, заполнит все поля, если это необходимо, а затем передаст эту модель представления представлению / странице:

public class EmployeeController : Controller
{
     private readonly IEmployeeService employeeService;

     public EmployeeController(IEmployeeService employeeService)
     {
          this.employeeService = employeeService;
     }

     public ActionResult Create()
     {
          CreateEmployeeViewModel model = new CreateEmployeeViewModel();

          return View(model);
     }

     public ActionResult Create(CreateEmployeeViewModel model)
     {
          // Do what ever needs to be done before adding the employee to the database
     }
}

Ваш вид / страница может выглядеть так (при условии, что вы используетеASP.NET MVC иRazor вид двигателя):

@model MyProject.Web.ViewModels.CreateEmployeeViewModel

<table>
     <tr>
          <td><b>First Name:</b></td>
          <td>@Html.TextBoxFor(m => m.FirstName, new { maxlength = "50", size = "50" })
              @Html.ValidationMessageFor(m => m.FirstName)
          </td>
     </tr>
     <tr>
          <td><b>Last Name:</b></td>
          <td>@Html.TextBoxFor(m => m.LastName, new { maxlength = "50", size = "50" })
              @Html.ValidationMessageFor(m => m.LastName)
          </td>
     </tr>
</table>

Таким образом, проверка будет проводиться только наFirstName а такжеLastName, С помощьюСвободная проверка у вас может быть такая проверка:

public class CreateEmployeeViewModelValidator : AbstractValidator<CreateEmployeeViewModel>
{
     public CreateEmployeeViewModelValidator()
     {
          RuleFor(m => m.FirstName)
               .NotEmpty()
               .WithMessage("First name required")
               .Length(1, 50)
               .WithMessage("First name must not be greater than 50 characters");

          RuleFor(m => m.LastName)
               .NotEmpty()
               .WithMessage("Last name required")
               .Length(1, 50)
               .WithMessage("Last name must not be greater than 50 characters");
     }
}

А с аннотациями данных это может выглядеть так:

public class CreateEmployeeViewModel : ViewModelBase
{
    [Display(Name = "First Name")]
    [Required(ErrorMessage = "First name required")]
    public string FirstName { get; set; }

    [Display(Name = "Last Name")]
    [Required(ErrorMessage = "Last name required")]
    public string LastName { get; set; }
}

The key thing to remember is that the view model only represents the data that you want to use, ничего больше. Вы можете представить весь ненужный код и проверку, если у вас есть модель домена с 30 свойствами, и вы хотите обновить только одно значение. При таком сценарии у вас будет только одно значение / свойство в модели представления, а не все свойства, которые находятся в объекте домена.

Модель представления может иметь не только данные из одной таблицы базы данных. Он может объединять данные из другой таблицы. Возьмите мой пример выше о добавлении новой записи сотрудника. Помимо добавления только имени и фамилии, вы также можете добавить отдел сотрудника. Этот список отделов придет из вашегоDepartments Таблица. Итак, теперь у вас есть данные изEmployees а такжеDepartments таблицы в одном представлении модели. Затем вам нужно будет добавить следующие два свойства в вашу модель представления и заполнить ее данными:

public int DepartmentId { get; set; }

public IEnumerable<Department> Departments { get; set; }

При редактировании данных о сотрудниках (сотрудниках, которые уже были добавлены в базу данных) они не будут сильно отличаться от моего примера выше. Создайте модель вида, назовите ее напримерEditEmployeeViewModel, Только данные, которые вы хотите редактировать в этой модели представления, например, имя и фамилия. Отредактируйте данные и нажмите кнопку отправки. Я бы не стал слишком беспокоиться оId поле, потому чтоId значение, вероятно, будет в URL, например:

http://www.yourwebsite.com/Employee/Edit/3

Возьми этоId и передайте его на ваш уровень хранилища вместе с вашими именами и фамилиями.

При удалении записи я обычно иду по тому же пути, что и в модели редактирования. У меня также будет URL, например:

http://www.yourwebsite.com/Employee/Delete/3

Когда представление загружается в первый раз, я получаю данные сотрудника из базы данных, используяId из 3. Затем я просто отображал бы статический текст на своем представлении / странице, чтобы пользователь мог видеть, какого сотрудника удаляют. Когда пользователь нажимает кнопку Удалить, я просто используюId значение 3 и передать его в мой слой хранилища. Вам нужно толькоId удалить запись из таблицы.

Еще один момент: вам не нужна модель представления для каждого действия. Если это простые данные, то было бы хорошо использовать толькоEmployeeViewModel, Если это сложные представления / страницы, и они отличаются друг от друга, то я бы предложил вам использовать отдельные модели представлений для каждого.

Я надеюсь, что это прояснит любую вашу путаницу с моделями представления и моделями доменов.

@Kenny: Тогда покажи :) Что я хотел сказать, скажем, у тебя модель домена с 50 свойствами, и твоему представлению нужно только отображать 5, тогда бесполезно отправлять все 50 свойств только для отображения 5.
@BrendanVogt & # x2013; Вы проделали хорошую работу, объяснив это, но я не понимаю, сколько стоит «отправить все 50 объектов». Другой код уже создал объект Model со всеми 50 свойствами, и, кажется, не стоит поддерживать другой класс только для того, чтобыnot отправить 45 объектов & # x2013; особенно если тыmight хочу отправить любой из этих 45 объектов в будущем.
+1 за упоминание беглой проверки
Прошу прощения за критику, но, к сожалению, этот ответ неполон. Определить модель представления как то, что вам нужно для отображения на своей странице, все равно, что задать вопрос "Что такое автомобиль?" и получение ответа "Это не самолет". Ну, это правда, но не очень полезно. Более правильное определение виртуальной машины - это «все, что вам нужно для отображения страницы». Если вы прочитаете до конца, я определил компоненты, которые вам необходимы для правильного и простого построения вашей виртуальной машины, во многих случаях используя ваши существующие доменные модели и модели представления.
@BrendanVogt & # x2013; Я думаю, что, возможно, ответ LukLed помогает мне понять, почему они могут быть полезны, в частности, что ViewModel (может) "... объединять значения из разных объектов базы данных" [где я предполагаю, что фраза является такой же истинной, как «сущности базы данных»; должен быть заменен на «Объекты модели». Но все же, какие конкретные проблемы были предназначены для решения ViewModels? У вас есть ссылки? Я сам ничего не смог найти. [И я прошу прощения, если я, кажется, придираюсь к тебе!]
1

ся, например, для получения подмножества или объединения данных из разных таблиц.

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

0

который мы можем использовать для визуализации данных в View. Предположим, у вас есть две сущности Place и PlaceCategory, и вы хотите получить доступ к данным обеих сущностей, используя одну модель, тогда мы используем ViewModel.

  public class Place
    {
       public int PlaceId { get; set; }
        public string PlaceName { get; set; }
        public string Latitude { get; set; }
        public string Longitude { get; set; }
        public string BestTime { get; set; }
    }
    public class Category
    {
        public int ID { get; set; }
        public int? PlaceId { get; set; }
        public string PlaceCategoryName { get; set; }
        public string PlaceCategoryType { get; set; }
    }
    public class PlaceCategoryviewModel
    {
        public string PlaceName { get; set; }
        public string BestTime { get; set; }
        public string PlaceCategoryName { get; set; }
        public string PlaceCategoryType { get; set; }
    }

Таким образом, в приведенном выше примере Place и Category - это две разные сущности, а ViewModel для PlaceCategory - это ViewModel, которую мы можем использовать в View.

126

View model это класс, который представляет модель данных, используемую в определенном представлении. Мы могли бы использовать этот класс в качестве модели для страницы входа в систему:

{
    [Required(ErrorMessage = "Are you really trying to login without entering username?")]
    [DisplayName("Username/e-mail")]
    public string UserName { get; set; }
    [Required(ErrorMessage = "Please enter password:)")]
    [DisplayName("Password")]
    public string Password { get; set; }
    [DisplayName("Stay logged in when browser is closed")]
    public bool RememberMe { get; set; }
}

Используя эту модель представления, вы можете определить представление (Razor view engine):

@model CamelTrap.Models.ViewModels.LoginPageVM

@using (Html.BeginForm()) {
    @Html.EditorFor(m => m);
    <input type="submit" value="Save" class="submit" />
}

И действия:

[HttpGet]
public ActionResult LoginPage()
{
    return View();
}

[HttpPost]
public ActionResult LoginPage(LoginPageVM model)
{
    ...code to login user to application...
    return View(model);
}

Который дает этот результат (после отправки формы отображается экран с сообщениями проверки):

Как видите, модель представления имеет много ролей:

View models documents a view by consisting only fields, that are represented in view. View models may contain specific validation rules using data annotations or IDataErrorInfo. View model defines how a view should look (for LabelFor,EditorFor,DisplayFor helpers). View models can combine values from different database entities. You can specify easily display templates for view models and reuse them in many places using DisplayFor or EditorFor helpers.

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

public class UserVM {
    public int ID { get; set; }
    public string FirstName { get; set; }
    public string LastName { get; set; }
    public bool IsAdministrator { get; set; }
    public string MothersName { get; set; }
}

индексирование:

var user = db.userRepository.GetUser(id);

var model = new UserVM() {
   ID = user.ID,
   FirstName = user.FirstName,
   LastName = user.LastName,
   IsAdministrator = user.Proviledges.IsAdministrator,
   MothersName = user.Mother.FirstName + " " + user.Mother.LastName
} 
спасибо, это очень полезно unique
@Chandana: я полагаю, что простое объединение может быть сделано в модели представления. Нет смысла выставлять два поля, если они должны быть представлены вместе.
Я худой пользователь. Mother.FirstName + & quot; & Quot; + user.Mother.LastName должно быть сделано в View Model End. Вся логика должна быть сделана в конце View Model.
22

специфичные для представления и не связанные с БД / Сервисом / Хранилищем данных, рекомендуется использовать ViewModels. Скажем, вы хотите оставить флажок установленным на основе поля БД (или двух), но само поле БД не является логическим. Хотя можно создать эти свойства в самой модели и скрыть ее от привязки к данным, вы можете не загромождать модель в зависимости от количества таких полей и транзакций.

Если данных и / или преобразований для конкретного вида слишком мало, вы можете использовать саму модель

1
ViewModel contain fields that are represented in the view (for LabelFor,EditorFor,DisplayFor helpers) ViewModel can have specific validation rules using data annotations or IDataErrorInfo. ViewModel can have multiple entities or objects from different data models or data source.

Designing ViewModel

{ 
[Required(ErrorMessage = "Please enter your username")] 
[Display(Name = "User Name")]
[MaxLength(50)]
public string UserName { get; set; }
 [Required(ErrorMessage = "Please enter your password")]
 [Display(Name = "Password")]
 [MaxLength(50)]
 public string Password { get; set; } 
} 

Presenting the viewmodel in the view

@model MyModels.UserLoginViewModel 
@{
 ViewBag.Title = "User Login";
 Layout = "~/Views/Shared/_Layout.cshtml";
}
@using (Html.BeginForm())
{
<div class="editor-label">
 @Html.LabelFor(m => m.UserName)
</div>
<div class="editor-field">
 @Html.TextBoxFor(m => m.UserName)
 @Html.ValidationMessageFor(m => m.UserName)
</div>
<div class="editor-label">
 @Html.LabelFor(m => m.Password)
</div>
<div class="editor-field">
 @Html.PasswordFor(m => m.Password)
 @Html.ValidationMessageFor(m => m.Password)
</div>
<p>
 <input type="submit" value="Log In" />
</p>
</div>
}

Working with Action

public ActionResult Login()
{ 
return View();
}
[HttpPost]
public ActionResult Login(UserLoginViewModel user)
{
// To acces data using LINQ
DataClassesDataContext mobjentity = new DataClassesDataContext();
 if (ModelState.IsValid) 
{ 
try
 {
 var q = mobjentity.tblUsers.Where(m => m.UserName == user.UserName && m.Password == user.Password).ToList(); 
 if (q.Count > 0) 
 { 
 return RedirectToAction("MyAccount");
 }
 else
 {
 ModelState.AddModelError("", "The user name or password provided is incorrect.");
 }
 }
 catch (Exception ex)
 {
 } 
 } 
 return View(user);
} 
In ViewModel put only those fields/data that you want to display on the view/page. Since view reperesents the properties of the ViewModel, hence it is easy for rendering and maintenance. Use a mapper when ViewModel become more complex.
10

позвольте мне объяснить в ясной и хрустящей форме.

ViewModel = Модель, созданная для обслуживания представления.

ASP.NET MVC view can't have more than one model so if we need to display properties from more than one models into the view, it is not possible. ViewModel serves this purpose.

Модель представления - это класс модели, который может содержать только те свойства, которые требуются для представления. Он также может содержать свойства более чем одной сущности (таблицы) базы данных. Как следует из названия, эта модель создана специально для требований View.

Несколько примеров моделей просмотра приведены ниже

To list data from more than entities in a view page – we can create a View model and have properties of all the entities for which we want to list data. Join those database entities and set View model properties and return to the View to show data of different entities in one tabular form View model may define only specific fields of a single entity that is required for the View.

ViewModel также можно использовать для вставки, обновления записей в более чем один объект, однако основное использование ViewModel - отображение столбцов из нескольких объектов (модели) в одном представлении.

Способ создания ViewModel аналогичен созданию Model, способ создания представления для Viewmodel аналогичен созданию представления для Model.

Вот небольшой примерВывод данных с использованием ViewModel.

Надеюсь, это будет полезно.

Похожие вопросы