Esempio n. 1
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)
            {
                return(null); // no entry
            }

            object newModel;

            bindingContext.ModelState.SetModelValue(bindingContext.ModelName, valueProviderResult);
            try
            {
                newModel = valueProviderResult.ConvertTo(bindingContext.ModelType);
                ModelBindingHelper.ReplaceEmptyStringWithNull(bindingContext.ModelMetadata, ref newModel);
                var validationNode = new ModelValidationNode(
                    bindingContext.ModelName,
                    bindingContext.ModelMetadata,
                    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;
                }

                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));
        }
        internal async Task <IEnumerable <TElement> > BindComplexCollectionFromIndexes(ModelBindingContext bindingContext,
                                                                                       IEnumerable <string> indexNames)
        {
            bool indexNamesIsFinite;

            if (indexNames != null)
            {
                indexNamesIsFinite = true;
            }
            else
            {
                indexNamesIsFinite = false;
                indexNames         = Enumerable.Range(0, Int32.MaxValue)
                                     .Select(i => i.ToString(CultureInfo.InvariantCulture));
            }

            var metadataProvider = bindingContext.OperationBindingContext.MetadataProvider;
            var elementMetadata  = metadataProvider.GetMetadataForType(typeof(TElement));

            var boundCollection = new List <TElement>();

            foreach (var indexName in indexNames)
            {
                var fullChildName       = ModelBindingHelper.CreateIndexModelName(bindingContext.ModelName, indexName);
                var childBindingContext = ModelBindingContext.GetChildModelBindingContext(
                    bindingContext,
                    fullChildName,
                    elementMetadata);

                var    didBind    = false;
                object boundValue = null;

                var modelType = bindingContext.ModelType;

                var result = await bindingContext.OperationBindingContext.ModelBinder.BindModelAsync(childBindingContext);

                if (result != null)
                {
                    didBind    = true;
                    boundValue = result.Model;
                }

                // infinite size collection stops on first bind failure
                if (!didBind && !indexNamesIsFinite)
                {
                    break;
                }

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

            return(boundCollection);
        }
        internal void ProcessDto(ModelBindingContext bindingContext, ComplexModelDto dto)
        {
            var validationInfo = GetPropertyValidationInfo(bindingContext);

            // Eliminate provided properties from requiredProperties; leaving just *missing* required properties.
            validationInfo.RequiredProperties.ExceptWith(dto.Results.Select(r => r.Key.PropertyName));

            foreach (var missingRequiredProperty in validationInfo.RequiredProperties)
            {
                var addedError    = false;
                var modelStateKey = ModelBindingHelper.CreatePropertyModelName(
                    bindingContext.ValidationNode.ModelStateKey, missingRequiredProperty);

                // Update Model as SetProperty() would: Place null value where validator will check for non-null. This
                // ensures a failure result from a required validator (if any) even for a non-nullable property.
                // (Otherwise, propertyMetadata.Model is likely already null.)
                var propertyMetadata = bindingContext.PropertyMetadata[missingRequiredProperty];
                propertyMetadata.Model = null;

                // Execute validator (if any) to get custom error message.
                IModelValidator validator;
                if (validationInfo.RequiredValidators.TryGetValue(missingRequiredProperty, out validator))
                {
                    addedError = RunValidator(validator, bindingContext, propertyMetadata, modelStateKey);
                }

                // Fall back to default message if BindingBehaviorAttribute required this property or validator
                // (oddly) succeeded.
                if (!addedError)
                {
                    bindingContext.ModelState.TryAddModelError(
                        modelStateKey,
                        Resources.FormatMissingRequiredMember(missingRequiredProperty));
                }
            }

            // for each property that was bound, call the setter, recording exceptions as necessary
            foreach (var entry in dto.Results)
            {
                var propertyMetadata = entry.Key;
                var dtoResult        = entry.Value;
                if (dtoResult != null)
                {
                    IModelValidator requiredValidator;
                    validationInfo.RequiredValidators.TryGetValue(propertyMetadata.PropertyName,
                                                                  out requiredValidator);
                    SetProperty(bindingContext, propertyMetadata, dtoResult, requiredValidator);
                    bindingContext.ValidationNode.ChildNodes.Add(dtoResult.ValidationNode);
                }
            }
        }
Esempio n. 4
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);
            }
        }
