public virtual async Task <bool> BindModelAsync(ModelBindingContext bindingContext)
        {
            ModelBindingHelper.ValidateBindingContext(bindingContext);
            if (!CanBindType(bindingContext.ModelType))
            {
                return(false);
            }

            var mutableObjectBinderContext = new MutableObjectBinderContext()
            {
                ModelBindingContext = bindingContext,
                PropertyMetadata    = GetMetadataForProperties(bindingContext),
            };

            if (!(await CanCreateModel(mutableObjectBinderContext)))
            {
                return(false);
            }

            EnsureModel(bindingContext);
            var dto = await CreateAndPopulateDto(bindingContext, mutableObjectBinderContext.PropertyMetadata);

            // post-processing, e.g. property setters and hooking up validation
            ProcessDto(bindingContext, dto);
            // complex models require full validation
            bindingContext.ValidationNode.ValidateAllProperties = true;
            return(true);
        }
示例#2
0
        public async Task <bool> BindModelAsync(ModelBindingContext bindingContext)
        {
            ModelBindingHelper.ValidateBindingContext(bindingContext);

            if (!ValueProviderResult.CanConvertFromString(bindingContext.ModelType))
            {
                // this type cannot be converted
                return(false);
            }

            var valueProviderResult = await bindingContext.ValueProvider.GetValueAsync(bindingContext.ModelName);

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

            object newModel;

            bindingContext.ModelState.SetModelValue(bindingContext.ModelName, valueProviderResult);
            try
            {
                newModel = valueProviderResult.ConvertTo(bindingContext.ModelType);
                ModelBindingHelper.ReplaceEmptyStringWithNull(bindingContext.ModelMetadata, ref newModel);
                bindingContext.Model = newModel;
            }
            catch (Exception ex)
            {
                ModelBindingHelper.AddModelErrorBasedOnExceptionType(bindingContext, ex);
            }

            return(true);
        }
示例#3
0
        /// <inheritdoc />
        public Task <ModelBindingResult> BindModelAsync(ModelBindingContext bindingContext)
        {
            if (bindingContext == null)
            {
                throw new ArgumentNullException(nameof(bindingContext));
            }

            ModelBindingHelper.ValidateBindingContext(bindingContext);
            if (!CanBindType(bindingContext.ModelMetadata))
            {
                return(ModelBindingResult.NoResultAsync);
            }

            var mutableObjectBinderContext = new MutableObjectBinderContext()
            {
                ModelBindingContext = bindingContext,
                PropertyMetadata    = GetMetadataForProperties(bindingContext).ToArray(),
            };

            if (!(CanCreateModel(mutableObjectBinderContext)))
            {
                return(ModelBindingResult.NoResultAsync);
            }

            return(BindModelCoreAsync(bindingContext, mutableObjectBinderContext));
        }
示例#4
0
        /// <inheritdoc />
        public virtual async Task <ModelBindingResult> BindModelAsync([NotNull] ModelBindingContext bindingContext)
        {
            ModelBindingHelper.ValidateBindingContext(bindingContext);
            if (!CanBindType(bindingContext.ModelMetadata))
            {
                return(null);
            }

            var mutableObjectBinderContext = new MutableObjectBinderContext()
            {
                ModelBindingContext = bindingContext,
                PropertyMetadata    = GetMetadataForProperties(bindingContext),
            };

            if (!(await CanCreateModel(mutableObjectBinderContext)))
            {
                return(null);
            }

            EnsureModel(bindingContext);
            var result = await CreateAndPopulateDto(bindingContext, mutableObjectBinderContext.PropertyMetadata);

            var validationNode = new ModelValidationNode(
                bindingContext.ModelName,
                bindingContext.ModelMetadata,
                bindingContext.Model);

            // post-processing, e.g. property setters and hooking up validation
            ProcessDto(bindingContext, (ComplexModelDto)result.Model, validationNode);
            return(new ModelBindingResult(
                       bindingContext.Model,
                       bindingContext.ModelName,
                       isModelSet: true,
                       validationNode: validationNode));
        }
