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);
            }
        }
Exemplo n.º 2
0
        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);
        }