Подтвердить что ты не робот

Почему мы используем ViewModels?

Недавно я начал работать в качестве веб-разработчика. Я работаю с ASP.NET MVC 4 и NHibernate.

На моем рабочем месте мы строго вынуждены использовать viewmodels для передачи данных между контроллером и представлением. И в моделях просмотра не предполагается содержать какой-либо объект модели. Я понимаю, что это своего рода уровень между контроллером и представлением.

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

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

return View(Repository.Get<Order>(id));

Но вместо этого, я должен написать viewmodel, заполнить его с выбранным порядком, а затем передать его в представление.

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

4b9b3361

Ответ 1

Для небольших проектов вы правы. Я слышу ваш аргумент и сочувствую - однако есть веские причины для этого, тяжелая и повторяющаяся работа, особенно в более крупных и более сложных приложениях:

  • Необходимо выполнить всю обработку в действии Controller. Однако в примере, который вы указали, метод Repository.Get может возвращать lazily-оцениваемый объект IQueryable, что означало бы, что БД не пострадает до тех пор, пока не будет оценен вид. По целому ряду причин это плохо. (Обходной путь заключается в вызове .ToList, пока он все еще находится в контроллере).
  • "В представлении не должно быть никакой непредвзятой логики" и "Вы не должны доверять представлению" (поскольку представление может быть предоставлено пользователем). Предоставляя объект Model (потенциально все еще подключенный к активному DatabaseContext), представление может вносить вредоносные изменения в вашу базу данных.
  • A Просмотр данных для отображения не всегда отображает 1:1 с данными модели, например, рассмотрите страницу сведений о пользователе:

    Объект User EF Model представляет свою сущность в базе данных, поэтому он, вероятно, выглядит следующим образом: User { UserId, UserName, PasswordHash, PasswordSalt, EmailAddress, CreatedDate }, тогда как поля на странице "Сведения о пользователе" будут User { UserId, UserName, Password, ConfirmYourPassword, EmailAddress }, вы видите разницу? Ergo, вы не можете использовать модель пользователя EF в качестве модели представления, вам нужно использовать отдельный класс.

  • Опасности манипуляции с моделью: если вы позволяете ASP.NET MVC (или любой другой инфраструктуре) привязывать модель к входящему HTTP POST-запросу, то (принимая пример данных пользователя выше) пользователь мог бы reset любой пароль, обманув значение свойства UserId. ASP.NET будет переписывать это значение во время привязки и, если вы специально не дезинфицируете его (что будет так же тяжело, как создание отдельных ViewModels), тогда эта уязвимость останется.

  • В проектах с несколькими разработчиками, работающими в командной ситуации, важно, чтобы все было согласовано. Не обязательно, чтобы на некоторых страницах использовались специальные модели ViewModels, но на других страницах, использующих модели EF, потому что команда не разделяет сознательный разум, все должно быть документировано и, как правило, имеет смысл. По той же причине один разработчик может уйти, не помещая чрезмерную документацию XML в свой исходный код, но в командной ситуации вы развалитесь, если вы этого не сделаете.

В вашем случае есть небольшое обходное решение, которое я поделюсь с вами, но обратите внимание на предварительные условия:

  • Ваши взгляды можно полностью доверять
  • Ваши взгляды содержат только презентационную логику
  • Ваше приложение в основном CRUD
  • Ваши представления соответствуют 1:1 с каждой моделью сущности EF (т.е. нет JOIN)
  • Ваши взгляды касаются только простых простых моделей для форм POST, а не сложных моделей (т.е. графа объектов)

... тогда вы можете сделать это:

  • Поместите все односторонние, не связанные с формой данные в вашу коллекцию ViewData или ViewBag в MVC 4 (или даже общий ViewData<T>, если вы хардкор). Это полезно для хранения заголовков страниц HTML и совместного использования данных с мастер-страницами.
  • Используйте ваши полностью оцененные и загруженные модели EF в качестве моделей View<TModel>.

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

Ответ 2

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

  • ViewModel имеет важное значение, если вы хотите разделить проблемы между DomainModel (DataModel) и остальной частью вашего кода.

Чем меньше зависимостей между моделью, View и контроллером, тем проще вносить изменения в DomainModel, не нарушая контракты интерфейса в представлении и контроллере и т.д. и т.д. Но еще раз это будет прагматичны. Мне нравится подход, поскольку перефакторинг кода является большой частью системного обслуживания - рефакторинг может включать в себя простую орфографическую ошибку для свойства модели - это изменение может пульсировать через код до уровня Контракта, если зависимости не разделены; например.

  • ViewModel используется для перевода данных между вашим DomainModel и вашими представлениями

Простой пример datetime, хранящийся в Informix, должен быть переведен в .Net DateTime. ViewModel - идеальное место для выполнения этого перевода и не заставляет вас вводить код перевода во всевозможные нежелательные места.

Одним из атрибутов хорошей конструкции [чего-либо] является возможность замены или модификации части реализации с небольшими или никакими последствиями для остальных частей системы. Но это требует усилий и времени для достижения - вам решать, чтобы найти практический баланс между идеальным дизайном и дизайном, который достаточно просто

Но да, есть много других веских причин использовать определенные шаблоны, но в итоге это:

Ничто не заставляет вас использовать ViewModels... ASP.NET MVC не заставит вас. Возьмите совет у прагматика внутри вас.

Ответ 3

Если вы используете те же модели, что и ваши модели ViewModels, ваше приложение должно быть очень маленьким и простым и должно содержать только операции CRUD. Но если вы создаете большие или корпоративные приложения с большими командами (с двумя или, возможно, с большим количеством разработчиков), у вас должны быть такие концепции, как Dependency Injection, Services, Repositories, Façades, Units of Work, Data Access Objects и т.д.

Чтобы упростить ваши потребности в сопоставлении между моделями и ViewModels, вы можете использовать AutoMapper https://github.com/AutoMapper/AutoMapper

или установить с помощью nuget Install-Package AutoMapper

Ответ 4

По моему мнению, важно иметь еще один слой (ViewModel) поверх уровня модели для сложных приложений, выполняющих большую часть операций CRUD, поскольку имеет следующие преимущества:

  • Установить свободную связь между моделью и контроллером. Так что любые изменения, связанные с DataModel, не будут влиять на контроллер.
  • Если вы правильно применили свой слой ViewModel приложения обеспечивая максимальный уровень IOC (инверсия контроля) через DI (зависимая инъекция с использованием Unity/других фреймворков) и т.д., Это будет также помогите вам MOQ ваши ViewModels (зависимости) только для тестирования логика контроллера.