Example #1
0
        internal static void GetRequiredPropertiesCollection(Type modelType, out HashSet <string> requiredProperties, out HashSet <string> skipProperties)
        {
            requiredProperties = new HashSet <string>(StringComparer.OrdinalIgnoreCase);
            skipProperties     = new HashSet <string>(StringComparer.OrdinalIgnoreCase);

            // Use attributes on the property before attributes on the type.
            ICustomTypeDescriptor        modelDescriptor     = TypeDescriptorHelper.Get(modelType);
            PropertyDescriptorCollection propertyDescriptors = modelDescriptor.GetProperties();
            BindingBehaviorAttribute     typeAttr            = modelDescriptor.GetAttributes().OfType <BindingBehaviorAttribute>().SingleOrDefault();

            foreach (PropertyDescriptor propertyDescriptor in propertyDescriptors)
            {
                BindingBehaviorAttribute propAttr    = propertyDescriptor.Attributes.OfType <BindingBehaviorAttribute>().SingleOrDefault();
                BindingBehaviorAttribute workingAttr = propAttr ?? typeAttr;
                if (workingAttr != null)
                {
                    switch (workingAttr.Behavior)
                    {
                    case BindingBehavior.Required:
                        requiredProperties.Add(propertyDescriptor.Name);
                        break;

                    case BindingBehavior.Never:
                        skipProperties.Add(propertyDescriptor.Name);
                        break;
                    }
                }
            }
        }
        private static bool TryGetProviderFromAttributes(Type modelType, out ModelBinderProvider provider)
        {
            ExtensibleModelBinderAttribute attr = TypeDescriptorHelper.Get(modelType).GetAttributes().OfType <ExtensibleModelBinderAttribute>().FirstOrDefault();

            if (attr == null)
            {
                provider = null;
                return(false);
            }

            if (typeof(ModelBinderProvider).IsAssignableFrom(attr.BinderType))
            {
                provider = (ModelBinderProvider)SecurityUtils.SecureCreateInstance(attr.BinderType);
            }
            else if (typeof(IModelBinder).IsAssignableFrom(attr.BinderType))
            {
                Type         closedBinderType = (attr.BinderType.IsGenericTypeDefinition) ? attr.BinderType.MakeGenericType(modelType.GetGenericArguments()) : attr.BinderType;
                IModelBinder binderInstance   = (IModelBinder)SecurityUtils.SecureCreateInstance(closedBinderType);
                provider = new SimpleModelBinderProvider(modelType, binderInstance)
                {
                    SuppressPrefixCheck = attr.SuppressPrefixCheck
                };
            }
            else
            {
                string errorMessage = String.Format(CultureInfo.CurrentCulture, SR.GetString(SR.ModelBinderProviderCollection_InvalidBinderType),
                                                    attr.BinderType, typeof(ModelBinderProvider), typeof(IModelBinder));
                throw new InvalidOperationException(errorMessage);
            }

            return(true);
        }
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);
                }
            }
        }
Example #4
0
 protected virtual ICustomTypeDescriptor GetTypeDescriptor(Type type)
 {
     return(TypeDescriptorHelper.Get(type));
 }