コード例 #1
0
        /// <summary>
        /// Creates a new <see cref="ModelBindingContext"/> for top-level model binding operation.
        /// </summary>
        /// <param name="operationBindingContext">
        /// The <see cref="OperationBindingContext"/> associated with the binding operation.
        /// </param>
        /// <param name="metadata"><see cref="ModelMetadata"/> associated with the model.</param>
        /// <param name="bindingInfo"><see cref="BindingInfo"/> associated with the model.</param>
        /// <param name="modelName">The name of the property or parameter being bound.</param>
        /// <returns>A new instance of <see cref="ModelBindingContext"/>.</returns>
        public static ModelBindingContext CreateBindingContext(
            [NotNull] OperationBindingContext operationBindingContext,
            [NotNull] ModelStateDictionary modelState,
            [NotNull] ModelMetadata metadata,
            BindingInfo bindingInfo,
            [NotNull] string modelName)
        {
            var binderModelName           = bindingInfo?.BinderModelName ?? metadata.BinderModelName;
            var propertyPredicateProvider =
                bindingInfo?.PropertyBindingPredicateProvider ?? metadata.PropertyBindingPredicateProvider;

            return(new ModelBindingContext()
            {
                BinderModelName = binderModelName,
                BindingSource = bindingInfo?.BindingSource ?? metadata.BindingSource,
                BinderType = bindingInfo?.BinderType ?? metadata.BinderType,
                PropertyFilter = propertyPredicateProvider?.PropertyFilter,

                // We only support fallback to empty prefix in cases where the model name is inferred from
                // the parameter or property being bound.
                FallbackToEmptyPrefix = binderModelName == null,

                // Because this is the top-level context, FieldName and ModelName should be the same.
                FieldName = binderModelName ?? modelName,
                ModelName = binderModelName ?? modelName,

                IsTopLevelObject = true,
                ModelMetadata = metadata,
                ModelState = modelState,
                OperationBindingContext = operationBindingContext,
                ValueProvider = operationBindingContext.ValueProvider,

                ValidationState = new ValidationStateDictionary(),
            });
        }
コード例 #2
0
        /// <summary>
        /// Creates a new <see cref="ModelBindingContext"/> for top-level model binding operation.
        /// </summary>
        /// <param name="operationBindingContext">
        /// The <see cref="OperationBindingContext"/> associated with the binding operation.
        /// </param>
        /// <param name="metadata"><see cref="ModelMetadata"/> associated with the model.</param>
        /// <param name="bindingInfo"><see cref="BindingInfo"/> associated with the model.</param>
        /// <param name="modelName">The name of the property or parameter being bound.</param>
        /// <returns>A new instance of <see cref="ModelBindingContext"/>.</returns>
        public static ModelBindingContext CreateBindingContext(
            OperationBindingContext operationBindingContext,
            ModelStateDictionary modelState,
            ModelMetadata metadata,
            BindingInfo bindingInfo,
            string modelName)
        {
            if (operationBindingContext == null)
            {
                throw new ArgumentNullException(nameof(operationBindingContext));
            }

            if (modelState == null)
            {
                throw new ArgumentNullException(nameof(modelState));
            }

            if (metadata == null)
            {
                throw new ArgumentNullException(nameof(metadata));
            }

            if (modelName == null)
            {
                throw new ArgumentNullException(nameof(modelName));
            }

            var binderModelName = bindingInfo?.BinderModelName ?? metadata.BinderModelName;
            var propertyPredicateProvider =
                bindingInfo?.PropertyBindingPredicateProvider ?? metadata.PropertyBindingPredicateProvider;

            return new ModelBindingContext()
            {
                BinderModelName = binderModelName,
                BindingSource = bindingInfo?.BindingSource ?? metadata.BindingSource,
                BinderType = bindingInfo?.BinderType ?? metadata.BinderType,
                PropertyFilter = propertyPredicateProvider?.PropertyFilter,

                // We only support fallback to empty prefix in cases where the model name is inferred from
                // the parameter or property being bound.
                FallbackToEmptyPrefix = binderModelName == null,

                // Because this is the top-level context, FieldName and ModelName should be the same.
                FieldName = binderModelName ?? modelName,
                ModelName = binderModelName ?? modelName,

                IsTopLevelObject = true,
                ModelMetadata = metadata,
                ModelState = modelState,
                OperationBindingContext = operationBindingContext,
                ValueProvider = operationBindingContext.ValueProvider,

                ValidationState = new ValidationStateDictionary(),
            };
        }
