ASP.NET MVC: using EF entities as viewmodels? [duplicate] - asp.net-mvc

This question already has answers here:
Closed 12 years ago.
Possible Duplicate:
ASP.NET MVC - Linq to Entities model as the ViewModel - is this good practice?
Is is OK to use EF entities classes as view models in ASP.NET MVC?
What if viewmodel is 90% the same of EF entity class?
Let's say I have a Survey class in Entity Framework model. It 90% matches data required for view to edit it.
The only difference from what view model should have - is one or several properties to be used in it (that are required to populate Survey object because EF class cannot be directly mapped onto how it's properties are represented (sub-checkboxes, radio groups, etc.))
Do you pass them using ViewData[]? Or create a copy of Survey class (SurveyViewModel) with new additional properties (it should be able to copy data from Survey and back to it)?
Edit:
I'm also trying to avoid using Survey as SurveyViewModel property. It will look strange when some Survey properties are updated using UpdateModel or with default binder, while others (that cannot be directly mapped to entity) - using SurveViewModel custom properties in controller.

I like using Jimmy Bogard's approach of always having a 1:1 relationship between a view and a view model. In other words, I would not use my domain models (in this case your EF entities) as view models. If you feel like you are doing a lot of work mapping between the two, you could use something like AutoMapper to do the work for you.

Some people don't like passing these model classes all the way through to the view, especially as they are classes that are tied to the particular ORM you're currently using. This does mean that you're tightly binding your data framework to your view types.
However, I have done this in several simple MVC apps, using the EF entity type as the Model for some strongly-typed views - it works fine and is very simple. Sometimes simple wins, otherwise you may find yourself putting a lot of effort and code into copying values between near-identical Model types in an app where realistically you'll never move away from EF.

You should always have view models even if they are 1:1. There are practical reasons rather than database layer coupling which I'll focus on.
The problem with domain, entity framework, nhibernate or linq 2 sql models as your view classes is you cannot handle contextual validation well. For example given a user class:
When a person signs up on your site they get a User screen, you then:
Validate Name
Validate Email
Validate Password Exists
When an admin edits a user's name they get a User screen, you then:
Validate Name
Validate Email
Now expose contextual validation via FluentValidation, DataAnnotations Attributes, or even custom IsValid() methods on business classes and validate just Name and Email changes. You can't. You need to represent different contexts as different view models because validation on those models changes depending on the screen representation.
Previously in MVC 1 you could get around this by simple not posting fields you didn't want validated. In MVC 2 this has changed and now every part of a model gets validated, posted or not.
Robert Harvey pointed out another good point. How does your user Entity Framework display a screen and validate double password matching?

On bigger projects, I usually split up business objects from data objects as a matter of style. It's a much easier way to let the program and database both change and only affect the control (or VM) layer.

Related

MVC, Strongly Typed Views and Entity Framework dilemma

I've read quite a few Q & As relating to logic in views within an MVC architecture and in most cases I agree that business logic shouldn't live in a view. However having said this, I constantly question my approach when using Microsoft's MVC Framework in conjunction with the Entity Framework because of the ease of accessibility to foreign key relationships a single entity can give me which ultimately results in me performing Linq to Entities queries inline within a View.
For example:
If I have the following two entities:
Product ([PK]ProductId, Title, Amount)
Image ([PK]ImageId, [FK]ProductId, ImageTitle, DisplayOrder)
Assuming I have a strongly typed Product view and I want to display the primary image (lowest display order) then I could do something like this in the view:
#{
Image image = (from l in Model.Image
orderby l.DisplayOrder
select l).FirstOrDefault();
}
This is a simple example for demonstration purposes, but surely this begins to bend the rules in relation to MVC architecture, but on the other hand doing this in the Controller and then (heaven forbid) jamming it into the ViewBag or ViewData would surely be just as much of a crime and become painful to manage for more than a few different related classes.
I used to create custom classes for complex Models, but it's time-consuming and ugly and I no longer see the point as the Entity Framework makes it quick and easy to define the View to be the primary Model (in this case a Product) and then easily retrieve all the peripheral components of the product using Linq queries.
I'd be interested to know how other people handle this type of scenario.
EDIT:
I also quite often do things like:
#foreach(Image i in Model.Image.OrderBy(e => e.DisplayOrder).ToList())
{
<img ... />
}
I'm going the 'custom classes for Models' way, and I agree it's time consuming and mundane, hence tools like http://automapper.codeplex.com/ have been created, to accompany you with this task.
Overall, I'm having similar feelings to yours. Reading some stuff saying it's good to have your domain model unrelated to your storage, then different class for your view model than the domain model, and then seeing that libraries actually seem to 'promote' the easy way (data annotations over your domain classes seem to be simplier than EF fluent interface etc etc).
At least we've got the choice I guess!
Model binding There is also issue that when you want to POST back the model data and store it in the database, you need to be careful and make sure MVC model binders bind all fields correctly. Else you may loose some data. With custom models for views, it might be simplier.
Validation
MVC gives you a way to validate using attributes, when you use viewmodels, you can freely pollute it with such annotations, because it's view specific (and validation should be view/controller action specific as well). When you use EF classes, you would be polluting those classes with unrelated (and possibly conflicting) logic.

