protected virtual object CreateModel(
            ControllerContext controllerContext,
            ExtensibleModelBindingContext bindingContext
            )
        {
            // If the Activator throws an exception, we want to propagate it back up the call stack, since the application
            // developer should know that this was an invalid type to try to bind to.
            try
            {
                return(Activator.CreateInstance(bindingContext.ModelType));
            }
            catch (MissingMethodException exception)
            {
                // Ensure thrown exception contains the type name.  Might be down a few levels.
                MissingMethodException replacementException =
                    ModelBinderUtil.EnsureDebuggableException(
                        exception,
                        bindingContext.ModelType.FullName
                        );
                if (replacementException != null)
                {
                    throw replacementException;
                }

                throw;
            }
        }
        public override IExtensibleModelBinder GetBinder(ControllerContext controllerContext, ExtensibleModelBindingContext bindingContext)
        {
            ModelBinderUtil.ValidateBindingContext(bindingContext);

            Type[] typeArguments = null;
            if (ModelType.IsInterface)
            {
                Type matchingClosedInterface = TypeHelpers.ExtractGenericInterface(bindingContext.ModelType, ModelType);
                if (matchingClosedInterface != null)
                {
                    typeArguments = matchingClosedInterface.GetGenericArguments();
                }
            }
            else
            {
                typeArguments = TypeHelpers.GetTypeArgumentsIfMatch(bindingContext.ModelType, ModelType);
            }

            if (typeArguments != null)
            {
                if (SuppressPrefixCheck || bindingContext.ValueProvider.ContainsPrefix(bindingContext.ModelName))
                {
                    return(_modelBinderFactory(typeArguments));
                }
            }

            return(null);
        }