コード例 #3
0
        /// <inheritdocs />
        public async Task<IDictionary<string, object>> BindArgumentsAsync(WidgetContext context, MethodInfo method, IDictionary<string, object> values)
        {
            var bindingContext = new OperationBindingContext
            {
                HttpContext = context.ViewContext.HttpContext,
                InputFormatters = _options.InputFormatters,
                MetadataProvider = _modelMetadataProvider,
                ModelBinder = new CompositeModelBinder(_options.ModelBinders),
                ValidatorProvider = new CompositeModelValidatorProvider(_options.ModelValidatorProviders),
                ValueProvider = await CompositeValueProvider.CreateAsync(_options.ValueProviderFactories, new ValueProviderFactoryContext(context.ViewContext.HttpContext, context.ViewContext.RouteData.Values))
            };

            var arguments = new Dictionary<string, object>(StringComparer.Ordinal);
            var parameters = method.GetParameters();

            foreach (var parameter in parameters)
            {
                if (values.ContainsKey(parameter.Name))
                {
                    arguments.Add(parameter.Name, values[parameter.Name]);
                }
                else
                {
                    var attribute = parameter.GetCustomAttributes().OfType<IBindingSourceMetadata>().FirstOrDefault();
                    var bindingInfo = new BindingInfo()
                    {
                        BindingSource = attribute?.BindingSource
                    };

                    var metadata = _modelMetadataProvider.GetMetadataForType(parameter.ParameterType);
                    var modelBindingContext = ModelBindingContext.CreateBindingContext(
                        bindingContext,
                        context.ModelState,
                        metadata,
                        bindingInfo,
                        parameter.Name);

                    var result = await bindingContext.ModelBinder.BindModelAsync(modelBindingContext);
                    if (result.IsModelSet)
                    {
                        _objectModelValidator.Validate(bindingContext.ValidatorProvider, context.ModelState, modelBindingContext.ValidationState, result.Key, result.Model);
                        arguments.Add(parameter.Name, result.Model);
                    }
                    else
                    {
                        arguments.Add(parameter.Name, Activator.CreateInstance(parameter.ParameterType));
                    }
                }
            }

            return arguments;
        }
コード例 #4
0
        private static ModelBindingContext GetBindingContext(
            Type modelType,
            IEnumerable <IInputFormatter> inputFormatters = null,
            HttpContext httpContext = null,
            IModelMetadataProvider metadataProvider = null)
        {
            if (httpContext == null)
            {
                httpContext = new DefaultHttpContext();
            }

            if (inputFormatters == null)
            {
                inputFormatters = Enumerable.Empty <IInputFormatter>();
            }

            if (metadataProvider == null)
            {
                metadataProvider = new EmptyModelMetadataProvider();
            }

            var operationBindingContext = new OperationBindingContext
            {
                ActionContext = new ActionContext()
                {
                    HttpContext = httpContext,
                },
                InputFormatters  = inputFormatters.ToList(),
                ModelBinder      = new BodyModelBinder(new TestHttpRequestStreamReaderFactory()),
                MetadataProvider = metadataProvider,
            };

            var bindingContext = new ModelBindingContext
            {
                IsTopLevelObject        = true,
                ModelMetadata           = metadataProvider.GetMetadataForType(modelType),
                ModelName               = "someName",
                ValueProvider           = Mock.Of <IValueProvider>(),
                ModelState              = new ModelStateDictionary(),
                OperationBindingContext = operationBindingContext,
                BindingSource           = BindingSource.Body,
            };

            return(bindingContext);
        }