Esempio n. 5
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 for testing.
        internal async Task <CollectionResult> BindSimpleCollection(
            ModelBindingContext bindingContext,
            object rawValue,
            CultureInfo culture)
        {
            var boundCollection = new List <TElement>();

            var metadataProvider = bindingContext.OperationBindingContext.MetadataProvider;
            var elementMetadata  = metadataProvider.GetMetadataForType(typeof(TElement));

            var validationNode = new ModelValidationNode(
                bindingContext.ModelName,
                bindingContext.ModelMetadata,
                boundCollection);
            var rawValueArray = RawValueToObjectArray(rawValue);

            foreach (var rawValueElement in rawValueArray)
            {
                var innerBindingContext = ModelBindingContext.GetChildModelBindingContext(
                    bindingContext,
                    bindingContext.ModelName,
                    elementMetadata);
                innerBindingContext.ValueProvider = new CompositeValueProvider
                {
                    // our temporary provider goes at the front of the list
                    new ElementalValueProvider(bindingContext.ModelName, rawValueElement, culture),
                    bindingContext.ValueProvider
                };

                object boundValue = null;
                var    result     =
                    await bindingContext.OperationBindingContext.ModelBinder.BindModelAsync(innerBindingContext);

                if (result != null && result.IsModelSet)
                {
                    boundValue = result.Model;
                    if (result.ValidationNode != null)
                    {
                        validationNode.ChildNodes.Add(result.ValidationNode);
                    }
                }
                boundCollection.Add(ModelBindingHelper.CastOrDefault <TElement>(boundValue));
            }

            return(new CollectionResult
            {
                ValidationNode = validationNode,
                Model = boundCollection
            });
        }
Esempio n. 6
0
        /// <summary>
        /// Attempts to convert the values in <paramref name="result"/> to the specified type.
        /// </summary>
        /// <param name="result">The <see cref="ValueProviderResult"/>.</param>
        /// <param name="type">The <see cref="Type"/> for conversion.</param>
        /// <returns>
        /// The converted value, or the default value of <paramref name="type"/> if the value could not be converted.
        /// </returns>
        public static object ConvertTo(this ValueProviderResult result, [NotNull] Type type)
        {
            object valueToConvert = null;

            if (result.Values.Count == 1)
            {
                valueToConvert = result.Values[0];
            }
            else if (result.Values.Count > 1)
            {
                valueToConvert = result.Values.ToArray();
            }
            return(ModelBindingHelper.ConvertTo(valueToConvert, type, result.Culture));
        }
Esempio n. 7
0
        /// <summary>
        /// Attempts to convert the values in <paramref name="result"/> to the specified type.
        /// </summary>
        /// <typeparam name="T">The <see cref="Type"/> for conversion.</typeparam>
        /// <param name="result">The <see cref="ValueProviderResult"/>.</param>
        /// <returns>
        /// The converted value, or the default value of <typeparamref name="T"/> if the value could not be converted.
        /// </returns>
        public static T ConvertTo <T>(this ValueProviderResult result)
        {
            object valueToConvert = null;

            if (result.Values.Count == 1)
            {
                valueToConvert = result.Values[0];
            }
            else if (result.Values.Count > 1)
            {
                valueToConvert = result.Values.ToArray();
            }
            return(ModelBindingHelper.ConvertTo <T>(valueToConvert, result.Culture));
        }