示例#5
0
        public async Task <bool> BindModelAsync(ModelBindingContext bindingContext)
        {
            if (bindingContext.ModelType == typeof(ComplexModelDto))
            {
                ModelBindingHelper.ValidateBindingContext(bindingContext,
                                                          typeof(ComplexModelDto),
                                                          allowNullModel: false);

                var dto = (ComplexModelDto)bindingContext.Model;
                foreach (var propertyMetadata in dto.PropertyMetadata)
                {
                    var propertyModelName = ModelBindingHelper.CreatePropertyModelName(bindingContext.ModelName,
                                                                                       propertyMetadata.PropertyName);

                    var propertyBindingContext = new ModelBindingContext(bindingContext,
                                                                         propertyModelName,
                                                                         propertyMetadata);

                    // bind and propagate the values
                    // If we can't bind then leave the result missing (don't add a null).
                    if (await bindingContext.OperationBindingContext.ModelBinder.BindModelAsync(propertyBindingContext))
                    {
                        var result = ComplexModelDtoResult.FromBindingContext(propertyBindingContext);
                        dto.Results[propertyMetadata] = result;
                    }
                }

                return(true);
            }

            return(false);
        }
示例#6
0
        public async Task <ModelBindingResult> BindModelAsync(ModelBindingContext bindingContext)
        {
            ModelBindingHelper.ValidateBindingContext(bindingContext);

            if (!TypeHelper.HasStringConverter(bindingContext.ModelType))
            {
                // this type cannot be converted
                return(null);
            }

            var valueProviderResult = await bindingContext.ValueProvider.GetValueAsync(bindingContext.ModelName);

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

            object newModel;

            bindingContext.ModelState.SetModelValue(bindingContext.ModelName, valueProviderResult);
            try
            {
                newModel = valueProviderResult.ConvertTo(bindingContext.ModelType);
                ModelBindingHelper.ReplaceEmptyStringWithNull(bindingContext.ModelMetadata, ref newModel);
                return(new ModelBindingResult(newModel, bindingContext.ModelName, isModelSet: true));
            }
            catch (Exception ex)
            {
                bindingContext.ModelState.TryAddModelError(bindingContext.ModelName, ex);
            }

            // Were able to find a converter for the type but conversion failed.
            // Tell the model binding system to skip other model binders i.e. return non-null.
            return(new ModelBindingResult(model: null, key: bindingContext.ModelName, isModelSet: false));
        }
示例#7
0
        public async Task <ModelBindingResult> BindModelAsync(ModelBindingContext bindingContext)
        {
            ModelBindingHelper.ValidateBindingContext(bindingContext);

            if (bindingContext.ModelMetadata.IsComplexType)
            {
                // this type cannot be converted
                return(null);
            }

            var valueProviderResult = await bindingContext.ValueProvider.GetValueAsync(bindingContext.ModelName);

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

            object newModel;

            bindingContext.ModelState.SetModelValue(bindingContext.ModelName, valueProviderResult);
            try
            {
                newModel = valueProviderResult.ConvertTo(bindingContext.ModelType);
                ModelBindingHelper.ReplaceEmptyStringWithNull(bindingContext.ModelMetadata, ref newModel);
                var isModelSet = true;

                // When converting newModel a null value may indicate a failed conversion for an otherwise required
                // model (can't set a ValueType to null). This detects if a null model value is acceptable given the
                // current bindingContext. If not, an error is logged.
                if (newModel == null && !AllowsNullValue(bindingContext.ModelType))
                {
                    bindingContext.ModelState.TryAddModelError(
                        bindingContext.ModelName,
                        Resources.FormatCommon_ValueNotValidForProperty(newModel));

                    isModelSet = false;
                }

                // Include a ModelValidationNode if binding succeeded.
                var validationNode = isModelSet ?
                                     new ModelValidationNode(bindingContext.ModelName, bindingContext.ModelMetadata, newModel) :
                                     null;

                return(new ModelBindingResult(newModel, bindingContext.ModelName, isModelSet, validationNode));
            }
            catch (Exception ex)
            {
                bindingContext.ModelState.TryAddModelError(bindingContext.ModelName, ex);
            }

            // Were able to find a converter for the type but conversion failed.
            // Tell the model binding system to skip other model binders i.e. return non-null.
            return(new ModelBindingResult(model: null, key: bindingContext.ModelName, isModelSet: false));
        }
