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());
        }
예제 #2
0
        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;
        }