protected virtual void BindProperty(ControllerContext controllerContext, ModelBindingContext bindingContext, PropertyDescriptor propertyDescriptor) { // need to skip properties that aren't part of the request, else we might hit a StackOverflowException string fullPropertyKey = CreateSubPropertyName(bindingContext.ModelName, propertyDescriptor.Name); if (!DictionaryHelpers.DoesAnyKeyHavePrefix(bindingContext.ValueProvider, fullPropertyKey)) { return; } // call into the property's model binder IModelBinder propertyBinder = Binders.GetBinder(propertyDescriptor.PropertyType); object originalPropertyValue = propertyDescriptor.GetValue(bindingContext.Model); ModelBindingContext innerBindingContext = new ModelBindingContext() { Model = originalPropertyValue, ModelName = fullPropertyKey, ModelState = bindingContext.ModelState, ModelType = propertyDescriptor.PropertyType, ValueProvider = bindingContext.ValueProvider }; object newPropertyValue = propertyBinder.BindModel(controllerContext, innerBindingContext); // validation if (OnPropertyValidating(controllerContext, bindingContext, propertyDescriptor, newPropertyValue)) { SetProperty(controllerContext, bindingContext, propertyDescriptor, newPropertyValue); OnPropertyValidated(controllerContext, bindingContext, propertyDescriptor, newPropertyValue); } }
public bool IsValidField(string key) { if (key == null) { throw new ArgumentNullException("key"); } // if the key is not found in the dictionary, we just say that it's valid (since there are no errors) return(DictionaryHelpers.FindKeysWithPrefix(this, key).All(entry => entry.Value.Errors.Count == 0)); }
public virtual object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext) { if (bindingContext == null) { throw new ArgumentNullException("bindingContext"); } bool performedFallback = false; if (!String.IsNullOrEmpty(bindingContext.ModelName) && !DictionaryHelpers.DoesAnyKeyHavePrefix(bindingContext.ValueProvider, bindingContext.ModelName)) { // We couldn't find any entry that began with the prefix. If this is the top-level element, fall back // to the empty prefix. if (bindingContext.FallbackToEmptyPrefix) { bindingContext = new ModelBindingContext() { Model = bindingContext.Model, ModelState = bindingContext.ModelState, ModelType = bindingContext.ModelType, PropertyFilter = bindingContext.PropertyFilter, ValueProvider = bindingContext.ValueProvider }; performedFallback = true; } else { return(null); } } // Simple model = int, string, etc.; determined by calling TypeConverter.CanConvertFrom(typeof(string)) // or by seeing if a value in the request exactly matches the name of the model we're binding. // Complex type = everything else. if (!performedFallback) { ValueProviderResult vpResult; bindingContext.ValueProvider.TryGetValue(bindingContext.ModelName, out vpResult); if (vpResult != null) { return(BindSimpleModel(controllerContext, bindingContext, vpResult)); } } if (TypeDescriptor.GetConverter(bindingContext.ModelType).CanConvertFrom(typeof(string))) { return(null); } return(BindComplexModel(controllerContext, bindingContext)); }
internal object UpdateCollection(ControllerContext controllerContext, ModelBindingContext bindingContext, Type elementType) { IModelBinder elementBinder = Binders.GetBinder(elementType); // build up a list of items from the request List <object> modelList = new List <object>(); for (int currentIndex = 0; ; currentIndex++) { string subIndexKey = CreateSubIndexName(bindingContext.ModelName, currentIndex); if (!DictionaryHelpers.DoesAnyKeyHavePrefix(bindingContext.ValueProvider, subIndexKey)) { // we ran out of elements to pull break; } ModelBindingContext innerContext = new ModelBindingContext() { ModelName = subIndexKey, ModelState = bindingContext.ModelState, ModelType = elementType, PropertyFilter = bindingContext.PropertyFilter, ValueProvider = bindingContext.ValueProvider }; object thisElement = elementBinder.BindModel(controllerContext, innerContext); // we need to merge model errors up VerifyValueUsability(controllerContext, bindingContext.ModelState, subIndexKey, elementType, thisElement); modelList.Add(thisElement); } // if there weren't any elements at all in the request, just return if (modelList.Count == 0) { return(null); } // replace the original collection object collection = bindingContext.Model; CollectionHelpers.ReplaceCollection(elementType, collection, modelList); return(collection); }
internal object UpdateDictionary(ControllerContext controllerContext, ModelBindingContext bindingContext, Type keyType, Type valueType) { IModelBinder keyBinder = Binders.GetBinder(keyType); IModelBinder valueBinder = Binders.GetBinder(valueType); // build up a list of items from the request List <KeyValuePair <object, object> > modelList = new List <KeyValuePair <object, object> >(); for (int currentIndex = 0; ; currentIndex++) { string subIndexKey = CreateSubIndexName(bindingContext.ModelName, currentIndex); string keyFieldKey = CreateSubPropertyName(subIndexKey, "key"); string valueFieldKey = CreateSubPropertyName(subIndexKey, "value"); if (!(DictionaryHelpers.DoesAnyKeyHavePrefix(bindingContext.ValueProvider, keyFieldKey) && DictionaryHelpers.DoesAnyKeyHavePrefix(bindingContext.ValueProvider, valueFieldKey))) { // we ran out of elements to pull break; } // bind the key ModelBindingContext keyBindingContext = new ModelBindingContext() { ModelName = keyFieldKey, ModelState = bindingContext.ModelState, ModelType = keyType, ValueProvider = bindingContext.ValueProvider }; object thisKey = keyBinder.BindModel(controllerContext, keyBindingContext); // we need to merge model errors up VerifyValueUsability(controllerContext, bindingContext.ModelState, keyFieldKey, keyType, thisKey); if (!keyType.IsInstanceOfType(thisKey)) { // we can't add an invalid key, so just move on continue; } // bind the value ModelBindingContext valueBindingContext = new ModelBindingContext() { ModelName = valueFieldKey, ModelState = bindingContext.ModelState, ModelType = valueType, PropertyFilter = bindingContext.PropertyFilter, ValueProvider = bindingContext.ValueProvider }; object thisValue = valueBinder.BindModel(controllerContext, valueBindingContext); // we need to merge model errors up VerifyValueUsability(controllerContext, bindingContext.ModelState, valueFieldKey, valueType, thisValue); KeyValuePair <object, object> kvp = new KeyValuePair <object, object>(thisKey, thisValue); modelList.Add(kvp); } // if there weren't any elements at all in the request, just return if (modelList.Count == 0) { return(null); } // replace the original collection object dictionary = bindingContext.Model; CollectionHelpers.ReplaceDictionary(keyType, valueType, dictionary, modelList); return(dictionary); }