Что такое ViewModel в MVC?

429

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

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

Если бы я получил хороший пример о его работе и объяснениях, это было бы лучше.

уникальный
источник
4
Этот пост - то, что вы ищете - «Что такое ASP.NET MVC ViewModel?»
Юсубов
6
Эта статья выглядит великолепно: rachelappel.com/…
Эндрю
Возможный дубликат В MVC, что такое ViewModel?
rogerdeuce 10.07.15

Ответы:

607

A 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. Используя FluentValidation, вы можете иметь такую ​​проверку:

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; }
}

Важно помнить, что модель представления представляет только те данные, которые вы хотите использовать , и ничего больше. Вы можете представить весь ненужный код и проверку, если у вас есть модель домена с 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

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

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

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

Брендан Фогт
источник
5
@Kenny: Тогда покажи это :) То, что я пытался сказать, скажем, у тебя есть модель домена с 50 свойствами, и твоему представлению нужно только отобразить 5, тогда бесполезно отправлять все 50 свойств только для отображения 5.
Брендан Фогт
5
@BrendanVogt - вы хорошо объяснили это, но я не понимаю, какова стоимость «отправки всех 50 объектов». Другой код уже создал объект модели, со всеми 50 свойствами, и это , кажется , не стоит поддерживать другой класс просто не послать 45 свойств - особенно , если вы , возможно , хотите отправить любую из этих 45 объектов в будущем.
Кенни Эвитт
5
@BrendanVogt - я думаю, что, возможно, ответ LukLed поможет мне понять, почему они могут быть полезны, особенно в том, что ViewModel (может) «... объединять значения из разных объектов базы данных» [где я предполагаю, что фраза точно так же, как и были » сущности базы данных »заменить" Модельными объектами "]. Но все же, какие конкретные проблемы были предназначены для решения ViewModels? У вас есть ссылки? Я ничего не мог найти сам. [И я прошу прощения, если мне кажется, что я тебя
придираю
1
Я только что слышал, как кто-то сказал, что ViewModels - это хороший способ отправки нескольких коллекций (или свойств кросс-модели) в одно представление без необходимости вставлять их в viewBag. Имеет смысл для меня.
Ayyash
3
Прошу прощения за критику, но этот ответ, к сожалению, неполный. Определить модель представления как то, что вам нужно для отображения на своей странице, все равно, что спросить "Что такое автомобиль?" и получить ответ "Это не самолет". Ну, это правда, но не очень полезно. Более правильное определение виртуальной машины: «Все, что вам нужно для рендеринга вашей страницы». Если вы прочитаете до конца, я определил компоненты, которые вам необходимы для правильного и простого построения вашей виртуальной машины, во многих случаях используя ваши существующие модели предметной области и модели представления.
Сэм
133

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

public class LoginPageVM
{
    [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);
}

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

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

  • Представление моделей документов представляет собой представление, состоящее только из полей, представленных в представлении.
  • Модели представлений могут содержать конкретные правила проверки с использованием аннотаций данных или IDataErrorInfo.
  • Посмотреть модель определяет как вид должен выглядеть (для LabelFor, EditorFor, DisplayForхелперов).
  • Модели представлений могут объединять значения из разных объектов базы данных.
  • Вы можете легко указать шаблоны отображения для моделей просмотра и использовать их во многих местах с помощью помощников DisplayFor или EditorFor.

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

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
} 
LukLed
источник
Я похудел user.Mother.FirstName + "" + user.Mother.LastName должно быть сделано в View Model End. Вся логика должна быть сделана в конце View Model.
Куркула
3
@Chandana: я полагаю, что простое объединение может быть сделано в модели представления. Нет смысла выставлять два поля, если они должны быть представлены вместе.
LukLed
82

Изменить: я обновил этот ответ в своем блоге:

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

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

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

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

Вот сравнение моделей Entity (a.ka. DTO's a.ka. models), презентационных моделей и моделей просмотра.

Объекты передачи данных ака «Модель»

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

• являются бизнес-объектами - их определение зависит от данных приложения.

• Обычно содержат только свойства - без кода.

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

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

Таблицы базы данных обычно нормализуются, поэтому 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; }
}

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

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

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

• являются бизнес-объектами - их определение зависит от данных приложения.

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

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

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

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

Модели представления используются «по мере необходимости» и «где необходимо» (тогда как 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); } }
}

Посмотреть модели

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

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

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

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

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

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

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

• написаны «на страницу» или «на экран». Уникальная модель представления обычно пишется для каждой страницы или экрана в приложении.

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

