Reputation: 81
I am trying to understand the whole MVC/EF relationship. If I create a Entity Model that would only interact with the database (since you shouldnt pass you entity model to a view), then a class for the Model, and finally a view model all shown below. My only question is it seems redundant to have the second class, the only different in the examples I have seen is that they apply data annotations to that class since it is interacting with the view. Why is it so important to make sure that entity objects arent exposed at the view layer?
I havent actually started writing a project yet, but I assume that you would use the Entity model for interacting with a database then cast it into a ProductModel to pass to the view is this the correct logic?
Entity Model:
public class Product
{
[Key()]
public int ID { get; set; }
public string Name { get; set; }
public string Description { get; set; }
public double Price { get; set; }
}
Model:
public class ProductModel
{
public int ID { get; set; }
[StringLength(50)]
[Required(ErrorMessage = "Product Name is required.")]
[Display(Name = "Product Name")]
public string Name { get; set; }
public string Description { get; set; }
public double Price { get; set; }
}
ViewModel:
public class ProductViewModel
{
Product myProduct { get; set; }\
//Plus any other properties I may need for the view.
}
UPDATE:
In the example I have been reading they also have a DBContext set as follows. So is the ProductModel class useless then?
public class MyAppContext : DbContext
{
public MyAppContext()
: base("name=DBConnection")
{
}
public DbSet<Product> Products { get; set; }
}
Upvotes: 8
Views: 762
Reputation: 37947
The ViewModel is going to be what actually gets passed to/from the browser, often via JSON if you're building something that can update in place/save in place. So:
ASP.Net MVC has some limitations around what it can produce/consume over JSON (and its limitations differ slightly in each direction); you can use a ViewModel to work around that
The size of the data you pull back from the database may not be what needs to get to the browser - for example you might need to pull back some extra fields and check them before passing it on, but only want to pass on a subset - the ViewModel is the subset.
Some natural structures in JSON are not really available in a database - for example you might have the equivalent of a Dictionary stored in your Model, as for example one table with some values, and another table with an FK pointing back to it, an Id, and a string value - but for the browser to leverage it you might just need that string value. So in the ViewModel you represent that all with a simple Dictionary (which ends up as a simple JS object on the client).
Often things like Date formatting are weak on the client or flimsy by depending on the client having an accurate system clock, etc. I frequently use a String in my ViewModel where I have a DateTime in my Model and translate from UTC to their timezone and format it nicely on the server before it arrives in their browser.
Sometimes you need to avoid exposing parts of the Model to the browser; for example in some systems if you exposed the row Id to the browser you could create a security risk. A ViewModel makes it trivial to hide portions of your Model.
See also: how to design ViewModel
Upvotes: 1
Reputation: 21
To start, there is something missing and combined techniques, one is to abstract completelly the DAL from all other layer, this is a technique. But also there is other technique that can be used; use the "Entities" classes as domain classes. On a simple scenario we always use the domain classes on the bussiness layer to apply all the bussiness rules. this will help us a lot to combine the testability throught layers and avoiding unuseful links between layers without increasing a lot of lines of code/number of classes.
Also this approach to have this domain objects (domain classes) throught all the layers will make you things a lot easier when you are working with MVC, because this classes can have data annotations that will be used by:
Also to understand the concept and use of this type of classes there is something that we need to pay attention. If we are using POCO's as our entities and domain classes, this same classes are not the same classes that Entity Framework will use when interpreting queries to the DB. Instead EF will create dynamic classes (derived from the POCO) that represent that domain object as a entity and load all the virtual fields, typically the related entities.
And you will be saving code of classes and trivial remapping.
Hope this helps
Upvotes: 0
Reputation: 239220
There's times, and particularly on simple models, where a view model may not be required. But, and a big "but", I've found very few instances of that situation and even then, I later generally find a need to go back and create a view model, anyways. Having a specialized view model is safer, simpler and easier all-around.
You might look at it as extra work, but think of it in terms of separation of concerns (which is the whole point of MVC). If I want to present a SelectList for an input, for example, I can either add it to ViewBag or to my model. If I add it to ViewBag, I lose strong-typing which is never ideal, but it doesn't belong on my database-tracked entity, either. Having a view model let's me put this information exactly where it should go: a strongly-typed model that exists to serve the view and only to serve the view.
Or, consider validation: what if I want a field required for the database (non-null), but I want to make this optional for the user, and fill it with some business logic myself behind the scenes if the user opts not to specify. The view model can handle that abstraction easily whereas adding it to the entity, itself, would add a huge layer of complexity.
Nothing is required, of course. You can always set up your project however you like, but best-practices are best-practices for a reason: developers just like you, time and again, have ran into the same issues and coalesced around a workable solution. You might be able to avoid view models for a time, but eventually, you'll run into the same roadblocks and incorporate them anyways, so just do it right from the start and make your life easier.
Upvotes: 3
Reputation: 1151
In Addition to the answers above, another point that hasnt been mentioned to to prevent data being sent to the view/client that doesnt need to be.
for example suppose your product model contains the price you pay your supplier to purchase the product. you dont want your customers to see this data, but if it is included in the model sent to the view - even if you don't display that field - they can assess it. this is a case where you would use a different view model and copy the data from the ef/database model to the view model before sending it to the view.
sometimes you can end up with a DBcontext class, an EF/database class/Model and several viewmodels each holding a different subset of the data from the database model.
you can also find yourself with a viewmodel that holds data from several Database models, you offten see this where the view uses lists or dropdowns as an alternative to sending the list options in the viewbag.
Upvotes: 1
Reputation: 4999
Why is it so important to make sure that entity objects arent exposed at the view layer?
It isn't. For a simple CRUD controller, it is often easier to just pass in the entity object. For a more complex page you may be interacting with more than one Entity object / type at the same time. How would you pass information about both objects without creating a new model class?
Upvotes: -1
Reputation: 3764
You need Product class
, ProductViewModel class
then your DbContext
.
If you are doing this for the first time, read Pro ASP.NET MVC 3 Framework, Third Edition
or
They have a detailed information about MVC and both books have a Real Application tutorial you can follow
from start to finish including deployment.
You will also learn about Unit Testing and other MVC tools such as Dependency Injection (Ninject) and Moq
Upvotes: 1
Reputation: 17307
There are two major reasons I create a model class, separate from my entity.
As you mentioned, attributes. You may want to reuse your entities in several applications and they may not use the same attributes. You don't want to pollute your entities with these.
Depending on them ORM, your entities may require a base class. Or there might be attributes, or other customizations that you have to apply to the entities. This could cause there to be difficulties when testing your Business Logic. Additionally, if you change ORMs or something in your ORM changes, you will keep that change isolated from the rest of the application.
Basically, you are isolating the different layers of your application and protecting one layer from changes made in another.
Upvotes: 1