Saturday, December 21, 2013

Custom Model Validation Provider for enabling ASP.NET MVC 3 client side validation.


Implementing Custom Model Validation Provider to enable client side MVC 3 validation 

The Validation framework of ASP.NET MVC 3 is designed for extensibility and customization.  It supports validation model using attributes, or by implementing IValidatableObject or unobtrusive javascript based client side validation. It supports both property based or model based validation.

But, again ASP.Net MVC 3 assumes your solution has view models defined in a simple, flat & non hierarchical fashion to make things work. Sometimes, in applications we need to apply or perform validation rather in different ways to comply with existing legacy code, architectural style and culture.

Update: Following solution is applicable to ASP.NET MVC 3 FRAMEWORK ON VS 2010

One last word!! we assume you have in place all necessary jquery /javascript /css files for the MVC client side validation to work

Use case for Implementing Custom ModelValidatorProvider:

In my case, I did not have the pleasure to have view models exclusively defined for the mvc project.

Domain model classes are directly applied to MVC views. I cannot litter domain classes with validation attributes. They are shared components. They derive from some base classes. So, I couldn't really force annotation based validation working directly using this convoluted & hierarchical model classes as shown below:





















Binding JuniorEngineer model to mvc view and enabling property level client side validation declaratively using attributes/annotations seemed difficult for me.

Inject the validation attributes at Run time on the model:

So, we decided to inject validation attributes on model at the run time dynamically. In this case, we have to go for implementing custom validation solution which means we have to create a custom ModelValidatorProvider that allows to inject validation rules on the fly into the model.

Implementing Custom DataAnnotationsModelValidatorProvider:

MVC provides hook to plug in your custom implementation of ModelValidatorProvider. The purpose is to bind validation attributes dynamically to model to enable client side validation.

 public class JuniorEmployeeModelValidator : DataAnnotationsModelValidatorProvider
    {
        protected override IEnumerable<ModelValidator> GetValidators(ModelMetadata metadata, ControllerContext context, IEnumerable<Attribute> attributes)
        {
            if (metadata.ContainerType != typeof(JuniorEngineer))
                return base.GetValidators(metadata, context, attributes);
            //enable client side validation for name prop for junior engineer model. Name property is inherited from base abstract employee class.
            if (!string.IsNullOrWhiteSpace(metadata.PropertyName) && metadata.PropertyName == "Name")
            {
                //injecting required attribute to name /salary properties.
                attributes = new List<Attribute>()
                {
                    new RequiredAttribute()
                    {
                        ErrorMessage = "Hey babe, we just need a human name."
                    }
                };
            }
            if (!string.IsNullOrWhiteSpace(metadata.PropertyName) && metadata.PropertyName == "Salary")
            {
                attributes = new List<Attribute>()
                {
                    new RequiredAttribute()
                    {
                        ErrorMessage = "No one works for free!! Give him some money."
                    }
                };
            }
            return base.GetValidators(metadata, context, attributes);
        }

      
    }




Register in Global.asax:
Any customization or extension should be registered. Or You get no cookie!!