VAB not recognizing web.config validators from DefaultModelBinder

Topics: Validation Application Block
Feb 10, 2010 at 11:49 PM

The validation application block is working for me when it called from a controller help function:

    public bool ValidateOrder (IOrder order)
    //          =============
    {
        ValidationResults objValidationResults = Validation.Validate(order, "Rule Set");
        if (objValidationResults.Count > 0)
        {
            foreach (var objValRslt in objValidationResults)
            {
                _modelState.AddModelError(objValRslt.Key, objValRslt.Message);
            }
            return false;
        }
        return true;
    }


The validators from the web config file look like this:

 

  <validation>
    <type assemblyName="DgrMvc, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null"
      name="DgrMvcModels.Order">
      <ruleset name="Rule Set">
        <properties>
          <property name="Customer">
            <validator lowerBound="1" lowerBoundType="Inclusive" upperBound="0"
              upperBoundType="Ignore" negated="false" messageTemplate="Customer length can NOT be zero" messageTemplateResourceName=""
              messageTemplateResourceType="" tag="" type="Microsoft.Practices.EnterpriseLibrary.Validation.Validators.StringLengthValidator, Microsoft.Practices.EnterpriseLibrary.Validation, Version=4.0.0.0, Culture=neutral, PublicKeyToken=null"
              name="String Length Validator" />
          </property>
		.
		.
		.
        </properties>
      </ruleset>
    </type>
  </validation>

After some internet research, it looks like including the same code inside of a
Default Model Binder would be cleaner. Therefore:

public class VabModelBinder : DefaultModelBinder
{
    protected override void OnModelUpdated(ControllerContext controllerContext,
                                            ModelBindingContext bindingContext)
    {
        ValidationResults objValidationResults = Validation.Validate(bindingContext.Model, "Rule Set");
        if (objValidationResults.Count > 0)
        {
            foreach (var objValRslt in objValidationResults)
            {
                bindingContext.ModelState.AddModelError(objValRslt.Key, objValRslt.Message);
            }
        }
    }
 
    protected override void OnPropertyValidated(ControllerContext controllerContext,
            ModelBindingContext bindingContext, PropertyDescriptor propertyDescriptor,
            object value)
    {
        // Do Nothing;
    }
}

with the Application_Start addition of:

ModelBinders.Binders.DefaultBinder = new VabModelBinder();

The problem that I'm having is with the VabModleBinder Validation.Validate call.  The 
bindingContext.Model is assigned the correct values from the form but
objValidationResults doesn't contain any errors.

After setting up a debug version of the VAB, I can track my problem to the DoValidate internal
method in the AndCompositeValidator class. The DefaultModelBinder process doesn't have any
data in the this.validators field. The first process that works (ie: controller helper function)
has the validators from the web.config file in the this.validators field.

I've setup something incorrectly. Does anyone have any suggestions?
Thanks,
Marty
Feb 11, 2010 at 3:39 AM

There's no validators because you tried to validate an object of type object.

You should create a validator first based on the bindingContext.Model's specific type:

Validator validator = ValidationFactory.CreateValidator(bindingContext.Model.GetType());

ValidatonResults result = validator.Validate(bindingContext.Model);

 

Sarah Urmeneta
Global Technology and Solutions
Avanade, Inc.
entlib.support@avanade.com

Feb 11, 2010 at 1:31 PM

Thanks, after adding "Rule Set" as the second parameter to CreateValidator, it worked great.