Different model validation scenarios

I have a user entity in my application where users input some basic information when they register to the application. If they want to use some advanced features they have to give full information.
So I have two validation scenarios.
My first approach was to exchange the Required attribute with MyRequired attribute to avoid columns being created as NOT NULL in the database via Entity Framework.
But the model is validated if I add it to my DB context. So I can't add the entity if it's just filled with basic information.
Is there a way to have one entity with several different validation scenarios?
Is there any way to validate a model with different scenarious?
That's what view models are supposed to do. I would recommend you to avoid passing your EF models to the views. Also avoid passing EF domain models to your actions => always use view models. Those classes are specifically designed to meet the requirements of a given view, including validation attributes. Then map your model entities to your view models.
This way your domain models are completely decoupled from the way the information is being presented on a given view. Also (as it is your case) the same domain model could have two different representations on different views as well as different validation requirements of course => view models fill this gap.

entity framework POCO + recommended patterns

We do like EntityFramework (CTP5) quite a lot and Using it along with ASP.NET MVC3.
What I dislike is;
things are mixed in together.
I can place a DisplayAttribute, RequiredAttribute, RangeAttribute, CompareAttribute together in the same class which means I am mixin in database validation, some business logic and UI alltogether. I can even place ScriptIgnore attribute to customize it as a Json DTO object. So I can use the same POCO class for Persistance, Presentation, DTO and Business Object, and as my domian model.
Which design patterns do you follow along with EF POCO + MVC3 toolset. What layers do you have?
What resposibilities do you add to your classes (Is Your POCO class also your Domain Model)
I use View Models to solve this problem. Validation and UI presentation attributes go to the view model. In this pattern the controller uses a repository to fetch an EF model, maps this EF model to a view model (I use AutoMapper for this) and passes the view model to the view. Because the view model contains all the UI presentation attributes the view behaves as expected. Each view must have its own view model. This means that you could have multiple view models associated to the same EF model but contain a different subset of properties and display formatting attributes based on the specific requirements of the view.
The process works the other way around as well: the controller receives a view model from the view as argument. It maps the view model back to a model and passes the EF model to the repository. UI validation attributes are handled on the view model because you could have different validation requirements in different views: think for example Insert/Update views. In the insert view you will be creating a new entity thus the Id property won't be required. You won't even have an Id property on your view model in this case. In the update view on the contrary the Id property will be required.
My POCO classes are almost always domain models and almost never view models so I don't have these problems.
The best practice is to use special "view model" class when passing data from controller to view (or as JsonResult). In such case you mark UI based attributes in that view model. In most cases (except pure crud applications) you need to display something more or something less then your domain object so you still need some view model (unless you use ViewData directly).
Data annotations on domain object makes sense only if you want to use them for business/data level validation which can take different rules then UI validation.
If you want to follow strict DDD where POCO classes are domain objects = offers methods performing domain logic on instance of object you should go even further because in such case your business facede should not expose domain objects to controller. In such case you will end up with data transfer objects exposed on business facade and consumed in controller. I'm not purist so in this scenario I'm open minded to using data annotations on DTOs directly but it depends on another requirements.

Asp.net MVC Architecture