示例#8
0
        public async Task <ModelBindingResult> BindModelAsync(ModelBindingContext bindingContext)
        {
            ModelBindingHelper.ValidateBindingContext(bindingContext,
                                                      typeof(KeyValuePair <TKey, TValue>),
                                                      allowNullModel: true);

            var keyResult = await TryBindStrongModel <TKey>(bindingContext, "Key");

            var valueResult = await TryBindStrongModel <TValue>(bindingContext, "Value");

            if (keyResult.IsModelSet && valueResult.IsModelSet)
            {
                var model = new KeyValuePair <TKey, TValue>(
                    ModelBindingHelper.CastOrDefault <TKey>(keyResult.Model),
                    ModelBindingHelper.CastOrDefault <TValue>(valueResult.Model));

                return(ModelBindingResult.Success(bindingContext.ModelName, model));
            }
            else if (!keyResult.IsModelSet && valueResult.IsModelSet)
            {
                bindingContext.ModelState.TryAddModelError(
                    keyResult.Key,
                    bindingContext.ModelMetadata.ModelBindingMessageProvider.MissingKeyOrValueAccessor());

                // Were able to get some data for this model.
                // Always tell the model binding system to skip other model binders.
                return(ModelBindingResult.Failed(bindingContext.ModelName));
            }
            else if (keyResult.IsModelSet && !valueResult.IsModelSet)
            {
                bindingContext.ModelState.TryAddModelError(
                    valueResult.Key,
                    bindingContext.ModelMetadata.ModelBindingMessageProvider.MissingKeyOrValueAccessor());

                // Were able to get some data for this model.
                // Always tell the model binding system to skip other model binders.
                return(ModelBindingResult.Failed(bindingContext.ModelName));
            }
            else
            {
                // If we failed to find data for a top-level model, then generate a
                // default 'empty' model and return it.
                if (bindingContext.IsTopLevelObject)
                {
                    var model = new KeyValuePair <TKey, TValue>();
                    return(ModelBindingResult.Success(bindingContext.ModelName, model));
                }

                return(ModelBindingResult.NoResult);
            }
        }
示例#9
0
        public async Task <bool> BindModelAsync(ModelBindingContext bindingContext)
        {
            ModelBindingHelper.ValidateBindingContext(bindingContext,
                                                      typeof(KeyValuePair <TKey, TValue>),
                                                      allowNullModel: true);

            var keyResult = await TryBindStrongModel <TKey>(bindingContext, "key");

            var valueResult = await TryBindStrongModel <TValue>(bindingContext, "value");

            if (keyResult.Success && valueResult.Success)
            {
                bindingContext.Model = new KeyValuePair <TKey, TValue>(keyResult.Model, valueResult.Model);
            }
            return(keyResult.Success || valueResult.Success);
        }
        public async Task <ModelBindingResult> BindModelAsync(ModelBindingContext bindingContext)
        {
            ModelBindingHelper.ValidateBindingContext(bindingContext,
                                                      typeof(KeyValuePair <TKey, TValue>),
                                                      allowNullModel: true);

            var keyResult = await TryBindStrongModel <TKey>(bindingContext, "Key");

            var valueResult = await TryBindStrongModel <TValue>(bindingContext, "Value");

            if (keyResult.IsModelSet && valueResult.IsModelSet)
            {
                var model = new KeyValuePair <TKey, TValue>(
                    ModelBindingHelper.CastOrDefault <TKey>(keyResult.Model),
                    ModelBindingHelper.CastOrDefault <TValue>(valueResult.Model));

                // Success
                return(new ModelBindingResult(model, bindingContext.ModelName, isModelSet: true));
            }
            else if (!keyResult.IsModelSet && valueResult.IsModelSet)
            {
                bindingContext.ModelState.TryAddModelError(
                    keyResult.Key,
                    Resources.KeyValuePair_BothKeyAndValueMustBePresent);

                // Were able to get some data for this model.
                // Always tell the model binding system to skip other model binders i.e. return non-null.
                return(new ModelBindingResult(model: null, key: bindingContext.ModelName, isModelSet: false));
            }
            else if (keyResult.IsModelSet && !valueResult.IsModelSet)
            {
                bindingContext.ModelState.TryAddModelError(
                    valueResult.Key,
                    Resources.KeyValuePair_BothKeyAndValueMustBePresent);

                // Were able to get some data for this model.
                // Always tell the model binding system to skip other model binders i.e. return non-null.
                return(new ModelBindingResult(model: null, key: bindingContext.ModelName, isModelSet: false));
            }
            else
            {
                // Caller (GenericModelBinder) was able to resolve a binder type and will create a ModelBindingResult
                // that exits current ModelBinding loop.
                return(null);
            }
        }
