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