コード例 #5
0
        private static ModelBindingContext GetBindingContext(
            Type modelType,
            IEnumerable<IInputFormatter> inputFormatters = null,
            HttpContext httpContext = null,
            IModelMetadataProvider metadataProvider = null)
        {
            if (httpContext == null)
            {
                httpContext = new DefaultHttpContext();
            }

            if (inputFormatters == null)
            {
                inputFormatters = Enumerable.Empty<IInputFormatter>();
            }

            if (metadataProvider == null)
            {
                metadataProvider = new EmptyModelMetadataProvider();
            }

            var operationBindingContext = new OperationBindingContext
            {
                InputFormatters = inputFormatters.ToList(),
                ModelBinder = new BodyModelBinder(),
                MetadataProvider = metadataProvider,
                HttpContext = httpContext,
            };

            var bindingContext = new ModelBindingContext
            {
                ModelMetadata = metadataProvider.GetMetadataForType(modelType),
                ModelName = "someName",
                ValueProvider = Mock.Of<IValueProvider>(),
                ModelState = new ModelStateDictionary(),
                OperationBindingContext = operationBindingContext,
                BindingSource = BindingSource.Body,
            };

            return bindingContext;
        }
コード例 #6
0
        private bool TryValidateModel(
            object model,
            string prefix,
            OperationBindingContext operationContext)
        {
            var controller = new TestController();
            controller.ControllerContext = new ControllerContext(operationContext.ActionContext);
            controller.ObjectValidator = ModelBindingTestHelper.GetObjectValidator(operationContext.MetadataProvider);
            controller.MetadataProvider = operationContext.MetadataProvider;
            controller.ControllerContext.ValidatorProviders = new[] { operationContext.ValidatorProvider }.ToList();

            return controller.TryValidateModel(model, prefix);
        }
コード例 #7
0
        private async Task PopulateArgumentsAsync(
            OperationBindingContext operationContext,
            ModelStateDictionary modelState,
            IDictionary<string, object> arguments,
            IEnumerable<ParameterDescriptor> parameterMetadata)
        {
            modelState.MaxAllowedErrors = _options.MaxModelValidationErrors;
            foreach (var parameter in parameterMetadata)
            {
                var metadata = _modelMetadataProvider.GetMetadataForType(parameter.ParameterType);
                var parameterType = parameter.ParameterType;
                var modelBindingContext = GetModelBindingContext(
                    parameter.Name,
                    metadata,
                    parameter.BindingInfo,
                    modelState,
                    operationContext);

                var modelBindingResult = await operationContext.ModelBinder.BindModelAsync(modelBindingContext);
                if (modelBindingResult != null && modelBindingResult.IsModelSet)
                {
                    var modelExplorer = new ModelExplorer(
                        _modelMetadataProvider,
                        metadata,
                        modelBindingResult.Model);

                    arguments[parameter.Name] = modelBindingResult.Model;
                    var validationContext = new ModelValidationContext(
                        modelBindingResult.Key,
                        modelBindingContext.BindingSource,
                        operationContext.ValidatorProvider,
                        modelState,
                        modelExplorer);
                    _validator.Validate(validationContext);
                }
            }
        }
コード例 #8
0
        private static ModelBindingContext GetModelBindingContext(
            string parameterName,
            ModelMetadata metadata,
            BindingInfo bindingInfo,
            ModelStateDictionary modelState,
            OperationBindingContext operationBindingContext)
        {
            var modelBindingContext = ModelBindingContext.GetModelBindingContext(
                metadata,
                bindingInfo,
                parameterName);

            modelBindingContext.ModelState = modelState;
            modelBindingContext.ValueProvider = operationBindingContext.ValueProvider;
            modelBindingContext.OperationBindingContext = operationBindingContext;

            return modelBindingContext;
        }