Посмотреть состав модели

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

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

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

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

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

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

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); } }
}

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

Композиция по наследству

Вот способ, которым мы могли бы пересмотреть модель представления заказа так, чтобы она стала истинной моделью представления и была бы полезна для отображения одного объекта 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!
}
Сэм
источник
2
Сэм Спасибо! это помогло мне полностью понять многогранную сущность: View-Model. Я студент колледжа, только изучающий архитектуру MVC, и это прояснило множество функциональных возможностей, которые предоставляет разработчик. Если бы я мог, я бы поставил звездочку рядом с вашим ответом.
Chef_Code
1
@Sam «Модели представлений часто содержат те же свойства, что и модели представления и DTO, и поэтому их часто путают друг с другом». Означает ли это, что они обычно используются вместо моделей презентации или они должны содержать модели презентации / dtos?
Александр Дерк
2
@AlexanderDerck Они используются для разных целей. Они перепутаны один за другим (по ошибке). Нет, вы обычно не будете использовать модель pres вместо модели представления. Гораздо более распространенным является то , что виртуальная машина «содержит» на презентации модели ИЭ MyViewModel<MyPresModel>
Sam
2
@Sam Предполагая, что объекты модели являются живыми объектами, например, моделями nhibernate .., поэтому, имея BusinessObject, мы не выставляем модели / живые объекты непосредственно на представление? т.е. бизнес-объект может быть использован для непосредственного изменения состояния базы данных? Кроме того, как насчет моделей с вложенным представлением? Это потребует нескольких свойств бизнес-объекта, верно?
Мухаммед Али
22

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

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

fozylet
источник
19

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

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

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

halfacreSal
источник
11

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

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

  • View отвечает за представление данных пользователю
  • Контроллер отвечает за поток страниц
  • Модель отвечает за бизнес-логику

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");
        }
    }
}

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

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

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

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

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

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

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

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

@model ProjectName.Model.StudentViewModel

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

Mayank
источник
10

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

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

Представление ASP.NET MVC не может иметь более одной модели, поэтому, если нам нужно отобразить в представлении свойства нескольких моделей, это невозможно. ViewModel служит этой цели.

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

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

  • Чтобы вывести данные из более чем сущностей на странице представления - мы можем создать модель представления и иметь свойства всех сущностей, для которых мы хотим вывести данные. Присоединитесь к этим объектам базы данных и установите свойства модели View и вернитесь в View, чтобы отобразить данные разных объектов в одной табличной форме.
  • Модель представления может определять только определенные поля одной сущности, которые требуются для представления.

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

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

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

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

Шео Нараян
источник
6

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

gsivanov
источник
1

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

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


источник
1
  • ViewModel содержит поля, которые представлены в представлении (для помощников LabelFor, EditorFor, DisplayFor)
  • ViewModel может иметь определенные правила проверки с использованием аннотаций данных или IDataErrorInfo.
  • ViewModel может иметь несколько объектов или объектов из разных моделей данных или источника данных.

Проектирование ViewModel

public class UserLoginViewModel 
{ 
[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; } 
} 

Представление модели представления в представлении

@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>
}

Работа с действием

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);
} 
  1. В ViewModel поместите только те поля / данные, которые вы хотите отобразить на представлении / странице.
  2. Поскольку представление представляет свойства ViewModel, следовательно, его легко рендерить и обслуживать.
  3. Используйте маппер, когда ViewModel становятся более сложными.
дикий кодер
источник
1

View Model - это класс, который мы можем использовать для визуализации данных в 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.

Сагар Шинде
источник
Ваши примеры не так понятны. Выше было сказано, что ViewModel подключает данные к своему представлению. Если вы посмотрите на ViewModels в BlipAjax, вы увидите классы, которые идеально подходят для него.
Херман ван дер Блом
0

Если вы хотите изучить код, как настроить «базовое» веб-приложение с помощью ViewModels, я могу посоветовать загрузить этот код на GitHub: https://github.com/ajsaulsberry/BlipAjax . Я разработал крупные корпоративные приложения. Когда вы делаете это, проблематично настроить хорошую архитектуру, которая обрабатывает все эти функциональные возможности «ViewModel». Я думаю, что с BlipAjax у вас будет очень хороший «базовый уровень» для начала. Это просто простой веб-сайт, но отличный в своей простоте. Мне нравится, как они использовали английский язык, чтобы указать на то, что действительно нужно в приложении.

Герман ван дер Блом
источник