Вопрос по viewmodel, asp.net-mvc-3, asp.net-mvc, orm – ASP.NET MVC - объекты базы данных или ViewModels?

39

В настоящее время я работаю над проектом ASP.NET MVC.

Некоторые разработчики в команде хотят привязать автоматически сгенерированные объекты базы данных непосредственно к представлениям.

Другие разработчики хотят создавать индивидуальные ViewModel и связывать их с представлениями.

Объективно, каковы плюсы и минусы обоих подходов?

(Под «сущностями базы данных» я имею в виду автоматически сгенерированные классы, которые генерирует каркас ORM, такие как LINQ to SQL, Entity Framework или LLBLGen).

Ваш Ответ

8   ответов
0

особенно ваши формыmassive проблема безопасности. Возьмите следующий объект POCO

public class User
{
    public int Id { get; set; }
    public string Username { get; set; }
    public string Email { get; set; }
    public bool IsAdmin { get; set; }
}

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

public class HomeController : Controller
{
    [HttpPost]
    public ActionResult ChangeEmail(User user)
    {
        //....
    }
}

Привязка модели в Asp.net работает путем поиска параметров GET или POST, соответствующих именам свойств в модели. Поэтому все, что нужно сделать пользователю, это добавитьIsAdmin=true к параметрам POSt и альту, модель перешла вChangeEmail Функция будет иметь свойство IsAdmin, установленное в значение true, которое очень легко может быть случайно добавлено в базу данных, предоставляя пользователям свободный доступ к данным об изменениях, к которым у них нет доступа к изменениям.

Это касается прав пользователей, изменения владельца объекта (сделайте так, чтобы ваш вопрос ассоциировался со мной вместо вас), изменения первоначальных дат создания и т. Д.

Я уже обсуждал это неделю назад в своем ответе. Это известно как «пересылка по почте». Смотрите мой пост выше. Alex York
Извините, когда я прочитал ваш ответ, я подумал, что вы больше хотели видеть данные в скрытых полях, чем отправлять данные на сервер, чтобы изменить данные, которые вы не сможете.
8

одов. У меня есть одна вещь, чтобы добавить, что никто не упомянул.

Over-posting attack

Тревожным недостатком связывания непосредственно с объектами БД является «атака с чрезмерной публикацией». Именно здесь злоумышленник, используя инструмент не более продвинутый, чем FireBug, может вставить поля формы, которые не предназначены для редактирования пользователем, но которые существуют в сущности БД.

Рассмотрите & quot; Изменить мой профиль & quot; стр. Ваше мнение может выглядеть так:

@using(Html.BeginForm() {
  <div>
    @Html.LabelFor(x=> x.FirstName)
    @Html.TextBoxFor(x=> x.FirstName)
  </div>
  <div>
    @Html.LabelFor(x=> x.LastName)
    @Html.TextBoxFor(x=> x.LastName)
  </div>

  <input type="Submit" value="Save" />
}

Будет отображаться следующий HTML:

<form action="/profile/edit" method="post">
  <div>
    <label for="FirstName">FirstName</label>
    <input type="text" name="FirstName" value="" />
  </div>
  <div>
    <label for="LastName">LastName</label>
    <input type="text" name="LastName" value="" />
  </div>

  <input type="Submit" value="Save" />
</form>

Используя FireBug, злоумышленнику просто нужно вставить кусок HTML внутри формы:

  <input type="hidden" name="IsAdmin" value="true" />

... и вдруг пользователи могут изменять данные очень неожиданным и вредным образом.

Вот некоторые еще более скрытые поля скрытой формы:

  <input type="hidden" name="ShoppingCart.Items[0].Price" value="0.01" />
  <input type="hidden" name="BankAccount.Balance" value="1000000" />
  <input type="hidden" name="User.Administrator.Password" value="hackedPassword" />

Ой!

Информация взята из: http://hendryluk.wordpress.com/tag/asp-net-mvc/

3

Реальное приложение имеет поведение, а не CRUD. Если вы связываете свои сущности с представлением о том, что это будет вопросом времени, прежде чем вы начнете копаться в грязном хакере, когда на клиентской стороне требуется поведение.

1

как взломанный китайский. Кроме того, я добавил бы, что с помощью fk для просмотра списков, вы просто ДОЛЖНЫ использовать view-модели, поскольку модель сущностей просто будет содержать указатель на один идентификатор в этой таблице. Модель представления позволяет вам передать требуемый заполненный список в представление - вуаля.

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

Целью ViewModel является главным образом разделение задач - отделение View от деталей реализации Model.

49

use view models in your viewsи использовать что-то вродеAutoMapper легко создавать модели представления из сущностей.

Минусы:

Sometimes it feels like you are duplicating code, specifically, when the view model and the entity have the exact same properties

Плюсы:

You often need to represent an object in a simpler format (often called flattening), but you need full fidelity on the server side. This allows you to transition between the two without mucking up your domain model with presentation cruft. Aggregate roots often have a lots of value objects and additional entities that are irrelevant to a specific view, and omitting them in a view model makes it easier to work with. Your entities will have lots of two way references that are sensible in terms of an API, but create pure hell when serializing them for JSON, XML, etc. View models will eliminate these circular references. You may often use the same entity but in different ways for different views. Trying to balance both needs on one type can create a huge mess.
+1 действительно хороший момент
12

I believe using view models is the only way to go, so no pros for ORM entities:) View models not only provide data for view, but they also define how view should look (by defining templates) or how it should validate (by adding data annotations or implementing IDataErrorInfo).

