public void CreateSimpleTypeBinderTest(string methodName) { var methodInfo = typeof(Sample).GetRuntimeMethods().Single(x => x.Name == methodName); var binder = _factory.CreateBinder(methodInfo.GetParameters()[0]); Assert.NotNull(binder); Assert.True(binder is SimpleTypeModelBinder); Assert.False(binder is ComplexTypeModelBinder); }
public async Task BindModelAsync(ModelBindingContext bindingContext) { if (bindingContext == null) { throw new ArgumentNullException(nameof(bindingContext)); } var typeValue = bindingContext.ValueProvider.GetValue(nameof(ComplexModel.Type)).Values; var nameValue = bindingContext.ValueProvider.GetValue(nameof(ComplexModel.Name)).Values; var finalModel = new ComplexModel { Name = nameValue, Type = typeValue }; var innerType = LookupType(typeValue); if (innerType != null) { finalModel.Parameters = Activator.CreateInstance(innerType); var modelMetadata = _modelMetadataProvider.GetMetadataForType(innerType); var modelBinder = _modelBinderFactory.CreateBinder(new ModelBinderFactoryContext { Metadata = modelMetadata, CacheToken = modelMetadata }); var modelName = bindingContext.BinderModelName == null ? "Parameters" : $"{bindingContext.BinderModelName}.Parameters"; using (var scope = bindingContext.EnterNestedScope(modelMetadata, modelName, modelName, finalModel.Parameters)) { await modelBinder.BindModelAsync(bindingContext); } } bindingContext.Result = ModelBindingResult.Success(finalModel); return; }
public Task <IBinding?> TryCreateAsync(BindingProviderContext context) { _ = context ?? throw new ArgumentNullException(nameof(context)); var attribute = context.Parameter.GetCustomAttributes(inherit: false).OfType <IBindingSourceMetadata>().FirstOrDefault(); if (!(attribute is null)) { var modelMetadata = _modelMetadataProvider switch { ModelMetadataProvider provider => provider.GetMetadataForParameter(context.Parameter), _ => _modelMetadataProvider.GetMetadataForType(context.Parameter.ParameterType) }; var modelBinderFactoryContext = new ModelBinderFactoryContext { Metadata = modelMetadata, BindingInfo = BindingInfo.GetBindingInfo(context.Parameter.GetCustomAttributes()) }; var modelBinder = _modelBinderFactory.CreateBinder(modelBinderFactoryContext); return(Task.FromResult <IBinding?>(new MvcModelBinding(context.Parameter, modelMetadata, modelBinder, _mvcOptions.ValueProviderFactories))); } return(Task.FromResult <IBinding?>(null)); } }
private static BindingInfo[] GetPropertyBindingInfo( IModelBinderFactory modelBinderFactory, IModelMetadataProvider modelMetadataProvider, ControllerActionDescriptor actionDescriptor) { var properties = actionDescriptor.BoundProperties; if (properties.Count == 0) { return(null); } var propertyBindingInfo = new BindingInfo[properties.Count]; var controllerType = actionDescriptor.ControllerTypeInfo.AsType(); for (var i = 0; i < properties.Count; i++) { var property = properties[i]; var metadata = modelMetadataProvider.GetMetadataForProperty(controllerType, property.Name); var binder = modelBinderFactory.CreateBinder(new ModelBinderFactoryContext { BindingInfo = property.BindingInfo, Metadata = metadata, CacheToken = property, }); propertyBindingInfo[i] = new BindingInfo(binder, metadata); } return(propertyBindingInfo); }
private static BindingInfo[] GetParameterBindingInfo( IModelBinderFactory modelBinderFactory, IModelMetadataProvider modelMetadataProvider, ControllerActionDescriptor actionDescriptor) { var parameters = actionDescriptor.Parameters; if (parameters.Count == 0) { return(null); } var parameterBindingInfo = new BindingInfo[parameters.Count]; for (var i = 0; i < parameters.Count; i++) { var parameter = parameters[i]; var metadata = modelMetadataProvider.GetMetadataForType(parameter.ParameterType); var binder = modelBinderFactory.CreateBinder(new ModelBinderFactoryContext { BindingInfo = parameter.BindingInfo, Metadata = metadata, CacheToken = parameter, }); parameterBindingInfo[i] = new BindingInfo(binder, metadata); } return(parameterBindingInfo); }
public async Task <ModelBindingResult?> BindModelAsync( ParameterDescriptor parameter, ControllerContext controllerContext) { if (parameter == null) { throw new ArgumentNullException(nameof(parameter)); } if (controllerContext == null) { throw new ArgumentNullException(nameof(controllerContext)); } var metadata = _modelMetadataProvider.GetMetadataForType(parameter.ParameterType); var modelBindingContext = DefaultModelBindingContext.CreateBindingContext( controllerContext, new CompositeValueProvider(controllerContext.ValueProviders), metadata, parameter.BindingInfo, parameter.Name); if (parameter.BindingInfo?.BinderModelName != null) { // The name was set explicitly, always use that as the prefix. modelBindingContext.ModelName = parameter.BindingInfo.BinderModelName; } else if (modelBindingContext.ValueProvider.ContainsPrefix(parameter.Name)) { // We have a match for the parameter name, use that as that prefix. modelBindingContext.ModelName = parameter.Name; } else { // No match, fallback to empty string as the prefix. modelBindingContext.ModelName = string.Empty; } var binder = _modelBinderFactory.CreateBinder(new ModelBinderFactoryContext() { BindingInfo = parameter.BindingInfo, Metadata = metadata, CacheToken = parameter, }); await binder.BindModelAsync(modelBindingContext); var modelBindingResult = modelBindingContext.Result; if (modelBindingResult != null && modelBindingResult.Value.IsModelSet) { _validator.Validate( controllerContext, modelBindingContext.ValidationState, modelBindingResult.Value.Key, modelBindingResult.Value.Model); } return(modelBindingResult); }
public async Task BindModelAsync(ModelBindingContext bindingContext) { if (!int.TryParse(bindingContext.ValueProvider.GetValue("id").FirstValue, out int productId)) { throw new Exception("The product id was not provided"); } var editModel = new ProductConfigurationEditModel { Fields = productRepository.GetProductFields(productId) }; for (int i = 0; i < editModel.Fields.Count; i++) { BaseField field = editModel.Fields[i]; ModelMetadata modelMetadata = modelMetadataProvider.GetMetadataForType(field.GetType()); IModelBinder modelBinder = modelBinderFactory.CreateBinder(new ModelBinderFactoryContext { Metadata = modelMetadata, CacheToken = modelMetadata }); string modelName = $"{bindingContext.BinderModelName}.Fields[{i}]".TrimStart('.'); using (var scope = bindingContext.EnterNestedScope(modelMetadata, modelName, modelName, field)) { await modelBinder.BindModelAsync(bindingContext); } } bindingContext.Result = ModelBindingResult.Success(editModel); }
private async Task <object> ExecuteWithParameterAsync(ObjectMethodExecutor executor, object @class, string parameterString) { var firstParameter = executor.MethodParameters[0]; try { var binder = _modelBinderFactory.CreateBinder(firstParameter); var bindResult = await binder.BindModelAsync(parameterString); if (bindResult.IsSuccess) { if (executor.IsMethodAsync) { return(await executor.ExecuteAsync(@class, bindResult.Model)); } return(executor.Execute(@class, bindResult.Model)); } throw new MethodBindException( $"Parameters:{firstParameter.Name} bind failed! ParameterString is: {parameterString} "); } catch (FormatException ex) { _logger.ModelBinderFormattingException(executor.MethodInfo?.Name, firstParameter.Name, parameterString, ex); return(null); } }
private IModelBinder GetBinder(ModelMetadata modelMetadata) { dynamic identity = typeof(ModelMetadata).GetProperty("Identity", BindingFlags.Public | BindingFlags.Instance | BindingFlags.NonPublic).GetValue(modelMetadata); var key = ModelMetadataIdentity.ForParameter(identity.ParameterInfo, modelMetadata.ModelType); var newModelMetadata = new DefaultModelMetadata(_modelMetadataProvider, _detailsProvider, new DefaultMetadataDetails(key, ModelAttributes.GetAttributesForParameter(identity.ParameterInfo, modelMetadata.ModelType)), _modelBindingMessageProvider); newModelMetadata.BindingMetadata.BinderType = null; var factoryContext = new ModelBinderFactoryContext() { Metadata = newModelMetadata, BindingInfo = new BindingInfo() { BinderModelName = newModelMetadata.BinderModelName, BinderType = newModelMetadata.BinderType, BindingSource = newModelMetadata.BindingSource, PropertyFilterProvider = newModelMetadata.PropertyFilterProvider, }, CacheToken = null, }; var binder = _modelBinderFactory.CreateBinder(factoryContext); return(binder); }
private BinderItem[] GetParameterBindingInfo(IModelBinderFactory modelBinderFactory) { if (Parameters.Count == 0) { return(null); } var parameterBindingInfo = new BinderItem[Parameters.Count]; for (var i = 0; i < Parameters.Count; i++) { var parameter = Parameters[i]; var metadata = new ModelMetadata(parameter); var binder = modelBinderFactory.CreateBinder(new ModelBinderFactoryContext { BindingInfo = parameter.BindingInfo, Metadata = metadata, CacheToken = parameter }); parameterBindingInfo[i] = new BinderItem(binder, metadata); } return(parameterBindingInfo); }
protected override async Task <ModelBindingResult> BindAsync(PageContext pageContext, object value, string name, Type type) { var factories = pageContext.ValueProviderFactories; var valueProviderFactoryContext = new ValueProviderFactoryContext(pageContext); for (var i = 0; i < factories.Count; i++) { var factory = factories[i]; await factory.CreateValueProviderAsync(valueProviderFactoryContext); } var valueProvider = new CompositeValueProvider(valueProviderFactoryContext.ValueProviders); var metadata = _modelMetadataProvider.GetMetadataForType(type); var binder = _modelBinderFactory.CreateBinder(new ModelBinderFactoryContext() { BindingInfo = null, Metadata = metadata, CacheToken = null, }); var modelBindingContext = DefaultModelBindingContext.CreateBindingContext( pageContext, valueProvider, metadata, null, name); modelBindingContext.Model = value; if (modelBindingContext.ValueProvider.ContainsPrefix(name)) { // We have a match for the parameter name, use that as that prefix. modelBindingContext.ModelName = name; } else { // No match, fallback to empty string as the prefix. modelBindingContext.ModelName = string.Empty; } await binder.BindModelAsync(modelBindingContext); var result = modelBindingContext.Result; if (result.IsModelSet) { _validator.Validate( pageContext, modelBindingContext.ValidationState, modelBindingContext.ModelName, result.Model); } return(result); }
public async Task <T> Bind <T>(HttpRequest request) where T : new() { //always rewind the stream; otherwise, //if multiple handlers concurrently bind //different models only the first one succeeds request.Body.Position = 0; var modelType = typeof(T); var modelMetadata = modelMetadataProvider.GetMetadataForType(modelType); var actionContext = new ActionContext( request.HttpContext, request.HttpContext.GetRouteData(), new ActionDescriptor(), new ModelStateDictionary()); var valueProvider = await CompositeValueProvider.CreateAsync(actionContext, mvcOptions.Value.ValueProviderFactories); #if NET5_0 if (modelMetadata.BoundConstructor != null) { throw new NotSupportedException("Record type not supported"); } #endif var modelBindingContext = DefaultModelBindingContext.CreateBindingContext( actionContext, valueProvider, modelMetadata, bindingInfo: null, modelName: ""); modelBindingContext.Model = new T(); modelBindingContext.PropertyFilter = _ => true; // All props var factoryContext = new ModelBinderFactoryContext() { Metadata = modelMetadata, BindingInfo = new BindingInfo() { BinderModelName = modelMetadata.BinderModelName, BinderType = modelMetadata.BinderType, BindingSource = modelMetadata.BindingSource, PropertyFilterProvider = modelMetadata.PropertyFilterProvider, }, CacheToken = modelMetadata, }; await modelBinderFactory .CreateBinder(factoryContext) .BindModelAsync(modelBindingContext); return((T)modelBindingContext.Result.Model); }
protected override object GetHttpValue(string name, Type valueType) { if (valueType == typeof(Stream) && name == "$request") { return(HttpContext.Request.Body); } else if (valueType == typeof(Stream) && name == "$response") { return(HttpContext.Response.Body); } else if (valueType == typeof(ISelectedFile) || valueType == typeof(ISelectedFile[])) { return(base.GetHttpValue(name, valueType)); } ModelBinderFactoryContext context = new ModelBinderFactoryContext(); context.BindingInfo = new BindingInfo() { BinderModelName = name, BindingSource = BindingSource.ModelBinding }; context.CacheToken = name + "_" + valueType.Name; context.Metadata = _ModelMetadataProvider.GetMetadataForType(valueType); var binder = _ModelBinderFactory.CreateBinder(context); var bindingContext = DefaultModelBindingContext.CreateBindingContext(ActionContext, this, context.Metadata, context.BindingInfo, name); try { binder.BindModelAsync(bindingContext).Wait(); if (bindingContext.Result.IsModelSet) { return(bindingContext.Result.Model); } } catch { } return(null); }
public async Task InvokeAsync() { using (_logger.BeginScope("consumer invoker begin")) { _logger.LogDebug("Executing consumer Topic: {0}", _consumerContext.ConsumerDescriptor.MethodInfo.Name); var obj = ActivatorUtilities.GetServiceOrCreateInstance(_serviceProvider, _consumerContext.ConsumerDescriptor.ImplTypeInfo.AsType()); var value = _consumerContext.DeliverMessage.Content; if (_executor.MethodParameters.Length > 0) { var firstParameter = _executor.MethodParameters[0]; try { var binder = _modelBinderFactory.CreateBinder(firstParameter); var result = await binder.BindModelAsync(value); if (result.IsSuccess) { _executor.Execute(obj, result.Model); } else { _logger.LogWarning($"Parameters:{firstParameter.Name} bind failed! the content is:" + value); } } catch (FormatException ex) { _logger.ModelBinderFormattingException(_executor.MethodInfo?.Name, firstParameter.Name, value, ex); } } else { _executor.Execute(obj); } } }
public async Task BindModelAsync(ModelBindingContext bindingContext) { var contentType = bindingContext.ActionContext.HttpContext.Request.ContentType; BindingInfo bindingInfo = new BindingInfo(); if (contentType == "application/json") { } else if (contentType == "application/x-www-form-urlencoded") { bindingInfo.BindingSource = BindingSource.Form; } else { bindingContext.Result = ModelBindingResult.Failed(); } var binder = factory.CreateBinder(new ModelBinderFactoryContext { Metadata = bindingContext.ModelMetadata, BindingInfo = bindingInfo, }); await binder.BindModelAsync(bindingContext); }
/// <summary> /// Binds a model specified by <paramref name="parameter"/> using <paramref name="value"/> as the initial value. /// </summary> /// <param name="actionContext">The <see cref="ActionContext"/>.</param> /// <param name="valueProvider">The <see cref="IValueProvider"/>.</param> /// <param name="parameter">The <see cref="ParameterDescriptor"/></param> /// <param name="value">The initial model value.</param> /// <returns>The result of model binding.</returns> public virtual Task <ModelBindingResult> BindModelAsync( ActionContext actionContext, IValueProvider valueProvider, ParameterDescriptor parameter, object value) { if (actionContext == null) { throw new ArgumentNullException(nameof(actionContext)); } if (valueProvider == null) { throw new ArgumentNullException(nameof(valueProvider)); } if (parameter == null) { throw new ArgumentNullException(nameof(parameter)); } var metadata = _modelMetadataProvider.GetMetadataForType(parameter.ParameterType); var binder = _modelBinderFactory.CreateBinder(new ModelBinderFactoryContext { BindingInfo = parameter.BindingInfo, Metadata = metadata, CacheToken = parameter, }); return(BindModelAsync( actionContext, binder, valueProvider, parameter, metadata, value)); }
public async Task BindModelAsync(ModelBindingContext bindingContext) { var actualDiscriminatorValue = await _reader.ReadDiscriminatorAsync(_discriminator.Property, bindingContext.HttpContext); if (null == actualDiscriminatorValue) { throw new CouldNotReadDiscriminatorException(); } var resolvedType = Fn.CreateResolver(_cases)(actualDiscriminatorValue); if (null == resolvedType) { throw new UnresolvableDiscriminatorCaseException(actualDiscriminatorValue); } var metadataForResolvedType = _metadataProvider.GetMetadataForType(resolvedType); var modelBinderForResolvedType = _factory.CreateBinder(new ModelBinderFactoryContext { Metadata = metadataForResolvedType, BindingInfo = new BindingInfo { BindingSource = bindingContext.BindingSource, BinderModelName = bindingContext.BinderModelName } }); if (null == modelBinderForResolvedType) { throw new CouldNotResolveBinderForTypeException(resolvedType); } bindingContext.ModelMetadata = metadataForResolvedType; await modelBinderForResolvedType.BindModelAsync(bindingContext); }
public IModelBinder CreateBinder(ModelBinderFactoryContext context) => new Wrapper(_modelBinderFactory.CreateBinder(context));
public static PageHandlerBinderDelegate CreateHandlerBinder( ParameterBinder parameterBinder, IModelMetadataProvider modelMetadataProvider, IModelBinderFactory modelBinderFactory, CompiledPageActionDescriptor actionDescriptor, HandlerMethodDescriptor handler, MvcOptions mvcOptions) { if (handler.Parameters == null || handler.Parameters.Count == 0) { return(NullHandlerBinder); } var handlerType = actionDescriptor.HandlerTypeInfo.AsType(); var parameterBindingInfo = new BinderItem[handler.Parameters.Count]; for (var i = 0; i < parameterBindingInfo.Length; i++) { var parameter = handler.Parameters[i]; ModelMetadata metadata; if (mvcOptions.AllowValidatingTopLevelNodes && modelMetadataProvider is ModelMetadataProvider modelMetadataProviderBase) { // The default model metadata provider derives from ModelMetadataProvider // and can therefore supply information about attributes applied to parameters. metadata = modelMetadataProviderBase.GetMetadataForParameter(parameter.ParameterInfo); } else { // For backward compatibility, if there's a custom model metadata provider that // only implements the older IModelMetadataProvider interface, access the more // limited metadata information it supplies. In this scenario, validation attributes // are not supported on parameters. metadata = modelMetadataProvider.GetMetadataForType(parameter.ParameterType); } var binder = modelBinderFactory.CreateBinder(new ModelBinderFactoryContext { BindingInfo = parameter.BindingInfo, Metadata = metadata, CacheToken = parameter, }); parameterBindingInfo[i] = new BinderItem(binder, metadata); } return(Bind); async Task Bind(PageContext pageContext, IDictionary <string, object> arguments) { var valueProvider = await CompositeValueProvider.CreateAsync(pageContext, pageContext.ValueProviderFactories); for (var i = 0; i < parameterBindingInfo.Length; i++) { var parameter = handler.Parameters[i]; var bindingInfo = parameterBindingInfo[i]; var modelMetadata = bindingInfo.ModelMetadata; if (!modelMetadata.IsBindingAllowed) { continue; } var result = await parameterBinder.BindModelAsync( pageContext, bindingInfo.ModelBinder, valueProvider, parameter, modelMetadata, value : null); if (result.IsModelSet) { arguments[parameter.Name] = result.Model; } } } }
public static Func <PageContext, object, Task> CreatePropertyBinder( ParameterBinder parameterBinder, IModelMetadataProvider modelMetadataProvider, IModelBinderFactory modelBinderFactory, CompiledPageActionDescriptor actionDescriptor) { if (parameterBinder == null) { throw new ArgumentNullException(nameof(parameterBinder)); } if (actionDescriptor == null) { throw new ArgumentNullException(nameof(actionDescriptor)); } var properties = actionDescriptor.BoundProperties; if (properties == null || properties.Count == 0) { return(NullPropertyBinder); } var handlerType = actionDescriptor.HandlerTypeInfo.AsType(); var propertyBindingInfo = new BinderItem[properties.Count]; for (var i = 0; i < properties.Count; i++) { var property = properties[i]; var metadata = modelMetadataProvider.GetMetadataForProperty(handlerType, property.Name); var binder = modelBinderFactory.CreateBinder(new ModelBinderFactoryContext { BindingInfo = property.BindingInfo, Metadata = metadata, CacheToken = property, }); propertyBindingInfo[i] = new BinderItem(binder, metadata); } return(Bind); async Task Bind(PageContext pageContext, object instance) { var valueProvider = await CompositeValueProvider.CreateAsync(pageContext, pageContext.ValueProviderFactories); for (var i = 0; i < properties.Count; i++) { var property = properties[i]; var bindingInfo = propertyBindingInfo[i]; var modelMetadata = bindingInfo.ModelMetadata; if (!modelMetadata.IsBindingAllowed) { continue; } var result = await parameterBinder.BindModelAsync( pageContext, bindingInfo.ModelBinder, valueProvider, property, modelMetadata, value : null); if (result.IsModelSet) { PropertyValueSetter.SetValue(bindingInfo.ModelMetadata, instance, result.Model); } } } }
public IModelBinder CreateBinder(ModelBinderFactoryContext context) => _factory.CreateBinder(context);
/// <summary> /// Updates the specified <paramref name="model"/> instance using the specified <paramref name="modelBinderFactory"/> /// and the specified <paramref name="valueProvider"/> and executes validation using the specified /// <paramref name="objectModelValidator"/>. /// </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="modelBinderFactory">The <see cref="IModelBinderFactory"/> used for binding.</param> /// <param name="valueProvider">The <see cref="IValueProvider"/> used for looking up values.</param> /// <param name="objectModelValidator">The <see cref="IObjectModelValidator"/> used for validating the /// bound values.</param> /// <param name="propertyFilter">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, IModelBinderFactory modelBinderFactory, IValueProvider valueProvider, IObjectModelValidator objectModelValidator, Func <ModelMetadata, bool> propertyFilter) { 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 (modelBinderFactory == null) { throw new ArgumentNullException(nameof(modelBinderFactory)); } if (valueProvider == null) { throw new ArgumentNullException(nameof(valueProvider)); } if (objectModelValidator == null) { throw new ArgumentNullException(nameof(objectModelValidator)); } if (propertyFilter == null) { throw new ArgumentNullException(nameof(propertyFilter)); } 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); var modelState = actionContext.ModelState; var modelBindingContext = DefaultModelBindingContext.CreateBindingContext( actionContext, valueProvider, modelMetadata, bindingInfo: null, modelName: prefix); modelBindingContext.Model = model; modelBindingContext.PropertyFilter = propertyFilter; var factoryContext = new ModelBinderFactoryContext() { Metadata = modelMetadata, BindingInfo = new BindingInfo() { BinderModelName = modelMetadata.BinderModelName, BinderType = modelMetadata.BinderType, BindingSource = modelMetadata.BindingSource, PropertyFilterProvider = modelMetadata.PropertyFilterProvider, }, // We're using the model metadata as the cache token here so that TryUpdateModelAsync calls // for the same model type can share a binder. This won't overlap with normal model binding // operations because they use the ParameterDescriptor for the token. CacheToken = modelMetadata, }; var binder = modelBinderFactory.CreateBinder(factoryContext); await binder.BindModelAsync(modelBindingContext); var modelBindingResult = modelBindingContext.Result; if (modelBindingResult.IsModelSet) { objectModelValidator.Validate( actionContext, modelBindingContext.ValidationState, modelBindingContext.ModelName, modelBindingResult.Model); return(modelState.IsValid); } return(false); }
private async Task <CustomPropertiesDictionary> BindCore(ModelBindingContext bindingContext) { var model = bindingContext.Model as CustomPropertiesDictionary ?? new CustomPropertiesDictionary(); var keys = GetValueProviderKeys(bindingContext.ActionContext, bindingContext.ModelName + "["); if (keys.Count == 0) { return(model); } foreach (var key in keys) { var keyName = GetKeyName(key); if (keyName == null || model.ContainsKey(keyName)) { continue; } var subPropertyName = GetSubPropertyName(key); if (subPropertyName.EqualsNoCase("__Type__")) { continue; } ModelMetadata valueMetadata; ModelBindingContext valueBindingContext; if (subPropertyName == null) { valueMetadata = _modelMetadataProvider.GetMetadataForType(GetValueType(keys, key, bindingContext.ValueProvider)); valueBindingContext = DefaultModelBindingContext.CreateBindingContext( bindingContext.ActionContext, bindingContext.ValueProvider, valueMetadata, bindingInfo: null, modelName: key); } else { // Is Complex type var modelName = key.Substring(0, key.Length - subPropertyName.Length - 1); var valueType = GetValueType(keys, modelName, bindingContext.ValueProvider); if (!valueType.HasAttribute <CustomModelPartAttribute>(false)) { throw new SecurityException("For security reasons complex types in '{0}' must be decorated with the '{1}' attribute.".FormatInvariant( typeof(CustomPropertiesDictionary).AssemblyQualifiedNameWithoutVersion(), typeof(CustomModelPartAttribute).AssemblyQualifiedNameWithoutVersion())); } valueMetadata = _modelMetadataProvider.GetMetadataForType(valueType); valueBindingContext = DefaultModelBindingContext.CreateBindingContext( bindingContext.ActionContext, bindingContext.ValueProvider, valueMetadata, bindingInfo: null, modelName: key.Substring(0, key.Length - subPropertyName.Length - 1)); } if (valueBindingContext != null) { valueBindingContext.PropertyFilter = bindingContext.PropertyFilter; var factoryContext = new ModelBinderFactoryContext { Metadata = valueMetadata }; var valueBinder = _modelBinderFactory.CreateBinder(factoryContext); if (valueBinder != null) { await valueBinder.BindModelAsync(valueBindingContext); if (valueBindingContext.Result.IsModelSet) { model[keyName] = valueBindingContext.Result.Model; } } } } return(model); }