protected virtual object CreateModel(IndexModelBindingContext bindingContext) { if (bindingContext == null) { throw new ArgumentNullException(nameof(bindingContext)); } if (_modelCreator == null) { var modelTypeInfo = bindingContext.ModelType.GetTypeInfo(); if (modelTypeInfo.IsAbstract || modelTypeInfo.GetConstructor(Type.EmptyTypes) == null) { if (bindingContext.IsTopLevelObject) { throw new InvalidOperationException($"{modelTypeInfo.FullName} - NoParameterlessConstructor-TopLevelObject"); } throw new InvalidOperationException($"{modelTypeInfo.FullName},{bindingContext.ModelName},{bindingContext.ModelMetadata.ContainerType.FullName}, " + $"NoParameterlessConstructor_ForProperty"); } _modelCreator = Expression .Lambda <Func <object> >(Expression.New(bindingContext.ModelType)) .Compile(); } return(_modelCreator()); }
protected virtual bool CanBindProperty(IndexModelBindingContext bindingContext, ModelMetadata propertyMetadata) { var metadataProviderFilter = bindingContext.ModelMetadata.PropertyFilterProvider?.PropertyFilter; if (metadataProviderFilter?.Invoke(propertyMetadata) == false) { return(false); } if (bindingContext.PropertyFilter?.Invoke(propertyMetadata) == false) { return(false); } if (!propertyMetadata.IsBindingAllowed) { return(false); } if (!CanUpdatePropertyInternal(propertyMetadata)) { return(false); } return(true); }
// Used when the ValueProvider contains the collection to be bound as multiple elements, e.g. foo[0], foo[1]. private Task <CollectionResult> BindComplexCollection(IndexModelBindingContext bindingContext) { var indexPropertyName = ModelNames.CreatePropertyModelName(bindingContext.ModelName, "index"); var valueProviderResultIndex = bindingContext.ValueProvider.GetValue(indexPropertyName); var indexNames = GetIndexNamesFromValueProviderResult(valueProviderResultIndex); return(BindComplexCollectionFromIndexes(bindingContext, indexNames)); }
private async Task BindModelCoreAsync(IndexModelBindingContext bindingContext) { if (bindingContext.Model == null) { bindingContext.Model = CreateModel(bindingContext); } for (var i = 0; i < bindingContext.ModelMetadata.Properties.Count; i++) { var property = bindingContext.ModelMetadata.Properties[i]; if (!CanBindProperty(bindingContext, property)) { continue; } object propertyModel = null; if (property.PropertyGetter != null && property.IsComplexType && !property.ModelType.IsArray) { propertyModel = property.PropertyGetter(bindingContext.Model); } var fieldName = property.BinderModelName ?? property.PropertyName; var modelName = ModelNames.CreatePropertyModelName(bindingContext.ModelName, fieldName); ModelBindingResult result; using (bindingContext.EnterNestedScope( modelMetadata: property, fieldName: fieldName, modelName: modelName, model: propertyModel)) { await BindProperty(bindingContext); result = bindingContext.Result; } if (result.IsModelSet) { SetProperty(bindingContext, modelName, property, result); } else if (property.IsBindingRequired) { var message = property.ModelBindingMessageProvider.MissingBindRequiredValueAccessor(fieldName); bindingContext.ModelState.TryAddModelError(modelName, message); } } bindingContext.Result = ModelBindingResult.Success(bindingContext.Model); }
private bool CanValueBindAnyModelProperties(IndexModelBindingContext bindingContext) { if (bindingContext.ModelMetadata.Properties.Count == 0) { return(false); } var hasBindableProperty = false; var isAnyPropertyEnabledForValueProviderBasedBinding = false; for (var i = 0; i < bindingContext.ModelMetadata.Properties.Count; i++) { var propertyMetadata = bindingContext.ModelMetadata.Properties[i]; if (!CanBindProperty(bindingContext, propertyMetadata)) { continue; } hasBindableProperty = true; var bindingSource = propertyMetadata.BindingSource; if (bindingSource == null || !bindingSource.IsGreedy) { isAnyPropertyEnabledForValueProviderBasedBinding = true; var fieldName = propertyMetadata.BinderModelName ?? propertyMetadata.PropertyName; var modelName = ModelNames.CreatePropertyModelName( bindingContext.ModelName, fieldName); using (bindingContext.EnterNestedScope( modelMetadata: propertyMetadata, fieldName: fieldName, modelName: modelName, model: null)) { if (bindingContext.ValueProvider.ContainsPrefix(bindingContext.ModelName)) { return(true); } } } } if (hasBindableProperty && !isAnyPropertyEnabledForValueProviderBasedBinding) { return(true); } return(false); }
public Task BindModelAsync(IndexModelBindingContext bindingContext) { if (bindingContext == null) { throw new ArgumentNullException(nameof(bindingContext)); } if (!CanCreateModel(bindingContext)) { return(Task.CompletedTask); } return(BindModelCoreAsync(bindingContext)); }
protected virtual void SetProperty( IndexModelBindingContext bindingContext, string modelName, ModelMetadata propertyMetadata, ModelBindingResult result) { if (bindingContext == null) { throw new ArgumentNullException(nameof(bindingContext)); } if (modelName == null) { throw new ArgumentNullException(nameof(modelName)); } if (propertyMetadata == null) { throw new ArgumentNullException(nameof(propertyMetadata)); } if (!result.IsModelSet) { return; } if (propertyMetadata.IsReadOnly) { return; } var value = result.Model; try { propertyMetadata.PropertySetter(bindingContext.Model, value); } catch (Exception exception) { AddModelError(exception, modelName, bindingContext); } }
private static void AddModelError( Exception exception, string modelName, IndexModelBindingContext bindingContext) { var targetInvocationException = exception as TargetInvocationException; if (targetInvocationException?.InnerException != null) { exception = targetInvocationException.InnerException; } var modelState = bindingContext.ModelState; var validationState = modelState.GetFieldValidationState(modelName); if (validationState == ModelValidationState.Unvalidated) { modelState.AddModelError(modelName, exception, bindingContext.ModelMetadata); } }
internal async Task <CollectionResult> BindSimpleCollection( IndexModelBindingContext bindingContext, ValueProviderResult values) { var boundCollection = new List <TElement>(); var elementMetadata = bindingContext.ModelMetadata.ElementMetadata; foreach (var value in values) { bindingContext.ValueProvider = new CompositeValueProvider { // our temporary provider goes at the front of the list new ElementalValueProvider(bindingContext.ModelName, value, values.Culture), bindingContext.ValueProvider }; using (bindingContext.EnterNestedScope( elementMetadata, fieldName: bindingContext.FieldName, modelName: bindingContext.ModelName, model: null)) { await ElementBinder.BindModelAsync(bindingContext); if (bindingContext.Result.IsModelSet) { var boundValue = bindingContext.Result.Model; boundCollection.Add(IndexModelBinderHelper.CastOrDefault <TElement>(boundValue)); } } } return(new CollectionResult { Model = boundCollection }); }
internal bool CanCreateModel(IndexModelBindingContext bindingContext) { var isTopLevelObject = bindingContext.IsTopLevelObject; var bindingSource = bindingContext.BindingSource; if (!isTopLevelObject && bindingSource != null && bindingSource.IsGreedy) { return(false); } if (isTopLevelObject) { return(true); } if (CanValueBindAnyModelProperties(bindingContext)) { return(true); } return(false); }
public Task BindModelAsync(IndexModelBindingContext bindingContext) { return(Inner.BindModelAsync(bindingContext)); }
public Task BindModelAsync(IndexModelBindingContext bindingContext) { return(Task.CompletedTask); }
public NestedScope(IndexModelBindingContext context) { _context = context; }
public Task BindModelAsync(IndexModelBindingContext bindingContext) { if (bindingContext == null) { throw new ArgumentNullException(nameof(bindingContext)); } var valueProviderResult = bindingContext.ValueProvider.GetValue(bindingContext.ModelName); if (valueProviderResult == ValueProviderResult.None) { // no entry return(Task.CompletedTask); } bindingContext.ModelState.SetModelValue(bindingContext.ModelName, valueProviderResult); try { var value = valueProviderResult.FirstValue; object model; if (bindingContext.ModelType == typeof(string)) { if (bindingContext.ModelMetadata.ConvertEmptyStringToNull && string.IsNullOrWhiteSpace(value)) { model = null; } else { model = value; } } else if (string.IsNullOrWhiteSpace(value)) { model = null; } else { model = _typeConverter.ConvertFrom( context: null, culture: valueProviderResult.Culture, value: value); } if (model == null && !bindingContext.ModelMetadata.IsReferenceOrNullableType) { bindingContext.ModelState.TryAddModelError( bindingContext.ModelName, bindingContext.ModelMetadata.ModelBindingMessageProvider.ValueMustNotBeNullAccessor( valueProviderResult.ToString())); return(Task.CompletedTask); } else { bindingContext.Result = ModelBindingResult.Success(model); return(Task.CompletedTask); } } catch (Exception exception) { var isFormatException = exception is FormatException; if (!isFormatException && exception.InnerException != null) { exception = ExceptionDispatchInfo.Capture(exception.InnerException).SourceException; } bindingContext.ModelState.TryAddModelError( bindingContext.ModelName, exception, bindingContext.ModelMetadata); return(Task.CompletedTask); } }
internal async Task <CollectionResult> BindComplexCollectionFromIndexes( IndexModelBindingContext bindingContext, IEnumerable <string> indexNames) { bool indexNamesIsFinite; if (indexNames != null) { indexNamesIsFinite = true; } else { indexNamesIsFinite = false; indexNames = Enumerable.Range(0, int.MaxValue) .Select(i => i.ToString(CultureInfo.InvariantCulture)); } var elementMetadata = bindingContext.ModelMetadata.ElementMetadata; var boundCollection = new List <TElement>(); foreach (var indexName in indexNames) { var fullChildName = ModelNames.CreateIndexModelName(bindingContext.ModelName, indexName); var didBind = false; object boundValue = null; ModelBindingResult?result; using (bindingContext.EnterNestedScope( elementMetadata, fieldName: indexName, modelName: fullChildName, model: null)) { await ElementBinder.BindModelAsync(bindingContext); result = bindingContext.Result; } if (result != null && result.Value.IsModelSet) { didBind = true; boundValue = result.Value.Model; } // infinite size collection stops on first bind failure if (!didBind && !indexNamesIsFinite) { break; } boundCollection.Add(IndexModelBinderHelper.CastOrDefault <TElement>(boundValue)); } return(new CollectionResult { Model = boundCollection, ValidationStrategy = indexNamesIsFinite ? new ExplicitIndexCollectionValidationStrategy(indexNames) : null, }); }
public virtual async Task BindModelAsync(IndexModelBindingContext bindingContext) { if (bindingContext == null) { throw new ArgumentNullException(nameof(bindingContext)); } var model = bindingContext.Model; if (!bindingContext.ValueProvider.ContainsPrefix(bindingContext.ModelName)) { if (bindingContext.IsTopLevelObject) { if (model == null) { model = CreateEmptyCollection(bindingContext.ModelType); } bindingContext.Result = ModelBindingResult.Success(model); } return; } var valueProviderResult = bindingContext.ValueProvider.GetValue(bindingContext.ModelName); CollectionResult result; if (valueProviderResult == ValueProviderResult.None) { result = await BindComplexCollection(bindingContext); } else { result = await BindSimpleCollection(bindingContext, valueProviderResult); } var boundCollection = result.Model; if (model == null) { model = ConvertToCollectionType(bindingContext.ModelType, boundCollection); } else { CopyToModel(model, boundCollection); } Debug.Assert(model != null); if (result.ValidationStrategy != null) { bindingContext.ValidationState.Add(model, new ValidationStateEntry() { Strategy = result.ValidationStrategy, }); } if (valueProviderResult != ValueProviderResult.None) { bindingContext.ModelState.SetModelValue( bindingContext.ModelName, valueProviderResult); } bindingContext.Result = ModelBindingResult.Success(model); }
protected virtual Task BindProperty(IndexModelBindingContext bindingContext) { var binder = _propertyBinders[bindingContext.ModelMetadata]; return(binder.BindModelAsync(bindingContext)); }