/// <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 copy of a <see cref="BindingInfo"/>. /// </summary> /// <param name="other">The <see cref="BindingInfo"/> to copy.</param> public BindingInfo(BindingInfo other) { if (other == null) { throw new ArgumentNullException(nameof(other)); } BindingSource = other.BindingSource; BinderModelName = other.BinderModelName; BinderType = other.BinderType; PropertyBindingPredicateProvider = other.PropertyBindingPredicateProvider; }
/// <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; }
/// <summary> /// Constructs a new instance of <see cref="BindingInfo"/> from the given <paramref name="attributes"/>. /// </summary> /// <param name="attributes">A collection of attributes which are used to construct <see cref="BindingInfo"/> /// </param> /// <returns>A new instance of <see cref="BindingInfo"/>.</returns> public static BindingInfo GetBindingInfo(IEnumerable<object> attributes) { var bindingInfo = new BindingInfo(); var isBindingInfoPresent = false; // BinderModelName foreach (var binderModelNameAttribute in attributes.OfType<IModelNameProvider>()) { isBindingInfoPresent = true; if (binderModelNameAttribute?.Name != null) { bindingInfo.BinderModelName = binderModelNameAttribute.Name; break; } } // BinderType foreach (var binderTypeAttribute in attributes.OfType<IBinderTypeProviderMetadata>()) { isBindingInfoPresent = true; if (binderTypeAttribute.BinderType != null) { bindingInfo.BinderType = binderTypeAttribute.BinderType; break; } } // BindingSource foreach (var bindingSourceAttribute in attributes.OfType<IBindingSourceMetadata>()) { isBindingInfoPresent = true; if (bindingSourceAttribute.BindingSource != null) { bindingInfo.BindingSource = bindingSourceAttribute.BindingSource; break; } } // PropertyBindingPredicateProvider var predicateProviders = attributes.OfType<IPropertyBindingPredicateProvider>().ToArray(); if (predicateProviders.Length > 0) { isBindingInfoPresent = true; bindingInfo.PropertyBindingPredicateProvider = new CompositePredicateProvider( predicateProviders); } return isBindingInfoPresent ? bindingInfo : null; }
/// <summary> /// Constructs a new instance of <see cref="ModelBindingContext"/> from given <paramref name="metadata"/> /// and <paramref name="bindingInfo"/>. /// </summary> /// <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">An optional name of the model to be used.</param> /// <returns>A new instance of <see cref="ModelBindingContext"/>.</returns> public static ModelBindingContext GetModelBindingContext( [NotNull] ModelMetadata metadata, BindingInfo bindingInfo, string modelName) { var binderModelName = bindingInfo?.BinderModelName ?? metadata.BinderModelName; var propertyPredicateProvider = bindingInfo?.PropertyBindingPredicateProvider ?? metadata.PropertyBindingPredicateProvider; return new ModelBindingContext { ModelMetadata = metadata, BindingSource = bindingInfo?.BindingSource ?? metadata.BindingSource, PropertyFilter = propertyPredicateProvider?.PropertyFilter, BinderType = bindingInfo?.BinderType ?? metadata.BinderType, BinderModelName = binderModelName, ModelName = binderModelName ?? metadata.PropertyName ?? modelName, FallbackToEmptyPrefix = binderModelName == null, }; }
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; }