示例#3
0
        public virtual bool BindModel(
            ControllerContext controllerContext,
            ExtensibleModelBindingContext bindingContext
            )
        {
            ModelBinderUtil.ValidateBindingContext(bindingContext);

            ValueProviderResult valueProviderResult = bindingContext.ValueProvider.GetValue(
                bindingContext.ModelName
                );
            List <TElement> boundCollection =
                (valueProviderResult != null)
                    ? BindSimpleCollection(
                    controllerContext,
                    bindingContext,
                    valueProviderResult.RawValue,
                    valueProviderResult.Culture
                    )
                    : BindComplexCollection(controllerContext, bindingContext);

            bool retVal = CreateOrReplaceCollection(
                controllerContext,
                bindingContext,
                boundCollection
                );

            return(retVal);
        }
        public bool BindModel(ControllerContext controllerContext, ExtensibleModelBindingContext bindingContext)
        {
            ModelBinderUtil.ValidateBindingContext(bindingContext, typeof(ComplexModelDto), false /* allowNullModel */);

            ComplexModelDto dto = (ComplexModelDto)bindingContext.Model;

            foreach (ModelMetadata propertyMetadata in dto.PropertyMetadata)
            {
                ExtensibleModelBindingContext propertyBindingContext = new ExtensibleModelBindingContext(bindingContext)
                {
                    ModelMetadata = propertyMetadata,
                    ModelName     = ModelBinderUtil.CreatePropertyModelName(bindingContext.ModelName, propertyMetadata.PropertyName)
                };

                // bind and propagate the values
                IExtensibleModelBinder propertyBinder = bindingContext.ModelBinderProviders.GetBinder(controllerContext, propertyBindingContext);
                if (propertyBinder != null)
                {
                    if (propertyBinder.BindModel(controllerContext, propertyBindingContext))
                    {
                        dto.Results[propertyMetadata] = new ComplexModelDtoResult(propertyBindingContext.Model, propertyBindingContext.ValidationNode);
                    }
                    else
                    {
                        dto.Results[propertyMetadata] = null;
                    }
                }
            }

            return(true);
        }
        public override IExtensibleModelBinder GetBinder(
            ControllerContext controllerContext,
            ExtensibleModelBindingContext bindingContext
            )
        {
            ModelBinderUtil.ValidateBindingContext(bindingContext);

            ValueProviderResult valueProviderResult = bindingContext.ValueProvider.GetValue(
                bindingContext.ModelName
                );

            if (valueProviderResult == null)
            {
                return(null); // no value to convert
            }

            if (
                !TypeDescriptor
                .GetConverter(bindingContext.ModelType)
                .CanConvertFrom(typeof(string))
                )
            {
                return(null); // this type cannot be converted
            }

            return(new TypeConverterModelBinder());
        }
        internal void ProcessDto(ControllerContext controllerContext, ExtensibleModelBindingContext bindingContext, ComplexModelDto dto)
        {
            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(dto.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 dto.Results)
            {
                ModelMetadata propertyMetadata = entry.Key;

                ComplexModelDtoResult dtoResult = entry.Value;
                if (dtoResult != null)
                {
                    SetProperty(controllerContext, bindingContext, propertyMetadata, dtoResult);
                    bindingContext.ValidationNode.ChildNodes.Add(dtoResult.ValidationNode);
                }
            }
        }
            public bool BindModel(ControllerContext controllerContext, ExtensibleModelBindingContext bindingContext)
            {
                ModelBinderUtil.ValidateBindingContext(bindingContext);
                ValueProviderResult valueProviderResult = bindingContext.ValueProvider.GetValue(bindingContext.ModelName);

                // case 1: there was no <input ... /> element containing this data
                if (valueProviderResult == null)
                {
                    return(false);
                }

                string base64String = (string)valueProviderResult.ConvertTo(typeof(string));

                // case 2: there was an <input ... /> element but it was left blank
                if (String.IsNullOrEmpty(base64String))
                {
                    return(false);
                }

                // Future proofing. If the byte array is actually an instance of System.Data.Linq.Binary
                // then we need to remove these quotes put in place by the ToString() method.
                string realValue = base64String.Replace("\"", String.Empty);

                try
                {
                    bindingContext.Model = ConvertByteArray(Convert.FromBase64String(realValue));
                    return(true);
                }
                catch
                {
                    // corrupt data - just ignore
                    return(false);
                }
            }
        private void ValidateThis(
            ControllerContext controllerContext,
            ModelValidationNode parentNode
            )
        {
            ModelStateDictionary modelState = controllerContext.Controller.ViewData.ModelState;

            if (!modelState.IsValidField(ModelStateKey))
            {
                return; // short-circuit
            }

            object container = TryConvertContainerToMetadataType(parentNode);

            foreach (ModelValidator validator in ModelMetadata.GetValidators(controllerContext))
            {
                foreach (ModelValidationResult validationResult in validator.Validate(container))
                {
                    string trueModelStateKey = ModelBinderUtil.CreatePropertyModelName(
                        ModelStateKey,
                        validationResult.MemberName
                        );
                    modelState.AddModelError(trueModelStateKey, validationResult.Message);
                }
            }
        }
        internal static ValueProviderResult GetCompatibleValueProviderResult(
            ExtensibleModelBindingContext bindingContext
            )
        {
            ModelBinderUtil.ValidateBindingContext(bindingContext);

            ValueProviderResult valueProviderResult = bindingContext.ValueProvider.GetValue(
                bindingContext.ModelName
                );

            if (valueProviderResult == null)
            {
                return(null); // the value doesn't exist
            }

            if (
                !TypeHelpers.IsCompatibleObject(
                    bindingContext.ModelType,
                    valueProviderResult.RawValue
                    )
                )
            {
                return(null); // value is of incompatible type
            }

            return(valueProviderResult);
        }
        public bool BindModel(
            ControllerContext controllerContext,
            ExtensibleModelBindingContext bindingContext
            )
        {
            ModelBinderUtil.ValidateBindingContext(
                bindingContext,
                typeof(KeyValuePair <TKey, TValue>),
                true /* allowNullModel */
                );

            TKey key;
            bool keyBindingSucceeded = KeyValuePairModelBinderUtil.TryBindStrongModel(
                controllerContext,
                bindingContext,
                "key",
                MetadataProvider,
                out key
                );

            TValue value;
            bool   valueBindingSucceeded = KeyValuePairModelBinderUtil.TryBindStrongModel(
                controllerContext,
                bindingContext,
                "value",
                MetadataProvider,
                out value
                );

            if (keyBindingSucceeded && valueBindingSucceeded)
            {
                bindingContext.Model = new KeyValuePair <TKey, TValue>(key, value);
            }
            return(keyBindingSucceeded || valueBindingSucceeded);
        }