Esempio n. 8
0
        /// <inheritdoc />
        protected override Task <ModelBindingResult> BindModelCoreAsync([NotNull] ModelBindingContext bindingContext)
        {
            var request       = bindingContext.OperationBindingContext.HttpContext.Request;
            var modelMetadata = bindingContext.ModelMetadata;

            // Property name can be null if the model metadata represents a type (rather than a property or parameter).
            var    headerName = bindingContext.BinderModelName ?? modelMetadata.PropertyName ?? bindingContext.ModelName;
            object model      = null;

            if (bindingContext.ModelType == typeof(string))
            {
                var value = request.Headers.Get(headerName);
                if (value != null)
                {
                    model = value;
                }
            }
            else if (typeof(IEnumerable <string>).IsAssignableFrom(bindingContext.ModelType))
            {
                var values = request.Headers.GetCommaSeparatedValues(headerName);
                if (values != null)
                {
                    model = ModelBindingHelper.ConvertValuesToCollectionType(
                        bindingContext.ModelType,
                        values);
                }
            }

            ModelValidationNode validationNode = null;

            if (model != null)
            {
                validationNode = new ModelValidationNode(
                    bindingContext.ModelName,
                    bindingContext.ModelMetadata,
                    model);

                var attemptedValue      = (model as string) ?? request.Headers.Get(headerName);
                var valueProviderResult = new ValueProviderResult(model, attemptedValue, CultureInfo.InvariantCulture);
                bindingContext.ModelState.SetModelValue(bindingContext.ModelName, valueProviderResult);
            }

            return(Task.FromResult(
                       new ModelBindingResult(
                           model,
                           bindingContext.ModelName,
                           isModelSet: model != null,
                           validationNode: validationNode)));
        }
        public async Task <ModelBindingResult> BindModelAsync(ModelBindingContext bindingContext)
        {
            var valueProviderResult = await GetCompatibleValueProviderResult(bindingContext);

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

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

            ModelBindingHelper.ReplaceEmptyStringWithNull(bindingContext.ModelMetadata, ref model);
            return(new ModelBindingResult(model, bindingContext.ModelName, isModelSet: true));
        }
Esempio n. 10
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);
            }
        }
Esempio n. 12
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);
        }
Esempio n. 13
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)
            {
                return(null); // no entry
            }

            object newModel;

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

                return(new ModelBindingResult(
                           newModel,
                           bindingContext.ModelName,
                           isModelSet: true,
                           validationNode: 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));
        }
Esempio n. 14
0
        /// <summary>
        /// Attempts to convert the values in <paramref name="result"/> to the specified type.
        /// </summary>
        /// <param name="result">The <see cref="ValueProviderResult"/>.</param>
        /// <param name="type">The <see cref="Type"/> for conversion.</param>
        /// <returns>
        /// The converted value, or the default value of <paramref name="type"/> if the value could not be converted.
        /// </returns>
        public static object ConvertTo(this ValueProviderResult result, Type type)
        {
            if (type == null)
            {
                throw new ArgumentNullException(nameof(type));
            }

            object valueToConvert = null;

            if (result.Values.Count == 1)
            {
                valueToConvert = result.Values[0];
            }
            else if (result.Values.Count > 1)
            {
                valueToConvert = result.Values.ToArray();
            }
            return(ModelBindingHelper.ConvertTo(valueToConvert, type, result.Culture));
        }
Esempio n. 15
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));
        }
Esempio n. 16
0
        // Validates a single node (not including children)
        // Returns true if validation passes successfully
        private static bool ShallowValidate(
            ModelMetadata metadata,
            ValidationContext validationContext,
            [NotNull] IEnumerable <IModelValidator> validators)
        {
            var    isValid  = true;
            string modelKey = null;

            // When the are no validators we bail quickly. This saves a GetEnumerator allocation.
            // In a large array (tens of thousands or more) scenario it's very significant.
            var validatorsAsCollection = validators as ICollection;

            if (validatorsAsCollection != null && validatorsAsCollection.Count == 0)
            {
                return(isValid);
            }

            var modelValidationContext =
                new ModelValidationContext(validationContext.ModelValidationContext, metadata);

            foreach (var validator in validators)
            {
                foreach (var error in validator.Validate(modelValidationContext))
                {
                    if (modelKey == null)
                    {
                        modelKey = validationContext.RootPrefix;
                        // This constructs the object heirarchy
                        // Example: prefix.Parent.Child
                        foreach (var keyBuilder in validationContext.KeyBuilders.Reverse())
                        {
                            modelKey = keyBuilder.AppendTo(modelKey);
                        }
                    }

                    var errorKey = ModelBindingHelper.CreatePropertyModelName(modelKey, error.MemberName);
                    validationContext.ModelValidationContext.ModelState.AddModelError(errorKey, error.Message);
                    isValid = false;
                }
            }

            return(isValid);
        }
Esempio n. 17
0
        public async Task <bool> BindModelAsync(ModelBindingContext bindingContext)
        {
            var valueProviderResult = await GetCompatibleValueProviderResult(bindingContext);

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

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

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

            // TODO: Determine if we need IBodyValidator here.
            return(true);
        }