Using view models:

Pros:

View models contain only properties required by view, nothing else. View models may contain specific validation rules using data annotations or IDataErrorInfo. View models can combine values from different database entities. View models document themselves and are not tied to any framework. View models protect you from forged POSTs, containing values, that were not provided in form, but were contained in ORM entities. You can specify easily display templates for view models and reuse them in many places using DisplayFor or EditorFor helpers.

Using ORM entities:

Cons:

ORM entities already contain data annotations, that can mess up your validation. Example: Password field in user may be markes as Required, but it is not required when you change only basic user info. ORM entities are strongly tied to Framework (Entity Framework) and may be not easy to implement rules in. ORM entities can contain properties for more than one view, but it is hard to separate validation rules for different views. Using ORM entities with lazy loading can lead you to executing SQL queries when views are rendered. It shouldn't happen. Using ORM entities can lead to using huge SQL queries instead on small ones. When you want to display dropdown with first name and last name, you should only retrieve first name and last name from database, not whole entities.
+1 еще одно замечательное резюме
5

которое использовало бы сущности NHibernate непосредственно в представлениях ASP.NET. Я столкнулся со многими проблемами с отложенной загрузкой и отложенным выполнением SQL, выполняемым непосредственно из представлений, а не на уровне бизнес-логики или даже контроллерах. Переход на viewmodels и использование automapper, казалось, решили все эти проблемы и упростили тестирование, отладку и обслуживание приложения.

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

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

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

+1 Гэвин, я столкнулся почти со всеми теми же проблемами, что и вы, и по той же причине перенял и автомаппер, и модели представления.
16

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

ORM lazy loading. Imagine your Customer has a lazy loaded collection Orders. You pass Customer off to the View and it iterates over Orders. You get an N*1 select on the Orders table. But it also means that your database connection still needs to be open in the View. There is a pattern that people use 'Transaction per Action' which disposes of the database context in the Action_Executed event, which happens before your View is rendered. So you could be trying to access the database after it has been disposed. Even if you are not doing that now, someone in future might decide to implement that pattern because it is fashionable.

The concerns of the ViewModel are different to the db Model. For example, you typically decorate your ViewModel properties with validation attributes. These typically are different or only concern the UI not the db. If you bind to your database entities you will find all these UI concerns polluting you DB entities.

Related to 2 - the requirements of the ViewModel may demand computed or derived properties. For example, a Fullname constructed from First and Last names. These kind of things are best kept in the ViewModel.

You can unit-test your ViewModels in isolation from the database. ViewModels can end up containing quite a lot of logic which needs to be unit-tested. This is easier to test if it is not tied to your database (as with EF entities).

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

+1, а также грабить - надмножество всех "хороших" идеи здесь подведут итоги темы.
Джим, кто-то должен написать новый ответ, комбинируя все уникальные моменты в других :)

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