Conditional Validation on MVC3 Model Class

2020-04-21 00:31发布

问题:

I'm using Entity Framework and a Model class, DonationForm, wrapped by a view model class "CreateDonationForm".

In keeping with the DRY principle, I have added the validation annotations on the Model class (not the just the view model), so that they will be reusable. However, not all of the properties on the class will always be used (some are in fact mutually exclusive). For example when a particular phone number property is relevant, I want to make it conform to a Regex annotation and be Required. But in a different situation I want to be able to get away with submitting (and persiting to the database) a null value.

Following this post: How do I use IValidatableObject?

I made the model class implement IValidatableObject and implemented custom validation to selectiely remove validation errors from the ValidationResult object (when the field was part of a group of fields that were not relevant given the user's other choice(s) on the form). It worked and I was able to get back List of ValidationResults where those errors had been expunged.

However, when I called SaveChanges() I get validation errors which prevent the save. The validation is still happening at the database/model class level. (The database was generated from the Model class using EF 4.1 Code First.)

How is it possible to acheive conditional formatting rules and still use Annotations on the Model class? This is essentially saying - apply these validation rules IF otherwise do not apply these validation rules. Please coach me here. I'm new-ish to MVC and I'm trying to do things the proper way. It seems like putting the validation on the view model and then mapping values onto the underlying model class might work; however, it doesn't feel right. I see big value in having the validation attributes on the Model class itself and lots of wasted, repetivitive work in placing the same annotations on both the create and update view models. It feels like I'm fighting MVC Fw here on something that ought to be easier. Any insights that you can provide would be greatly appreciated.

回答1:

There is a lot of cool principles but sometimes small violation makes your life easier. Get rid of data annotations from your EF model and place them on your view model where they belong. You can still use IValidatableObject in view model and compose the validation from multiple reusable helper methods used by multiple view models (so you can still achieve DRY principle).

If you stubborn and really want to have validation in EF model turn off validation in EF and handle it in upper layer as you already do:

dbContext.Configuration.ValidateOnSaveEnabled = false; 

EF level validation is for simple scenarios where your validation rules do not change among operations.