Esempio n. 18
0
        /// <inheritdoc />
        public async Task <ModelBindingResult> BindModelAsync([NotNull] ModelBindingContext bindingContext)
        {
            object value;

            if (bindingContext.ModelType == typeof(IFormFile))
            {
                var postedFiles = await GetFormFilesAsync(bindingContext);

                value = postedFiles.FirstOrDefault();
            }
            else if (typeof(IEnumerable <IFormFile>).IsAssignableFrom(bindingContext.ModelType))
            {
                var postedFiles = await GetFormFilesAsync(bindingContext);

                value = ModelBindingHelper.ConvertValuesToCollectionType(bindingContext.ModelType, postedFiles);
            }
            else
            {
                // This binder does not support the requested type.
                return(null);
            }

            ModelValidationNode validationNode = null;

            if (value != null)
            {
                validationNode =
                    new ModelValidationNode(bindingContext.ModelName, bindingContext.ModelMetadata, value)
                {
                    SuppressValidation = true,
                };

                var valueProviderResult = new ValueProviderResult(rawValue: value);
                bindingContext.ModelState.SetModelValue(bindingContext.ModelName, valueProviderResult);
            }

            return(new ModelBindingResult(
                       value,
                       bindingContext.ModelName,
                       isModelSet: value != null,
                       validationNode: validationNode));
        }
Esempio n. 19
0
        internal async Task <BindResult <TModel> > TryBindStrongModel <TModel>(ModelBindingContext parentBindingContext,
                                                                               string propertyName)
        {
            var propertyBindingContext = new ModelBindingContext(parentBindingContext)
            {
                ModelMetadata = parentBindingContext.MetadataProvider.GetMetadataForType(modelAccessor: null,
                                                                                         modelType: typeof(TModel)),
                ModelName = ModelBindingHelper.CreatePropertyModelName(parentBindingContext.ModelName, propertyName)
            };

            if (await propertyBindingContext.ModelBinder.BindModelAsync(propertyBindingContext))
            {
                var untypedModel = propertyBindingContext.Model;
                var model        = ModelBindingHelper.CastOrDefault <TModel>(untypedModel);
                parentBindingContext.ValidationNode.ChildNodes.Add(propertyBindingContext.ValidationNode);
                return(new BindResult <TModel>(success: true, model: model));
            }

            return(new BindResult <TModel>(success: false, model: default(TModel)));
        }
Esempio n. 20
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);
        }
Esempio n. 21
0
        /// <inheritdoc />
        public async Task <ModelBindingResult> BindModelAsync([NotNull] ModelBindingContext bindingContext)
        {
            if (bindingContext.ModelType == typeof(IFormFile))
            {
                var postedFiles = await GetFormFilesAsync(bindingContext);

                var value = postedFiles.FirstOrDefault();
                return(new ModelBindingResult(value, bindingContext.ModelName, isModelSet: value != null));
            }
            else if (typeof(IEnumerable <IFormFile>).GetTypeInfo().IsAssignableFrom(
                         bindingContext.ModelType.GetTypeInfo()))
            {
                var postedFiles = await GetFormFilesAsync(bindingContext);

                var value = ModelBindingHelper.ConvertValuesToCollectionType(bindingContext.ModelType, postedFiles);
                return(new ModelBindingResult(value, bindingContext.ModelName, isModelSet: value != null));
            }

            return(null);
        }
Esempio n. 22
0
        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));
        }
Esempio n. 23
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 for testing.
        internal async Task <CollectionResult> BindSimpleCollection(
            ModelBindingContext bindingContext,
            ValueProviderResult values)
        {
            var boundCollection = new List <TElement>();

            var metadataProvider = bindingContext.OperationBindingContext.MetadataProvider;
            var elementMetadata  = metadataProvider.GetMetadataForType(typeof(TElement));

            var innerBindingContext = ModelBindingContext.CreateChildBindingContext(
                bindingContext,
                elementMetadata,
                fieldName: bindingContext.FieldName,
                modelName: bindingContext.ModelName,
                model: null);

            foreach (var value in values)
            {
                innerBindingContext.ValueProvider = new CompositeValueProvider
                {
                    // our temporary provider goes at the front of the list
                    new ElementalValueProvider(bindingContext.ModelName, value, values.Culture),
                    bindingContext.ValueProvider
                };

                object boundValue = null;
                var    result     =
                    await bindingContext.OperationBindingContext.ModelBinder.BindModelAsync(innerBindingContext);

                if (result != null && result.IsModelSet)
                {
                    boundValue = result.Model;
                    boundCollection.Add(ModelBindingHelper.CastOrDefault <TElement>(boundValue));
                }
            }

            return(new CollectionResult
            {
                Model = boundCollection
            });
        }
