Example #1
0
        internal void ProcessComplexModel(ModelBindingExecutionContext modelBindingExecutionContext, ModelBindingContext bindingContext, ComplexModel complexModel)
        {
            HashSet <string> requiredProperties;
            HashSet <string> skipProperties;

            GetRequiredPropertiesCollection(bindingContext.ModelType, out requiredProperties, out skipProperties);

            // Are all of the required fields accounted for?
            HashSet <string> missingRequiredProperties = new HashSet <string>(requiredProperties);

            missingRequiredProperties.ExceptWith(complexModel.Results.Select(r => r.Key.PropertyName));
            string missingPropertyName = missingRequiredProperties.FirstOrDefault();

            if (missingPropertyName != null)
            {
                string fullPropertyKey = ModelBinderUtil.CreatePropertyModelName(bindingContext.ModelName, missingPropertyName);
                throw Error.BindingBehavior_ValueNotFound(fullPropertyKey);
            }

            // for each property that was bound, call the setter, recording exceptions as necessary
            foreach (var entry in complexModel.Results)
            {
                ModelMetadata propertyMetadata = entry.Key;

                ComplexModelResult complexModelResult = entry.Value;
                if (complexModelResult != null)
                {
                    SetProperty(modelBindingExecutionContext, bindingContext, propertyMetadata, complexModelResult);
                    bindingContext.ValidationNode.ChildNodes.Add(complexModelResult.ValidationNode);
                }
            }
        }
        protected virtual void SetProperty(ModelBindingExecutionContext modelBindingExecutionContext, ModelBindingContext bindingContext, ModelMetadata propertyMetadata, ComplexModelResult complexModelResult) {
            PropertyDescriptor propertyDescriptor = TypeDescriptorHelper.Get(bindingContext.ModelType).GetProperties().Find(propertyMetadata.PropertyName, true /* ignoreCase */);
            if (propertyDescriptor == null || propertyDescriptor.IsReadOnly) {
                return; // nothing to do
            }

            object value = complexModelResult.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 = complexModelResult.ValidationNode.ModelStateKey;
                if (bindingContext.ModelState.IsValidField(modelStateKey)) {
                    ModelValidator requiredValidator = ModelValidatorProviders.Providers.GetValidators(propertyMetadata, modelBindingExecutionContext).Where(v => v.IsRequired).FirstOrDefault();
                    if (requiredValidator != null) {
                        foreach (ModelValidationResult validationResult in requiredValidator.Validate(bindingContext.Model)) {
                            bindingContext.ModelState.AddModelError(modelStateKey, validationResult.Message);
                        }
                    }
                }
            }

            if (value != null || TypeHelpers.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 = complexModelResult.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 = complexModelResult.ValidationNode.ModelStateKey;
                if (bindingContext.ModelState.IsValidField(modelStateKey)) {
                    complexModelResult.ValidationNode.Validated += CreateNullCheckFailedHandler(modelBindingExecutionContext, propertyMetadata, value);
                }
            }
        }
Example #3
0
        protected virtual void SetProperty(ModelBindingExecutionContext modelBindingExecutionContext, ModelBindingContext bindingContext, ModelMetadata propertyMetadata, ComplexModelResult complexModelResult)
        {
            PropertyDescriptor propertyDescriptor = TypeDescriptorHelper.Get(bindingContext.ModelType).GetProperties().Find(propertyMetadata.PropertyName, true /* ignoreCase */);

            if (propertyDescriptor == null || propertyDescriptor.IsReadOnly)
            {
                return; // nothing to do
            }

            object value = complexModelResult.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 = complexModelResult.ValidationNode.ModelStateKey;
                if (bindingContext.ModelState.IsValidField(modelStateKey))
                {
                    ModelValidator requiredValidator = ModelValidatorProviders.Providers.GetValidators(propertyMetadata, modelBindingExecutionContext).Where(v => v.IsRequired).FirstOrDefault();
                    if (requiredValidator != null)
                    {
                        foreach (ModelValidationResult validationResult in requiredValidator.Validate(bindingContext.Model))
                        {
                            bindingContext.ModelState.AddModelError(modelStateKey, validationResult.Message);
                        }
                    }
                }
            }

            if (value != null || TypeHelpers.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 = complexModelResult.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 = complexModelResult.ValidationNode.ModelStateKey;
                if (bindingContext.ModelState.IsValidField(modelStateKey))
                {
                    complexModelResult.ValidationNode.Validated += CreateNullCheckFailedHandler(modelBindingExecutionContext, propertyMetadata, value);
                }
            }
        }