/// <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(), }); }
/// <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(), }; }
/// <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; }
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); }
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; }
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); }
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); } } }
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; }
/// <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); }