示例#11
0
        internal static async Task <ValueProviderResult> GetCompatibleValueProviderResult(ModelBindingContext context)
        {
            ModelBindingHelper.ValidateBindingContext(context);

            var valueProviderResult = await context.ValueProvider.GetValueAsync(context.ModelName);

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

            if (!context.ModelType.IsCompatibleWith(valueProviderResult.RawValue))
            {
                return(null); // value is of incompatible type
            }

            return(valueProviderResult);
        }
示例#12
0
        public virtual async Task <bool> BindModelAsync(ModelBindingContext bindingContext)
        {
            ModelBindingHelper.ValidateBindingContext(bindingContext);

            if (!await bindingContext.ValueProvider.ContainsPrefixAsync(bindingContext.ModelName))
            {
                return(false);
            }

            var valueProviderResult = await bindingContext.ValueProvider.GetValueAsync(bindingContext.ModelName);

            var bindCollectionTask = valueProviderResult != null?
                                     BindSimpleCollection(bindingContext, valueProviderResult.RawValue, valueProviderResult.Culture) :
                                         BindComplexCollection(bindingContext);

            var boundCollection = await bindCollectionTask;

            return(CreateOrReplaceCollection(bindingContext, boundCollection));
        }
示例#13
0
        public virtual async Task <bool> BindModelAsync(ModelBindingContext bindingContext)
        {
            ModelBindingHelper.ValidateBindingContext(bindingContext);

            if (!CanBindType(bindingContext.ModelType) ||
                !await bindingContext.ValueProvider.ContainsPrefixAsync(bindingContext.ModelName))
            {
                return(false);
            }

            EnsureModel(bindingContext);
            var propertyMetadatas = GetMetadataForProperties(bindingContext);
            var dto = CreateAndPopulateDto(bindingContext, propertyMetadatas);

            // post-processing, e.g. property setters and hooking up validation
            ProcessDto(bindingContext, dto);
            // complex models require full validation
            bindingContext.ValidationNode.ValidateAllProperties = true;
            return(true);
        }
        public virtual async Task <ModelBindingResult> BindModelAsync(ModelBindingContext bindingContext)
        {
            ModelBindingHelper.ValidateBindingContext(bindingContext);

            if (!await bindingContext.ValueProvider.ContainsPrefixAsync(bindingContext.ModelName))
            {
                return(null);
            }

            var valueProviderResult = await bindingContext.ValueProvider.GetValueAsync(bindingContext.ModelName);

            var bindCollectionTask = valueProviderResult != null?
                                     BindSimpleCollection(bindingContext, valueProviderResult.RawValue, valueProviderResult.Culture) :
                                         BindComplexCollection(bindingContext);

            var boundCollection = await bindCollectionTask;
            var model           = GetModel(boundCollection);

            return(new ModelBindingResult(model, bindingContext.ModelName, isModelSet: true));
        }
示例#15
0
        public async Task <ModelBindingResult> BindModelAsync(ModelBindingContext bindingContext)
        {
            if (bindingContext.ModelType != typeof(ComplexModelDto))
            {
                return(null);
            }

            ModelBindingHelper.ValidateBindingContext(bindingContext, typeof(ComplexModelDto), allowNullModel: false);

            var dto = (ComplexModelDto)bindingContext.Model;

            foreach (var propertyMetadata in dto.PropertyMetadata)
            {
                var propertyModelName = ModelNames.CreatePropertyModelName(
                    bindingContext.ModelName,
                    propertyMetadata.BinderModelName ?? propertyMetadata.PropertyName);

                var propertyBindingContext = ModelBindingContext.GetChildModelBindingContext(
                    bindingContext,
                    propertyModelName,
                    propertyMetadata);

                var modelBindingResult =
                    await bindingContext.OperationBindingContext.ModelBinder.BindModelAsync(propertyBindingContext);

                if (modelBindingResult == null)
                {
                    // Could not bind. Add a result so MutableObjectModelBinder will check for [DefaultValue].
                    dto.Results[propertyMetadata] =
                        new ModelBindingResult(model: null, key: propertyModelName, isModelSet: false);
                }
                else
                {
                    dto.Results[propertyMetadata] = modelBindingResult;
                }
            }

            return(new ModelBindingResult(dto, bindingContext.ModelName, isModelSet: true));
        }