コード例 #9
0
        /// <summary>
        /// Updates the specified <paramref name="model"/> instance using the specified <paramref name="modelBinder"/>
        /// and the specified <paramref name="valueProvider"/> and executes validation using the specified
        /// <paramref name="validatorProvider"/>.
        /// </summary>
        /// <param name="model">The model instance to update and validate.</param>
        /// <param name="modelType">The type of model instance to update and validate.</param>
        /// <param name="prefix">The prefix to use when looking up values in the <paramref name="valueProvider"/>.
        /// </param>
        /// <param name="actionContext">The <see cref="ActionContext"/> for the current executing request.</param>
        /// <param name="metadataProvider">The provider used for reading metadata for the model type.</param>
        /// <param name="modelBinder">The <see cref="IModelBinder"/> used for binding.</param>
        /// <param name="valueProvider">The <see cref="IValueProvider"/> used for looking up values.</param>
        /// <param name="inputFormatters">
        /// The set of <see cref="IInputFormatter"/> instances for deserializing the body.
        /// </param>
        /// <param name="objectModelValidator">The <see cref="IObjectModelValidator"/> used for validating the
        /// bound values.</param>
        /// <param name="validatorProvider">The <see cref="IModelValidatorProvider"/> used for executing validation
        /// on the model instance.</param>
        /// <param name="predicate">A predicate which can be used to
        /// filter properties(for inclusion/exclusion) at runtime.</param>
        /// <returns>A <see cref="Task"/> that on completion returns <c>true</c> if the update is successful</returns>
        public static async Task <bool> TryUpdateModelAsync(
            object model,
            Type modelType,
            string prefix,
            ActionContext actionContext,
            IModelMetadataProvider metadataProvider,
            IModelBinder modelBinder,
            IValueProvider valueProvider,
            IList <IInputFormatter> inputFormatters,
            IObjectModelValidator objectModelValidator,
            IModelValidatorProvider validatorProvider,
            Func <ModelBindingContext, string, bool> predicate)
        {
            if (model == null)
            {
                throw new ArgumentNullException(nameof(model));
            }

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

            if (prefix == null)
            {
                throw new ArgumentNullException(nameof(prefix));
            }

            if (actionContext == null)
            {
                throw new ArgumentNullException(nameof(actionContext));
            }

            if (metadataProvider == null)
            {
                throw new ArgumentNullException(nameof(metadataProvider));
            }

            if (modelBinder == null)
            {
                throw new ArgumentNullException(nameof(modelBinder));
            }

            if (valueProvider == null)
            {
                throw new ArgumentNullException(nameof(valueProvider));
            }

            if (inputFormatters == null)
            {
                throw new ArgumentNullException(nameof(inputFormatters));
            }

            if (objectModelValidator == null)
            {
                throw new ArgumentNullException(nameof(objectModelValidator));
            }

            if (validatorProvider == null)
            {
                throw new ArgumentNullException(nameof(validatorProvider));
            }

            if (predicate == null)
            {
                throw new ArgumentNullException(nameof(predicate));
            }

            if (!modelType.IsAssignableFrom(model.GetType()))
            {
                var message = Resources.FormatModelType_WrongType(
                    model.GetType().FullName,
                    modelType.FullName);
                throw new ArgumentException(message, nameof(modelType));
            }

            var modelMetadata = metadataProvider.GetMetadataForType(modelType);

            // Clear ModelStateDictionary entries for the model so that it will be re-validated.
            var modelState = actionContext.ModelState;

            ClearValidationStateForModel(modelType, modelState, metadataProvider, prefix);

            var operationBindingContext = new OperationBindingContext
            {
                InputFormatters   = inputFormatters,
                ModelBinder       = modelBinder,
                ValidatorProvider = validatorProvider,
                MetadataProvider  = metadataProvider,
                ActionContext     = actionContext,
                ValueProvider     = valueProvider,
            };

            var modelBindingContext = ModelBindingContext.CreateBindingContext(
                operationBindingContext,
                modelMetadata,
                bindingInfo: null,
                modelName: prefix ?? string.Empty);

            modelBindingContext.Model          = model;
            modelBindingContext.PropertyFilter = predicate;

            var modelBindingResult = await modelBinder.BindModelAsync(modelBindingContext);

            if (modelBindingResult.IsModelSet)
            {
                objectModelValidator.Validate(
                    operationBindingContext.ActionContext,
                    operationBindingContext.ValidatorProvider,
                    modelBindingContext.ValidationState,
                    modelBindingResult.Key,
                    modelBindingResult.Model);

                return(modelState.IsValid);
            }

            return(false);
        }