(MVC / MVVM). В чем причина создания отдельной модели представления для каждого представления? [Дубликат]

[D2] DateTime.Now.ToString ( "ГГГГММДДччммсс");

, если вы просто хотите, чтобы он отображался как строка

22
задан mridula 20 January 2013 в 11:02
поделиться

4 ответа

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

  • Важно выполнить всю обработку в действии контроллера. Однако в примере, который вы указали, метод Repository.Get может возвращать lazily-оцененный объект IQueryable, что означало бы, что БД не пострадает, пока не будет оценен вид. По целому ряду причин это плохо. (Обходной путь состоит в том, чтобы вызвать .ToList, пока он все еще находится в контроллере).
  • «В представлении не должно быть никакой нерепрезентативной логики» и «Вы не должны доверять представлению» (поскольку представление может быть предоставленный пользователем). Предоставляя объект Model (потенциально все еще подключенный к активному DatabaseContext), представление может вносить вредоносные изменения в вашу базу данных.
  • Данные, отображаемые в представлении View, не всегда отображают 1: 1 с данными модели, например, рассмотрим страницу «Сведения о пользователе»: объект «Модель пользователя EF» представляет свою сущность в базе данных, поэтому он, вероятно, выглядит следующим образом: User { UserId, UserName, PasswordHash, PasswordSalt, EmailAddress, CreatedDate }, тогда как поля на странице «Сведения о пользователе» будут User { UserId, UserName, Password, ConfirmYourPassword, EmailAddress }, do вы видите разницу? Ergo, вы не можете использовать модель пользователя EF в качестве модели представления, вы должны использовать отдельный класс.
  • Опасности манипуляции с моделью: если вы разрешите ASP.NET MVC ( или любая другая инфраструктура) связывают модель с входящим HTTP POST-запросом (принимая приведенный выше пример сведений о пользователе), пользователь может сбросить пароль пользователя, присвоив значение свойства UserId. ASP.NET будет переписывать это значение во время привязки и, если вы специально не дезинформируете его (что будет так же тяжело, как создание отдельных ViewModels), тогда эта уязвимость останется.
  • В проектах с несколькими разработчиками, работающими в команде ситуация, , важно, чтобы все было согласовано . Не обязательно, чтобы на некоторых страницах использовались специальные модели ViewModels, но на других страницах, использующих модели EF, потому что команда не разделяет сознательный разум, все должно быть документировано и, как правило, имеет смысл. По той же причине один разработчик может уйти, не помещая чрезмерную документацию XML в свой исходный код, но в командной ситуации вы развалитесь, если вы этого не сделаете.

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

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

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

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

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

14
ответ дан Dai 15 August 2018 в 23:11
поделиться
  • 1
    Я все еще думаю, как можно безопасно использовать модель представления на примере вашей проблемы безопасности (поддельное значение UserId), поскольку в модели представления также есть свойство UserId – Agung Setiawan 11 November 2015 в 07:20
  • 2
    @AgungSetiawan. Ваша ViewModel не должна содержать никаких неизменяемых (только для чтения) полей. Неизменяемые значения должны быть в вашем ViewData. И ваш код действия контроллера не должен доверять никаким данным, предоставленным пользователем. Сердцем проблемы безопасности Entity-as-ViewModel является автоматическое связывание, предоставляемое каркасом, и веб-приложение, предполагающее, что данные от клиента могут быть доверены, чтобы не перезаписывать чувствительные элементы Entity. Путем ручного заполнения объекта из режима просмотра, при необходимости проверив проверки безопасности, эта проблема предотвращается. – Dai 12 November 2015 в 06:04
  • 3
    @AgungSetiawan. Вы можете использовать объект Entity с чувствительными полями как ViewModel, если вы не не присоединяете его к вашему DbContext, а вместо этого вручную копируете значения элементов между ним и новый, прикрепленный объект объекта; однако, как и прежде, вы должны убедиться, что вы не копируете и не перезаписываете чувствительные элементы. – Dai 12 November 2015 в 06:05
  • 4
    В случае, если у каких-либо будущих посетителей будут подобные смущения для меня о «моделях просмотра», которые предотвращают изменение вредоносных баз данных ». бит: stackoverflow.com/questions/45307963/… – Sinjai 28 July 2017 в 17:45

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

  1. To установить свободную связь между моделью и контроллером. Так что любые изменения, связанные с DataModel, не будут влиять на контроллер.
  2. Если вы правильно реализовали слой ViewModel вашего приложения, предоставив максимальный уровень IOC (Inversion of Control) через DI (зависимость от инъекций с использованием Unity / других фреймворков) и т. д., это также поможет вам MOQ ваши модели ViewModels (зависимости) для тестирования только логики контроллера.
1
ответ дан Bugs 15 August 2018 в 23:11
поделиться

Если вы используете те же модели, что и ваши модели ViewModels, ваше приложение должно быть очень маленьким и простым и должно содержать только операции CRUD. Но если вы строите большие или корпоративные приложения с большими командами (с двумя или, вероятно, с большим количеством разработчиков), у вас должны быть такие понятия, как инжекция зависимостей, сервисы, репозитории, фасады, единицы работы, объекты доступа к данным и т. Д.

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

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

2
ответ дан Mert Sakarya 15 August 2018 в 23:11
поделиться

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

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

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

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

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

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

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

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

4
ответ дан Quinton Bernhardt 15 August 2018 в 23:11
поделиться
  • 1
    Я согласен, добавление слоя разделения означает добавление слоя дополнительного кода! например. добавление модульных тестов, чтобы при удалении столбца, который вы знаете об этом, и можно изменить механизм перевода ModelModel ViewModel. Но это помогает изолировать изменения модели, влияющие на один уровень кода, и ограничивает повторное тестирование, требуемое только для тех изменений кода .... в любом случае - у всех нас есть собственное мнение, и я все еще изучаю каждый день, и мое мнение будет изменить в соответствии;) – Quinton Bernhardt 20 January 2013 в 11:37
  • 2
    Я добавлю, что я думаю, что нужно делать больше, чтобы различать однонаправленные данные ViewData и двунаправленные данные ViewModel. В Model люди не должны передавать такие вещи, как заголовки HTML-страниц и метаданные. – Dai 20 January 2013 в 11:39
  • 3
    Я не думал использовать ViewModels в качестве переводчиков, как в примере, который вы дали! Спасибо вам за понимание. – mridula 20 January 2013 в 18:19
Другие вопросы по тегам:

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