示例#16
0
        public virtual async Task <bool> BindModelAsync(ModelBindingContext bindingContext)
        {
            ModelBindingHelper.ValidateBindingContext(bindingContext);

            if (!CanBindType(bindingContext.ModelType))
            {
                return(false);
            }

            var topLevelObject         = bindingContext.ModelMetadata.ContainerType == null;
            var isThereAnExplicitAlias = bindingContext.ModelMetadata.ModelName != null;


            // The first check is necessary because if we fallback to empty prefix, we do not want to depend
            // on a value provider to provide a value for empty prefix.
            var containsPrefix = (bindingContext.ModelName == string.Empty && topLevelObject) ||
                                 await bindingContext.ValueProvider.ContainsPrefixAsync(bindingContext.ModelName);

            // Always create the model if
            // 1. It is a top level object and the model name is empty.
            // 2. There is a value provider which can provide value for the model name.
            // 3. There is an explicit alias provided by the user and it is a top level object.
            // The reson we depend on explicit alias is that otherwise we want the FallToEmptyPrefix codepath
            // to kick in so that empty prefix values could be bound.
            if (!containsPrefix && !(isThereAnExplicitAlias && topLevelObject))
            {
                return(false);
            }

            EnsureModel(bindingContext);
            var propertyMetadatas = GetMetadataForProperties(bindingContext).ToArray();
            var dto = CreateAndPopulateDto(bindingContext, propertyMetadatas);

            // post-processing, e.g. property setters and hooking up validation
            ProcessDto(bindingContext, dto);
            // complex models require full validation
            bindingContext.ValidationNode.ValidateAllProperties = true;
            return(true);
        }
        /// <inheritdoc />
        public virtual async Task <ModelBindingResult> BindModelAsync([NotNull] ModelBindingContext bindingContext)
        {
            ModelBindingHelper.ValidateBindingContext(bindingContext);
            if (!CanBindType(bindingContext.ModelMetadata))
            {
                return(null);
            }

            var mutableObjectBinderContext = new MutableObjectBinderContext()
            {
                ModelBindingContext = bindingContext,
                PropertyMetadata    = GetMetadataForProperties(bindingContext).ToArray(),
            };

            if (!(await CanCreateModel(mutableObjectBinderContext)))
            {
                return(null);
            }

            // Create model first (if necessary) to avoid reporting errors about properties when activation fails.
            var model = GetModel(bindingContext);

            var results = await BindPropertiesAsync(bindingContext, mutableObjectBinderContext.PropertyMetadata);

            var validationNode = new ModelValidationNode(
                bindingContext.ModelName,
                bindingContext.ModelMetadata,
                model);

            // Post-processing e.g. property setters and hooking up validation.
            bindingContext.Model = model;
            ProcessResults(bindingContext, results, validationNode);

            return(new ModelBindingResult(
                       model,
                       bindingContext.ModelName,
                       isModelSet: true,
                       validationNode: validationNode));
        }