I'm coming to the end of my first MVC project, and I'm not overly happy with how I constructed my Model objects and I'm looking for some ideas on how to improve them.
I use repositories for each DB table with Get, Save, Delete etc methods.
The repositories use Linq2Sql for the DB access.
I do mapping from the Linq2Sql objects to MVC Model objects, in the main, these are very much 1 to 1 mappings.
My problem is, I don't think my MVC model objects were granular enough, and I am probably passing more data back and forth than needed.
For example, I have a User table. An admin can edit a users details as can the user themselves, so I reckon I should really have a "AdminUserModel" and "UserModel" objects, where "AdminUserModel" has a greater set of values (IsEnabled for example).
So my bigger question is really, what kind of architectures are people using out there in the wild, in order to map many similar, related Model objects down through the layers to the DB?
Any sample architecture solutions anyone can suggest beyond NerdDinner?
thanks in advance!
In the case of your user model, you should use inheritence in stead of 2 seperated models. In this way you can use the code that was created for user in the ones that inherite from it.
the type of model you use depends completely on what you want to do with it. A good thing might be to take a look at patterns and try to get the patterns working that are needed for your situation...
I usually take implement inheritance in my models.
I usually have a base class of entity, which will have id, datecreated, valid and any other fields that are shared between entities (publishStatus, locked etc).
If needs be you can create other base classes inheriting from entity: person entity, product entity etc.
this way you can have a generic repository base, constrained to Entity or IEntity, i find that most entities CRUD functions dont need much more behaviour than that provided by the generic base (perhaps you will need to add a few additional get methods for some types)
In your case, AdminUser could inherit from User

Reusing validation attributes in custom ViewModels

