Making good use of ASP.NET MVC DataAnnotations with separate assemblies
Let's say that I have a Domain assembly that describes the domain model, and it has a class called product:
public class Product
{
public int Id { get; set; }
public string Name { get; set; }
}
I have also another assembly that is the web application running with this domain model. Now I want to create a form to create new products and have some validation on the attributes. The easiest way to do this is to use DataAnnotations on the class. However this results in that the domain model now contains metadata about form validation, which is not a very clear separation of concerns.
It is possible to have the MetadataType
attribute for the class but I see this as no better. Suddenly your domain model class has a dependency on the form validation metada class.
Another way is to create a CreateProductForm
class and add the required attributes there, and do mapping between the classes. However this creates some overhead as you need to maintain these classes seperately and changes in one might break the other. It might be desirable in some scenarios to do that, but in some others it might just create extra work (imagine that you have an Address class, for example).
UPDATE: some people have suggested that I use AutoMapper for this, which I'm already aware of. AutoMapper just makes mapping simpler and easier, does not actually solve the problem of having to maintain two separate classes which will be almost identical. My preference would be to only create the form classes when there is a distinct need for it.
Is there a straightforward to declar开发者_开发知识库e the annotations within the web assembly, without creating unnecessary dependencies for the domain assembly?
If you don't want to introduce coupling between your domain model and your views, you should go for the CreateProductForm class way.
Depending on your project size/requirements, you're going to have to separate your view model from your domain sooner or later. Suppose you're using the DisplayName attribute : are you going to tag your domain entities ?
Using a tool like AutoMapper simplifies greatly the mapping process.
Why wouldn't you have DataAnnotations on your domain classes. If there is something that is Required, then I think it's perfectly valid to mark it as required in the domain.
Other DataAnnotations such as StringLength, Range etc, all to me perfectly valid things to decorate your domain entities with.
Implementing IValidableObject is also a perfectly acceptable thing for domain object to do IMHO.
I wouldn't go putting UI stuff on them such as UIHint though or annoations describing the formatting of the property. That would be bad.
Normally I avoid displaying domain classes on the user interface, and use ViewModel classes with a mapping tool such as AutoMapper etc to map from one to the other. The ViewModel class has the annoations of the domain class with perhaps additional UI specific annotations.
As mathieu and XHalent state you should use a CreateProductForm (or a CreateProductFormViewModel) along with Automapper and create attribues that automap the model to the viewmodel for the action.
That way all the form validation goes on your view model and all the data validation (related to the database) goes in your domain model.
In Silverlight and WPF it is called the MVVM pattern and a lot of people who do asp.net mvc recommend it.
In my current project I am also using it with Automapper. All my views have an associated view model that is a flattened version of the domain model specific to that view.
I think this was the example I used (It's the one I still have bookmarked anyway. but this one linked in the first one seems better.) Using the attribute means that you return the domain object from your action in the controller and the automap attribute maps the domain object to your viewmodel automatically.
Doing this should give you the seperation you are looking for.
精彩评论