示例#11
0
        private void ValidateProperties(ControllerContext controllerContext)
        {
            // Based off CompositeModelValidator.
            ModelStateDictionary modelState = controllerContext.Controller.ViewData.ModelState;

            // DevDiv Bugs #227802 - Caching problem in ModelMetadata requires us to manually regenerate
            // the ModelMetadata.
            object        model           = ModelMetadata.Model;
            ModelMetadata updatedMetadata = ModelMetadataProviders.Current.GetMetadataForType(() => model, ModelMetadata.ModelType);

            foreach (ModelMetadata propertyMetadata in updatedMetadata.Properties)
            {
                // Only want to add errors to ModelState if something doesn't already exist for the property node,
                // else we could end up with duplicate or irrelevant error messages.
                string propertyKeyRoot = ModelBinderUtil.CreatePropertyModelName(ModelStateKey, propertyMetadata.PropertyName);

                if (modelState.IsValidField(propertyKeyRoot))
                {
                    foreach (ModelValidator propertyValidator in propertyMetadata.GetValidators(controllerContext))
                    {
                        foreach (ModelValidationResult propertyResult in propertyValidator.Validate(model))
                        {
                            string thisErrorKey = ModelBinderUtil.CreatePropertyModelName(propertyKeyRoot, propertyResult.MemberName);
                            modelState.AddModelError(thisErrorKey, propertyResult.Message);
                        }
                    }
                }
            }
        }
        // Used when the ValueProvider contains the collection to be bound as multiple elements, e.g. foo[0], foo[1].
        private static List <TElement> BindComplexCollection(ControllerContext controllerContext, ExtensibleModelBindingContext bindingContext)
        {
            string indexPropertyName           = ModelBinderUtil.CreatePropertyModelName(bindingContext.ModelName, "index");
            ValueProviderResult  vpResultIndex = bindingContext.ValueProvider.GetValue(indexPropertyName);
            IEnumerable <string> indexNames    = CollectionModelBinderUtil.GetIndexNamesFromValueProviderResult(vpResultIndex);

            return(BindComplexCollectionFromIndexes(controllerContext, bindingContext, indexNames));
        }