示例#18
0
        /// <inheritdoc />
        public virtual async Task <ModelBindingResult> BindModelAsync([NotNull] ModelBindingContext bindingContext)
        {
            ModelBindingHelper.ValidateBindingContext(bindingContext);

            var model = bindingContext.Model;

            if (!await bindingContext.ValueProvider.ContainsPrefixAsync(bindingContext.ModelName))
            {
                // If this is the fallback case and we failed to find data for a top-level model, then generate a
                // default 'empty' model (or use existing Model) and return it.
                if (!bindingContext.IsFirstChanceBinding && bindingContext.IsTopLevelObject)
                {
                    if (model == null)
                    {
                        model = CreateEmptyCollection(bindingContext.ModelType);
                    }

                    var validationNode = new ModelValidationNode(
                        bindingContext.ModelName,
                        bindingContext.ModelMetadata,
                        model);

                    return(new ModelBindingResult(
                               model,
                               bindingContext.ModelName,
                               isModelSet: true,
                               validationNode: validationNode));
                }

                return(null);
            }

            var valueProviderResult = await bindingContext.ValueProvider.GetValueAsync(bindingContext.ModelName);

            CollectionResult result;

            if (valueProviderResult == null)
            {
                result = await BindComplexCollection(bindingContext);
            }
            else
            {
                if (valueProviderResult.RawValue == null)
                {
                    // Value exists but is null. Handle similarly to fallback case above. This avoids a
                    // ModelBindingResult with IsModelSet = true but ValidationNode = null.
                    model = bindingContext.Model ?? CreateEmptyCollection(bindingContext.ModelType);
                    var validationNode =
                        new ModelValidationNode(bindingContext.ModelName, bindingContext.ModelMetadata, model);

                    return(new ModelBindingResult(
                               model,
                               bindingContext.ModelName,
                               isModelSet: true,
                               validationNode: validationNode));
                }

                result = await BindSimpleCollection(
                    bindingContext,
                    valueProviderResult.RawValue,
                    valueProviderResult.Culture);
            }

            var boundCollection = result.Model;

            if (model == null)
            {
                model = ConvertToCollectionType(bindingContext.ModelType, boundCollection);
            }
            else
            {
                // Special case for TryUpdateModelAsync(collection, ...) scenarios. Model is null in all other cases.
                CopyToModel(model, boundCollection);
            }

            return(new ModelBindingResult(
                       model,
                       bindingContext.ModelName,
                       isModelSet: true,
                       validationNode: result.ValidationNode));
        }
示例#19
0
        /// <inheritdoc />
        public virtual async Task <ModelBindingResult> BindModelAsync([NotNull] ModelBindingContext bindingContext)
        {
            ModelBindingHelper.ValidateBindingContext(bindingContext);

            object model;

            if (!await bindingContext.ValueProvider.ContainsPrefixAsync(bindingContext.ModelName))
            {
                // If this is the fallback case, and we failed to find data as a top-level model, then generate a
                // default 'empty' model and return it.
                var isTopLevelObject = bindingContext.ModelMetadata.ContainerType == null;
                var hasExplicitAlias = bindingContext.BinderModelName != null;

                if (isTopLevelObject && (hasExplicitAlias || bindingContext.ModelName == string.Empty))
                {
                    model = CreateEmptyCollection();

                    var validationNode = new ModelValidationNode(
                        bindingContext.ModelName,
                        bindingContext.ModelMetadata,
                        model);

                    return(new ModelBindingResult(
                               model,
                               bindingContext.ModelName,
                               isModelSet: true,
                               validationNode: validationNode));
                }

                return(null);
            }

            var valueProviderResult = await bindingContext.ValueProvider.GetValueAsync(bindingContext.ModelName);

            IEnumerable <TElement> boundCollection;
            CollectionResult       result;

            if (valueProviderResult == null)
            {
                result = await BindComplexCollection(bindingContext);

                boundCollection = result.Model;
            }
            else
            {
                result = await BindSimpleCollection(
                    bindingContext,
                    valueProviderResult.RawValue,
                    valueProviderResult.Culture);

                boundCollection = result.Model;
            }

            model = bindingContext.Model;
            if (model == null)
            {
                model = GetModel(boundCollection);
            }
            else
            {
                // Special case for TryUpdateModelAsync(collection, ...) scenarios. Model is null in all other cases.
                CopyToModel(model, boundCollection);
            }

            return(new ModelBindingResult(
                       model,
                       bindingContext.ModelName,
                       isModelSet: true,
                       validationNode: result?.ValidationNode));
        }