Esempio n. 24
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 async Task <IEnumerable <TElement> > BindSimpleCollection(ModelBindingContext bindingContext,
                                                                           object rawValue,
                                                                           CultureInfo culture)
        {
            if (rawValue == null)
            {
                return(null); // nothing to do
            }

            var boundCollection = new List <TElement>();

            var metadataProvider = bindingContext.OperationBindingContext.MetadataProvider;
            var elementMetadata  = metadataProvider.GetMetadataForType(typeof(TElement));

            var rawValueArray = RawValueToObjectArray(rawValue);

            foreach (var rawValueElement in rawValueArray)
            {
                var innerBindingContext = ModelBindingContext.GetChildModelBindingContext(
                    bindingContext,
                    bindingContext.ModelName,
                    elementMetadata);
                innerBindingContext.ValueProvider = new CompositeValueProvider
                {
                    // our temporary provider goes at the front of the list
                    new ElementalValueProvider(bindingContext.ModelName, rawValueElement, culture),
                    bindingContext.ValueProvider
                };

                object boundValue = null;
                var    result     = await bindingContext.OperationBindingContext.ModelBinder.BindModelAsync(innerBindingContext);

                if (result != null)
                {
                    boundValue = result.Model;
                }
                boundCollection.Add(ModelBindingHelper.CastOrDefault <TElement>(boundValue));
            }

            return(boundCollection);
        }
Esempio n. 25
0
        private async Task <ModelBindingResult> BindModelCoreAsync(ModelBindingContext bindingContext)
        {
            object value;

            if (bindingContext.ModelType == typeof(IFormFile))
            {
                var postedFiles = await GetFormFilesAsync(bindingContext);

                value = postedFiles.FirstOrDefault();
            }
            else if (typeof(IEnumerable <IFormFile>).IsAssignableFrom(bindingContext.ModelType))
            {
                var postedFiles = await GetFormFilesAsync(bindingContext);

                value = ModelBindingHelper.ConvertValuesToCollectionType(bindingContext.ModelType, postedFiles);
            }
            else
            {
                // This binder does not support the requested type.
                Debug.Fail("We shouldn't be called without a matching type.");
                return(ModelBindingResult.NoResult);
            }

            if (value == null)
            {
                return(ModelBindingResult.Failed(bindingContext.ModelName));
            }
            else
            {
                bindingContext.ValidationState.Add(value, new ValidationStateEntry()
                {
                    SuppressValidation = true
                });
                bindingContext.ModelState.SetModelValue(
                    bindingContext.ModelName,
                    rawValue: null,
                    attemptedValue: null);

                return(ModelBindingResult.Success(bindingContext.ModelName, value));
            }
        }
Esempio n. 26
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)
            {
                if (IsFormatException(ex))
                {
                    // there was a type conversion failure
                    bindingContext.ModelState.AddModelError(bindingContext.ModelName, ex.Message);
                }
                else
                {
                    bindingContext.ModelState.AddModelError(bindingContext.ModelName, ex);
                }
            }

            return(true);
        }
Esempio n. 27
0
        public async Task <ModelBindingResult> BindModelAsync(ModelBindingContext bindingContext)
        {
            var valueProviderResult = await GetCompatibleValueProviderResult(bindingContext);

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

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

            ModelBindingHelper.ReplaceEmptyStringWithNull(bindingContext.ModelMetadata, ref model);

            // We do not need to set an explict ModelValidationNode since CompositeModelBinder does that automatically.
            return(new ModelBindingResult(
                       model,
                       bindingContext.ModelName,
                       isModelSet: true));
        }
        /// <inheritdoc />
        public Task <ModelBindingResult> BindModelAsync([NotNull] ModelBindingContext 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));
        }
Esempio n. 29
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));
        }
Esempio n. 30
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).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));
        }