示例#13
0
        // Used when the ValueProvider contains the collection to be bound as a single element, e.g. the raw value
        // is [ "1", "2" ] and needs to be converted to an int[].
        internal static List <TElement> BindSimpleCollection(
            ControllerContext controllerContext,
            ExtensibleModelBindingContext bindingContext,
            object rawValue,
            CultureInfo culture
            )
        {
            if (rawValue == null)
            {
                return(null); // nothing to do
            }

            List <TElement> boundCollection = new List <TElement>();

            object[] rawValueArray = ModelBinderUtil.RawValueToObjectArray(rawValue);
            foreach (object rawValueElement in rawValueArray)
            {
                ExtensibleModelBindingContext innerBindingContext =
                    new ExtensibleModelBindingContext(bindingContext)
                {
                    ModelMetadata = ModelMetadataProviders.Current.GetMetadataForType(
                        null,
                        typeof(TElement)
                        ),
                    ModelName     = bindingContext.ModelName,
                    ValueProvider = new ValueProviderCollection
                    {
                        // aggregate value provider
                        new ElementalValueProvider(
                            bindingContext.ModelName,
                            rawValueElement,
                            culture
                            ), // our temporary provider goes at the front of the list
                        bindingContext.ValueProvider
                    }
                };

                object boundValue = null;
                IExtensibleModelBinder childBinder = bindingContext.ModelBinderProviders.GetBinder(
                    controllerContext,
                    innerBindingContext
                    );
                if (childBinder != null)
                {
                    if (childBinder.BindModel(controllerContext, innerBindingContext))
                    {
                        boundValue = innerBindingContext.Model;
                        bindingContext.ValidationNode.ChildNodes.Add(
                            innerBindingContext.ValidationNode
                            );
                    }
                }
                boundCollection.Add(ModelBinderUtil.CastOrDefault <TElement>(boundValue));
            }

            return(boundCollection);
        }
        public bool BindModel(
            ControllerContext controllerContext,
            ExtensibleModelBindingContext bindingContext
            )
        {
            ModelBinderUtil.ValidateBindingContext(bindingContext);

            ValueProviderResult valueProviderResult = bindingContext.ValueProvider.GetValue(
                bindingContext.ModelName
                );

            if (valueProviderResult == null)
            {
                return(false); // no entry
            }

            object newModel;

            bindingContext.ModelState.SetModelValue(bindingContext.ModelName, valueProviderResult);
            try
            {
                newModel = valueProviderResult.ConvertTo(bindingContext.ModelType);
            }
            catch (Exception ex)
            {
                if (IsFormatException(ex))
                {
                    // there was a type conversion failure
                    string errorString = ModelBinderConfig.TypeConversionErrorMessageProvider(
                        controllerContext,
                        bindingContext.ModelMetadata,
                        valueProviderResult.AttemptedValue
                        );
                    if (errorString != null)
                    {
                        bindingContext.ModelState.AddModelError(
                            bindingContext.ModelName,
                            errorString
                            );
                    }
                }
                else
                {
                    bindingContext.ModelState.AddModelError(bindingContext.ModelName, ex);
                }
                return(false);
            }

            ModelBinderUtil.ReplaceEmptyStringWithNull(bindingContext.ModelMetadata, ref newModel);
            bindingContext.Model = newModel;
            return(true);
        }
示例#15
0
        public override IExtensibleModelBinder GetBinder(ControllerContext controllerContext, ExtensibleModelBindingContext bindingContext)
        {
            ModelBinderUtil.ValidateBindingContext(bindingContext);

            if (!bindingContext.ModelMetadata.IsReadOnly && bindingContext.ModelType.IsArray &&
                bindingContext.ValueProvider.ContainsPrefix(bindingContext.ModelName))
            {
                Type elementType = bindingContext.ModelType.GetElementType();
                return((IExtensibleModelBinder)Activator.CreateInstance(typeof(ArrayModelBinder <>).MakeGenericType(elementType)));
            }

            return(null);
        }
        public virtual bool BindModel(ControllerContext controllerContext, ExtensibleModelBindingContext bindingContext)
        {
            ModelBinderUtil.ValidateBindingContext(bindingContext);

            EnsureModel(controllerContext, bindingContext);
            IEnumerable <ModelMetadata> propertyMetadatas = GetMetadataForProperties(controllerContext, bindingContext);
            ComplexModelDto             dto = CreateAndPopulateDto(controllerContext, bindingContext, propertyMetadatas);

            // post-processing, e.g. property setters and hooking up validation
            ProcessDto(controllerContext, bindingContext, dto);
            bindingContext.ValidationNode.ValidateAllProperties = true; // complex models require full validation
            return(true);
        }