示例#20
0
        /// <inheritdoc />
        public virtual async Task <ModelBindingResult> BindModelAsync([NotNull] ModelBindingContext bindingContext)
        {
            ModelBindingHelper.ValidateBindingContext(bindingContext);

            var model = bindingContext.Model;

            if (!bindingContext.ValueProvider.ContainsPrefix(bindingContext.ModelName))
            {
                // If we failed to find data for a top-level model, then generate a
                // default 'empty' model (or use existing Model) and return it.
                if (bindingContext.IsTopLevelObject)
                {
                    if (model == null)
                    {
                        model = CreateEmptyCollection(bindingContext.ModelType);
                    }

                    return(ModelBindingResult.Success(bindingContext.ModelName, model));
                }

                return(ModelBindingResult.NoResult);
            }

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

            CollectionResult result;

            if (valueProviderResult == ValueProviderResult.None)
            {
                result = await BindComplexCollection(bindingContext);
            }
            else
            {
                result = await BindSimpleCollection(bindingContext, valueProviderResult);
            }

            var boundCollection = result.Model;

            if (model == null)
            {
                model = ConvertToCollectionType(bindingContext.ModelType, boundCollection);
            }
            else
            {
                // Special case for TryUpdateModelAsync(collection, ...) scenarios. Model is null in all other cases.
                CopyToModel(model, boundCollection);
            }

            Debug.Assert(model != null);
            if (result.ValidationStrategy != null)
            {
                bindingContext.ValidationState.Add(model, new ValidationStateEntry()
                {
                    Strategy = result.ValidationStrategy,
                });
            }

            if (valueProviderResult != ValueProviderResult.None)
            {
                // If we did simple binding, then modelstate should be updated to reflect what we bound for ModelName.
                // If we did complex binding, there will already be an entry for each index.
                bindingContext.ModelState.SetModelValue(
                    bindingContext.ModelName,
                    valueProviderResult);
            }

            return(ModelBindingResult.Success(bindingContext.ModelName, model));
        }
示例#21
0
        public async Task <ModelBindingResult> BindModelAsync(ModelBindingContext bindingContext)
        {
            ModelBindingHelper.ValidateBindingContext(bindingContext,
                                                      typeof(KeyValuePair <TKey, TValue>),
                                                      allowNullModel: true);

            var childNodes = new List <ModelValidationNode>();
            var keyResult  = await TryBindStrongModel <TKey>(bindingContext, "Key", childNodes);

            var valueResult = await TryBindStrongModel <TValue>(bindingContext, "Value", childNodes);

            if (keyResult.IsModelSet && valueResult.IsModelSet)
            {
                var model = new KeyValuePair <TKey, TValue>(
                    ModelBindingHelper.CastOrDefault <TKey>(keyResult.Model),
                    ModelBindingHelper.CastOrDefault <TValue>(valueResult.Model));

                // Update the model for the top level validation node.
                var modelValidationNode =
                    new ModelValidationNode(
                        bindingContext.ModelName,
                        bindingContext.ModelMetadata,
                        model,
                        childNodes);

                // Success
                return(new ModelBindingResult(
                           model,
                           bindingContext.ModelName,
                           isModelSet: true,
                           validationNode: modelValidationNode));
            }
            else if (!keyResult.IsModelSet && valueResult.IsModelSet)
            {
                bindingContext.ModelState.TryAddModelError(
                    keyResult.Key,
                    Resources.KeyValuePair_BothKeyAndValueMustBePresent);

                // Were able to get some data for this model.
                // Always tell the model binding system to skip other model binders i.e. return non-null.
                return(new ModelBindingResult(model: null, key: bindingContext.ModelName, isModelSet: false));
            }
            else if (keyResult.IsModelSet && !valueResult.IsModelSet)
            {
                bindingContext.ModelState.TryAddModelError(
                    valueResult.Key,
                    Resources.KeyValuePair_BothKeyAndValueMustBePresent);

                // Were able to get some data for this model.
                // Always tell the model binding system to skip other model binders i.e. return non-null.
                return(new ModelBindingResult(model: null, key: bindingContext.ModelName, isModelSet: false));
            }
            else
            {
                // If this is the fallback case, and we failed to find data as a top-level model, then generate a
                // default 'empty' model and return it.
                var isTopLevelObject = bindingContext.ModelMetadata.ContainerType == null;
                var hasExplicitAlias = bindingContext.BinderModelName != null;

                if (isTopLevelObject && (hasExplicitAlias || bindingContext.ModelName == string.Empty))
                {
                    var model = new KeyValuePair <TKey, TValue>();

                    var validationNode = new ModelValidationNode(
                        bindingContext.ModelName,
                        bindingContext.ModelMetadata,
                        model);

                    return(new ModelBindingResult(
                               model,
                               bindingContext.ModelName,
                               isModelSet: true,
                               validationNode: validationNode));
                }

                return(null);
            }
        }