ASP.NET MVC - Database entities or ViewModels?

2019-02-03 00:01发布

I am currently working on an ASP.NET MVC project.

Some developers on the team want to bind the auto-generated database entities directly to the Views.

Other developers want to create tailor-made ViewModel's and bind those to the Views.

Objectively, what are the pros and cons of both approaches?

(By "database entities" I am referring to the auto generated classes that an ORM framework generates, such as LINQ to SQL, Entity Framework or LLBLGen).

8条回答
smile是对你的礼貌
2楼-- · 2019-02-03 00:11

I once tried to develop an app which used NHibernate entities directly in ASP.NET views. I ran into many problems with Lazy loading and deferred SQL execution running directly from the views rather than in the business logic layer or even controllers. Moving to a viewmodels and using automapper seemed to solve all these problems and make the app easier to test, debug and maintain.

I also found that view models were helpful in holding all the associated data I needed on a page. Some developers like to use the dynamic ViewBag for this, but this is bad for testing and debugging.

In particular, view models made it easy when you wanted to pick associated entities from dropdown lists.

AutoMapper was a lifesaver on this project, as it saved having to write a ton of mapping code, all I had to do was create the view models and then the controllers automapped from entities to view models.

查看更多
做个烂人
3楼-- · 2019-02-03 00:17

Do not expose backend-entities to the client. Real world application have behaviour -not CRUD. It you databind your entities to the view it will just be a matter of time before you dig into muddy hack when behaviour is required on the clientside.

查看更多
Lonely孤独者°
4楼-- · 2019-02-03 00:19

Thanks for the answers so far - they have been a big help in understanding the pros/cons of both approaches. I have one thing to add that no one else has mentioned.

Over-posting attack

A worrying disadvantage with binding directly against DB entities is an "over-posting attack". This is where the attacker, using a tool no more advanced than FireBug, can insert form fields that are not intended to be editable by the user, but which do exist on the DB entity.

Consider an "Edit my profile" page. Your view might look like this:

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

It would render the following 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>

Using FireBug, an attacker merely needs to insert a chunk of HTML inside the form:

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

...and suddenly users are able change data in very unexpected and harmful ways.

Here are some even scarier hidden form fields:

  <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" />

Ouch!

Info taken from: http://hendryluk.wordpress.com/tag/asp-net-mvc/

查看更多
▲ chillily
5楼-- · 2019-02-03 00:24

I was just about to add exactly the same sentiment as hackedbychinese. also i'd add, with fk's to lookup lists, you just HAVE to use viewmodels as the entity model merely will hold a pointer to a single id within that table. A viewmodel allows you to pass the required populated list into the view - voila.

Also, a viewmodel can contain discreet logic where required, this would definately NOT be the case with the entity model. Also, your validations may vary depending on the use of your view, therefore different validations can be applied per 'view' requirement.

The purpose of a ViewModel is mainly separation of concerns - decoupling the View from the implementation details of the Model.

查看更多
戒情不戒烟
6楼-- · 2019-02-03 00:27

Definitely use view models in your views, and use something like AutoMapper to create view models from entities easily.

Cons:

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

Pros:

  1. 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.
  2. 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.
  3. 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.
  4. 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.
查看更多
等我变得足够好
7楼-- · 2019-02-03 00:27

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.
查看更多
登录 后发表回答