示例#17
0
        public override IExtensibleModelBinder GetBinder(ControllerContext controllerContext, ExtensibleModelBindingContext bindingContext)
        {
            ModelBinderUtil.ValidateBindingContext(bindingContext);

            if (bindingContext.ValueProvider.ContainsPrefix(bindingContext.ModelName))
            {
                return(CollectionModelBinderUtil.GetGenericBinder(typeof(IDictionary <,>), typeof(Dictionary <,>), typeof(DictionaryModelBinder <,>), bindingContext.ModelMetadata));
            }
            else
            {
                return(null);
            }
        }
        internal static List <TElement> BindComplexCollectionFromIndexes(ControllerContext controllerContext, ExtensibleModelBindingContext bindingContext, IEnumerable <string> indexNames)
        {
            bool indexNamesIsFinite;

            if (indexNames != null)
            {
                indexNamesIsFinite = true;
            }
            else
            {
                indexNamesIsFinite = false;
                indexNames         = CollectionModelBinderUtil.GetZeroBasedIndexes();
            }

            List <TElement> boundCollection = new List <TElement>();

            foreach (string indexName in indexNames)
            {
                string fullChildName = ModelBinderUtil.CreateIndexModelName(bindingContext.ModelName, indexName);
                ExtensibleModelBindingContext childBindingContext = new ExtensibleModelBindingContext(bindingContext)
                {
                    ModelMetadata = ModelMetadataProviders.Current.GetMetadataForType(null, typeof(TElement)),
                    ModelName     = fullChildName
                };

                object boundValue = null;
                IExtensibleModelBinder childBinder = bindingContext.ModelBinderProviders.GetBinder(controllerContext, childBindingContext);
                if (childBinder != null)
                {
                    if (childBinder.BindModel(controllerContext, childBindingContext))
                    {
                        boundValue = childBindingContext.Model;

                        // merge validation up
                        bindingContext.ValidationNode.ChildNodes.Add(childBindingContext.ValidationNode);
                    }
                }
                else
                {
                    // should we even bother continuing?
                    if (!indexNamesIsFinite)
                    {
                        break;
                    }
                }

                boundCollection.Add(ModelBinderUtil.CastOrDefault <TElement>(boundValue));
            }

            return(boundCollection);
        }
        public override IExtensibleModelBinder GetBinder(ControllerContext controllerContext, ExtensibleModelBindingContext bindingContext)
        {
            ModelBinderUtil.ValidateBindingContext(bindingContext);

            if (bindingContext.ModelType == ModelType)
            {
                if (SuppressPrefixCheck || bindingContext.ValueProvider.ContainsPrefix(bindingContext.ModelName))
                {
                    return(_modelBinderFactory());
                }
            }

            return(null);
        }
        public GenericModelBinderProvider(Type modelType, Type modelBinderType)
        {
            // The binder can be a closed type, in which case it will be instantiated directly. If the binder
            // is an open type, the type arguments will be determined at runtime and the corresponding closed
            // type instantiated.

            if (modelType == null)
            {
                throw new ArgumentNullException("modelType");
            }
            if (modelBinderType == null)
            {
                throw new ArgumentNullException("modelBinderType");
            }

            ValidateParameters(modelType, modelBinderType);
            bool modelBinderTypeIsOpenGeneric = modelBinderType.IsGenericTypeDefinition;

            _modelType          = modelType;
            _modelBinderFactory = typeArguments =>
            {
                Type closedModelBinderType =
                    (modelBinderTypeIsOpenGeneric)
                        ? modelBinderType.MakeGenericType(typeArguments)
                        : modelBinderType;
                try
                {
                    return((IExtensibleModelBinder)Activator.CreateInstance(closedModelBinderType));
                }
                catch (MissingMethodException exception)
                {
                    // Ensure thrown exception contains the type name.  Might be down a few levels.
                    MissingMethodException replacementException =
                        ModelBinderUtil.EnsureDebuggableException(
                            exception,
                            closedModelBinderType.FullName
                            );
                    if (replacementException != null)
                    {
                        throw replacementException;
                    }

                    throw;
                }
            };
        }
        public bool BindModel(ControllerContext controllerContext, ExtensibleModelBindingContext bindingContext)
        {
            ValueProviderResult valueProviderResult = GetCompatibleValueProviderResult(bindingContext);

            if (valueProviderResult == null)
            {
                return(false); // conversion would have failed
            }

            bindingContext.ModelState.SetModelValue(bindingContext.ModelName, valueProviderResult);
            object model = valueProviderResult.RawValue;

            ModelBinderUtil.ReplaceEmptyStringWithNull(bindingContext.ModelMetadata, ref model);
            bindingContext.Model = model;

            return(true);
        }
