public void GetModelValidator_DoesNotReadPropertyValues() { // Arrange IEnumerable <ModelValidatorProvider> validatorProviders = new[] { new ObservableModelValidatorProvider() }; ObservableModel model = new ObservableModel(); ModelMetadata metadata = new EmptyModelMetadataProvider().GetMetadataForType(() => model, typeof(ObservableModel)); // Act ModelValidator validator = ModelValidator.GetModelValidator(validatorProviders); ModelValidationResult[] results = validator.Validate(metadata, model).ToArray(); // Assert Assert.False(model.PropertyWasRead()); }
private void ValidateThis(HttpActionContext actionContext, ModelValidationNode parentNode) { ModelStateDictionary modelState = actionContext.ModelState; if (!modelState.IsValidField(ModelStateKey)) { return; // short-circuit } // If 'this' is null and there is no parent, we cannot validate, and // the DataAnnotationsModelValidator will throw. So we intercept here // to provide a catch-all value-required validation error if (parentNode == null && ModelMetadata.Model == null) { string trueModelStateKey = ModelBindingHelper.CreatePropertyModelName( ModelStateKey, ModelMetadata.GetDisplayName() ); modelState.AddModelError(trueModelStateKey, SRResources.Validation_ValueNotFound); return; } _validators = actionContext.GetValidators(ModelMetadata); object container = TryConvertContainerToMetadataType(parentNode); // Optimize for the common case where the validators are in an array ModelValidator[] validators = _validators.AsArray(); for (int i = 0; i < validators.Length; i++) { ModelValidator validator = validators[i]; foreach ( ModelValidationResult validationResult in validator.Validate( ModelMetadata, container ) ) { string trueModelStateKey = ModelBindingHelper.CreatePropertyModelName( ModelStateKey, validationResult.MemberName ); modelState.AddModelError(trueModelStateKey, validationResult.Message); } } }
protected virtual void SetProperty(HttpActionContext actionContext, ModelBindingContext bindingContext, ModelMetadata propertyMetadata, ComplexModelDtoResult dtoResult, ModelValidator requiredValidator) { PropertyDescriptor propertyDescriptor = TypeDescriptorHelper.Get(bindingContext.ModelType).GetProperties().Find(propertyMetadata.PropertyName, true /* ignoreCase */); if (propertyDescriptor == null || propertyDescriptor.IsReadOnly) { return; // nothing to do } object value = dtoResult.Model ?? GetPropertyDefaultValue(propertyDescriptor); propertyMetadata.Model = value; // 'Required' validators need to run first so that we can provide useful error messages if // the property setters throw, e.g. if we're setting entity keys to null. See comments in // DefaultModelBinder.SetProperty() for more information. if (value == null) { string modelStateKey = dtoResult.ValidationNode.ModelStateKey; if (bindingContext.ModelState.IsValidField(modelStateKey)) { if (requiredValidator != null) { foreach (ModelValidationResult validationResult in requiredValidator.Validate(propertyMetadata, bindingContext.Model)) { bindingContext.ModelState.AddModelError(modelStateKey, validationResult.Message); } } } } if (value != null || TypeHelper.TypeAllowsNullValue(propertyDescriptor.PropertyType)) { try { propertyDescriptor.SetValue(bindingContext.Model, value); } catch (Exception ex) { // don't display a duplicate error message if a binding error has already occurred for this field string modelStateKey = dtoResult.ValidationNode.ModelStateKey; if (bindingContext.ModelState.IsValidField(modelStateKey)) { bindingContext.ModelState.AddModelError(modelStateKey, ex); } } } else { // trying to set a non-nullable value type to null, need to make sure there's a message string modelStateKey = dtoResult.ValidationNode.ModelStateKey; if (bindingContext.ModelState.IsValidField(modelStateKey)) { dtoResult.ValidationNode.Validated += CreateNullCheckFailedHandler(propertyMetadata, value); } } }
// Returns true if validator execution adds a model error. private static bool RunValidator(ModelValidator validator, ModelBindingContext bindingContext, ModelMetadata propertyMetadata, string modelStateKey) { bool addedError = false; if (validator != null) { foreach (ModelValidationResult validationResult in validator.Validate(propertyMetadata, bindingContext.Model)) { bindingContext.ModelState.AddModelError(modelStateKey, validationResult.Message); addedError = true; } } return addedError; }