开发者

MVC, ViewModels, and Validation

开发者 https://www.devze.com 2023-02-02 01:44 出处:网络
I\'m creating an MVC3 application with EF4 using POCOs. I\'ve added validation attributes to my EF entities. Now, as I\'m building the views, I want to use a view model (and perhaps use AutoMapper to

I'm creating an MVC3 application with EF4 using POCOs. I've added validation attributes to my EF entities. Now, as I'm building the views, I want to use a view model (and perhaps use AutoMapper to fill them).

The problem that I have run into is that I have to redefine my validation attr开发者_如何学运维ibutes on my view model which violates the DRY principal. For example, if I decide to change the size of a field, I have to change the MaxLength attribute on both the POCO and any view models that use it.

Is there some tricky way I can map the validation rules from my POCOs to my view model?


Personally I perform validation at view models. This is what a controller receives from a view and it is the class which contains the user input. I distinguish between two type of validation rules: surface validation and business validation. Rules such as required fields, proper formats should be enforced at the view models whereas business rules like a user with a given name already exists in the database should be validated on the model.

Also you could have different view models mapped to the same model but based on the view validation rules could vary. Because of this you won't have exactly the same validation rules on the view models.


One approach that gets some abstraction is to have a ViewModel 'composed' of your business model class, including other view information you need.

class MyObject 
{
    public int ID {get;set}

    [Required]
    [StringLength(512)]     
    public string Name {get;set;}

}

class MyViewModel // ViewModel for a specific view 
{
    public MyObject MyModel {get;set;}        // the model that is being edited 

    // other data the view might need, set by the controller 
    public string SomeMessage { get; set; }
    public List<SomeObject> SomeObjects {get;set;} /// e.g. for a drop-down list

}

Then in the view reference the ViewModel accordingly.

@model My.Namespace.MyViewModel


Hello @model.MyModel.Name !!!

This way, you only specify your validation and/or data-annotations in your business class in one place.

If you are wanting to have different validation then that will require some strategy to selectively apply validation logic.


I too struggle with this, and I agree that it violates DRY. I posted a recent question about this Here and got quite a bit of pushback.

You can't ever get perfect DRY in any real world application. Sometimes you get more good out of violating a principle than by trying to stick to it blindly.

EDIT:

One might also consider that DRY can violate the Single Responsibility Principle (SRP). By reusing similar code, you are now causing the code to do more than one thing. If you think about the fact that data models and view models have different purposes, and thus different responsibilities... combing them into a single model violates SRP. That is, by making your data model also be a view model, that's two different responsibilities.

Now, one can think of a number of ways to potentially try and reconcile SRP with DRY in this regard, but at some point you have to weigh the benefits from the cost.

0

精彩评论

暂无评论...
验证码 换一张
取 消