示例#22
0
        public override IExtensibleModelBinder GetBinder(ControllerContext controllerContext, ExtensibleModelBindingContext bindingContext)
        {
            ModelBinderUtil.ValidateBindingContext(bindingContext);

            string keyFieldName   = ModelBinderUtil.CreatePropertyModelName(bindingContext.ModelName, "key");
            string valueFieldName = ModelBinderUtil.CreatePropertyModelName(bindingContext.ModelName, "value");

            if (bindingContext.ValueProvider.ContainsPrefix(keyFieldName) && bindingContext.ValueProvider.ContainsPrefix(valueFieldName))
            {
                return(ModelBinderUtil.GetPossibleBinderInstance(bindingContext.ModelType, typeof(KeyValuePair <,>) /* supported model type */, typeof(KeyValuePairModelBinder <,>) /* binder type */));
            }
            else
            {
                // 'key' or 'value' missing
                return(null);
            }
        }
        public override IExtensibleModelBinder GetBinder(ControllerContext controllerContext, ExtensibleModelBindingContext bindingContext)
        {
            ModelBinderUtil.ValidateBindingContext(bindingContext);

            if (!bindingContext.ValueProvider.ContainsPrefix(bindingContext.ModelName))
            {
                // no values to bind
                return(null);
            }

            if (bindingContext.ModelType == typeof(ComplexModelDto))
            {
                // forbidden type - will cause a stack overflow if we try binding this type
                return(null);
            }

            return(new MutableObjectModelBinder());
        }
        private static object CreateInstance(Type type)
        {
            try
            {
                return(Activator.CreateInstance(type));
            }
            catch (MissingMethodException exception)
            {
                // Ensure thrown exception contains the type name.  Might be down a few levels.
                MissingMethodException replacementException =
                    ModelBinderUtil.EnsureDebuggableException(exception, type.FullName);
                if (replacementException != null)
                {
                    throw replacementException;
                }

                throw;
            }
        }
        public static bool TryBindStrongModel <TModel>(
            ControllerContext controllerContext,
            ExtensibleModelBindingContext parentBindingContext,
            string propertyName,
            ModelMetadataProvider metadataProvider,
            out TModel model
            )
        {
            ExtensibleModelBindingContext propertyBindingContext =
                new ExtensibleModelBindingContext(parentBindingContext)
            {
                ModelMetadata = metadataProvider.GetMetadataForType(null, typeof(TModel)),
                ModelName     = ModelBinderUtil.CreatePropertyModelName(
                    parentBindingContext.ModelName,
                    propertyName
                    )
            };

            IExtensibleModelBinder binder = parentBindingContext.ModelBinderProviders.GetBinder(
                controllerContext,
                propertyBindingContext
                );

            if (binder != null)
            {
                if (binder.BindModel(controllerContext, propertyBindingContext))
                {
                    object untypedModel = propertyBindingContext.Model;
                    model = ModelBinderUtil.CastOrDefault <TModel>(untypedModel);
                    parentBindingContext.ValidationNode.ChildNodes.Add(
                        propertyBindingContext.ValidationNode
                        );
                    return(true);
                }
            }

            model = default(TModel);
            return(false);
        }