When I started using xVal for client-side validation, I was only implementing action methods which used domain model objects as a viewmodel or embedded instances of those objects in the viewmodel.
This approach works fine most of the time, but there are cases when the view needs to display and post back only a subset of the model's properties (for example when the user wants to update his password, but not the rest of his profile data).
One (ugly) workaround is to have a hidden input field on the form for each property that is not otherwise present on the form.
Apparently the best practice here is to create a custom viewmodel which only contains properties relevant to the view and populate the viewmodel via Automapper. It's much cleaner since I am only transferring the data relevant to the view, but it's far from perfect since I have to repeat the same validation attributes that are already present on the domain model object.
Ideally I'd like to specify the Domain Model object as a meta class via a MetaData attribute (this is also often referred to as "buddy class"), but that doesn't work since xVal throws when the metadata class has properties that are not present on the viewmodel.
Is there any elegant workaround to this? I've been considering hacking the xVal sourcecode, but perhaps there is some other way I have overlooked so far.
Thanks,
Adrian
Edit: With the arrival of ASP.NET MVC 2, this is not only a problem related to validation attributes anymore, but it also applies to editor and display attributes.
This is the quintessential reason why your input screens should not be tightly coupled to your model. This question actually pops up here on the MVC tag about 3-4 times a month. I'd dupe if I could find the previous question and some of the comment discussion here is interesting. ;)
The issue your having is you're trying to force two different validation contexts of a model into a single model which fails under a large amount of scenarios. The best example is signing up a new user and then having an admin edit a user field later. You need to validate a password on a user object during registration but you won't show the password field to the admin editing the user details.
The choices for getting around these are all sub-optimal. I've worked on this problem for 3 projects now and implementing the following solutions has never been clean and usually frustrating. I'm going to try and be practical and forget all the DDD/db/model/hotnessofthemonth discussions everybody else is having.
1) Multiple View Models
Having viewmodels that are almost the same violates the DRY principal but I feel the costs of this approach are really low. Usually violating DRY amps up maintenance costs but IMHO the costs for this are the lowest and don't amount to much. Hypothetically speaking you don't change how max number characters the LastName field can have very often.
2) Dynamic Metadata
There are hooks in MVC 2 for providing your own metadata for a model. With this approach you could have whatever your using to provide metadata exclude certain fields based on the current HTTPRequest and therefore Action and Controller. I've used this technique to build a database driven permissions system which goes to the DB and tells the a subclass of the DataAnnotationsMetadataProvider to exclude properties based values stored in the database.
This technique is working great atm but the only problem is validating with UpdateModel(). To solve this problem we created a SmartUpdateModel() method which also goes to the database and automatically generates the exclude string[] array so that any non-permissisable fields aren't validated. We of course cached this for performance reasons so its not bad.
Just want to reiterate that we used [ValidationAttributes] on our models and then superceeded them with new rules on runtime. The end result was that the [Required] User.LastName field wasn't validated if the user didn't have permission to access it.
3) Crazy Interface Dynamic Proxy Thing
The last technique I tried to was to use interfaces for ViewModels. The end result was I had a User object that inherited from interfaces like IAdminEdit and IUserRegistration. IAdminEdit and IUserRegistration would both contain DataAnnotation attributes that performed all the context specific validation like a Password property with the interfaces.
This required some hackery and was more an academic exercise than anything else. The problem with 2 and 3 is that UpdateModel and the DataAnnotationsAttribute provider needed to be customized to be made aware of this technique.
My biggest stumbling block was I didn't ever want to send the whole user object to the view so I ended up using dynamic proxies to create runtime instances of IAdminEdit
Now I understand this is a very xVal specific question but all of the roads to dynamic validation like this lead to customization of the internal MVC Metadata providers. Since all the metadata stuff is new nothing is that clean or simple to do at this point. The work you'd have to do to customize MVC's validation behavior isn't hard but requires some in depth knowledge of how all of the internals work.
We moved our validation attributes to the ViewModel layer. In our case, this provided a cleaner separation of concerns anyway, as we were then able to design our domain model such that it couldn't get into an invalid state in the first place. For example, Date might be required on a BillingTransaction object. So we don't want to make it Nullable. But on our ViewModel, we might need to expose Nullable such that we can catch the situation where the user didn't enter a value.
In other cases, you might have validation that is specific per page/form, and you'll want to validate based on the command the user is trying to perform, rather than set a bunch of stuff and ask the domain model, "are you valid for trying to do XYZ", where in doing "ABC" those values are valid.
If ViewModels are hypothetically being forced upon you, then I recommend that they only enforce domain-agnostic requirements. This includes things like "username is required" and "email is formatted properly".
If you duplicate validation from the domain models in the view models, then you have tightly coupled the domain to the UI. When the domain validation changes ("can only apply 2 coupon per week" becomes "can only apply 1 coupon per week"), the UI must be updated. Generally speaking, this would be awful, and detrimental to agility.
If you move the validation from the domain models to the UI, you've essentially gutted your domain and placed the responsibility of validation on the UI. A second UI would have to duplicate all the validation, and you have coupled two separate UI's together. Now if the customer wants a special interface to administrate the inventory from their iPhone, the iPhone project needs to replicate all the validation that is also found in the website UI.
This would be even more awful than validation duplication described above.
Unless you can predict the future and can rule out these possibilities, only validate domain-agnostic requirements.
I don't know how this will play for client-side validation, but if partial validation is your issue you can modify the DataAnnotationsValidationRunner discussed here to take in an IEnumerable<string> list of property names, as follows:
public static class DataAnnotationsValidationRunner
{
public static IEnumerable<ErrorInfo> GetErrors(object instance, IEnumerable<string> fieldsToValidate)
{
return from prop in TypeDescriptor.GetProperties(instance).Cast<PropertyDescriptor>().Where(p => fieldsToValidate.Contains(p.Name))
from attribute in prop.Attributes.OfType<ValidationAttribute>()
where !attribute.IsValid(prop.GetValue(instance))
select new ErrorInfo(prop.Name, attribute.FormatErrorMessage(string.Empty), instance);
}
}
I'm gonna risk the downvotes and state that there is no benefit to ViewModels (in ASP.NET MVC), especially considering the overhead of creating and maintaining them. If the idea is to decouple from the domain, that is indefensible. A UI decoupled from a domain is not a UI for that domain. The UI must depend on the domain, so you're either going to have your Views/Actions coupled to the domain model, or your ViewModel management logic coupled to the domain model. The architecture argument is thus moot.
If the idea is to prevent users from hacking malicious HTTP POSTs that take advantage of ASP.NET MVC's model binding to mutate fields they shouldn't be allowed to change, then A) the domain should enforce this requirement, and B) the actions should provide whitelists of updateable properties to the model binder.
Unless you're domain is exposing something crazy like a live, in-memory object graph instead of entity copies, ViewModels are wasted effort. So to answer your question, keep domain validation in the domain model.

Resources