public async Task BindModelAsync(ModelBindingContext bindingContext) { if (bindingContext == null) { throw new ArgumentNullException(nameof(bindingContext)); } _logger.AttemptingToBindModel(bindingContext); var keyModelName = ModelNames.CreatePropertyModelName(bindingContext.ModelName, "Key"); var keyResult = await TryBindStrongModel <TKey?>(bindingContext, _keyBinder, "Key", keyModelName); var valueModelName = ModelNames.CreatePropertyModelName(bindingContext.ModelName, "Value"); var valueResult = await TryBindStrongModel <TValue?>(bindingContext, _valueBinder, "Value", valueModelName); if (keyResult.IsModelSet && valueResult.IsModelSet) { var model = new KeyValuePair <TKey?, TValue?>( ModelBindingHelper.CastOrDefault <TKey?>(keyResult.Model), ModelBindingHelper.CastOrDefault <TValue?>(valueResult.Model)); bindingContext.Result = ModelBindingResult.Success(model); _logger.DoneAttemptingToBindModel(bindingContext); return; } if (!keyResult.IsModelSet && valueResult.IsModelSet) { bindingContext.ModelState.TryAddModelError( keyModelName, bindingContext.ModelMetadata.ModelBindingMessageProvider.MissingKeyOrValueAccessor()); _logger.DoneAttemptingToBindModel(bindingContext); return; } if (keyResult.IsModelSet && !valueResult.IsModelSet) { bindingContext.ModelState.TryAddModelError( valueModelName, bindingContext.ModelMetadata.ModelBindingMessageProvider.MissingKeyOrValueAccessor()); _logger.DoneAttemptingToBindModel(bindingContext); return; } // If we failed to find data for a top-level model, then generate a // default 'empty' model and return it. if (bindingContext.IsTopLevelObject) { var model = new KeyValuePair <TKey?, TValue?>(); bindingContext.Result = ModelBindingResult.Success(model); } _logger.DoneAttemptingToBindModel(bindingContext); }
private static string GetName(string containerName, ApiParameterDescriptionContext metadata) { if (!string.IsNullOrEmpty(metadata.BinderModelName)) { // Name was explicitly provided return(metadata.BinderModelName); } else { return(ModelBindingHelper.CreatePropertyModelName(containerName, metadata.PropertyName)); } }
public override IEnumerable <ModelValidationResult> Validate( ModelMetadata metadata, object container ) { bool propertiesValid = true; foreach (ModelMetadata propertyMetadata in metadata.Properties) { foreach ( ModelValidator propertyValidator in propertyMetadata.GetValidators( ValidatorProviders ) ) { foreach ( ModelValidationResult propertyResult in propertyValidator.Validate( metadata, container ) ) { propertiesValid = false; yield return(new ModelValidationResult { MemberName = ModelBindingHelper.CreatePropertyModelName( propertyMetadata.PropertyName, propertyResult.MemberName ), Message = propertyResult.Message }); } } } if (propertiesValid) { foreach ( ModelValidator typeValidator in metadata.GetValidators(ValidatorProviders) ) { foreach ( ModelValidationResult typeResult in typeValidator.Validate( metadata, container ) ) { yield return(typeResult); } } } }
public virtual bool BindModel(HttpActionContext actionContext, ModelBindingContext bindingContext) { ModelBindingHelper.ValidateBindingContext(bindingContext); EnsureModel(actionContext, bindingContext); IEnumerable <ModelMetadata> propertyMetadatas = GetMetadataForProperties(actionContext, bindingContext); ComplexModelDto dto = CreateAndPopulateDto(actionContext, bindingContext, propertyMetadatas); // post-processing, e.g. property setters and hooking up validation ProcessDto(actionContext, bindingContext, dto); bindingContext.ValidationNode.ValidateAllProperties = true; // complex models require full validation return(true); }
public override IModelBinder GetBinder(HttpActionContext actionContext, ModelBindingContext bindingContext) { ModelBindingHelper.ValidateBindingContext(bindingContext); if (bindingContext.ValueProvider.ContainsPrefix(bindingContext.ModelName)) { return(CollectionModelBinderUtil.GetGenericBinder(typeof(ICollection <>), typeof(List <>), typeof(CollectionModelBinder <>), bindingContext.ModelMetadata)); } else { return(null); } }
public virtual bool BindModel(HttpActionContext actionContext, ModelBindingContext bindingContext) { ModelBindingHelper.ValidateBindingContext(bindingContext); ValueProviderResult valueProviderResult = bindingContext.ValueProvider.GetValue(bindingContext.ModelName); List <TElement> boundCollection = (valueProviderResult != null) ? BindSimpleCollection(actionContext, bindingContext, valueProviderResult.RawValue, valueProviderResult.Culture) : BindComplexCollection(actionContext, bindingContext); bool retVal = CreateOrReplaceCollection(actionContext, bindingContext, boundCollection); return(retVal); }
public override IModelBinder GetBinder(HttpActionContext actionContext, ModelBindingContext bindingContext) { ModelBindingHelper.ValidateBindingContext(bindingContext); if (!bindingContext.ModelMetadata.IsReadOnly && bindingContext.ModelType.IsArray && bindingContext.ValueProvider.ContainsPrefix(bindingContext.ModelName)) { Type elementType = bindingContext.ModelType.GetElementType(); return((IModelBinder)Activator.CreateInstance(typeof(ArrayModelBinder <>).MakeGenericType(elementType))); } return(null); }
public async Task TryUpdateModel_UsingIncludeExpressionOverload_ReturnsTrue_ModelBindsAndValidatesSuccessfully() { // Arrange var binders = new IModelBinder[] { new TypeConverterModelBinder(), new ComplexModelDtoModelBinder(), new MutableObjectModelBinder() }; var validator = new DataAnnotationsModelValidatorProvider(); var model = new MyModel { MyProperty = "Old-Value", IncludedProperty = "Old-IncludedPropertyValue", ExcludedProperty = "Old-ExcludedPropertyValue" }; var modelStateDictionary = new ModelStateDictionary(); var values = new Dictionary <string, object> { { "", null }, { "MyProperty", "MyPropertyValue" }, { "IncludedProperty", "IncludedPropertyValue" }, { "ExcludedProperty", "ExcludedPropertyValue" } }; var valueProvider = new TestValueProvider(values); var metadataProvider = TestModelMetadataProvider.CreateDefaultProvider(); // Act var result = await ModelBindingHelper.TryUpdateModelAsync( model, "", Mock.Of <HttpContext>(), modelStateDictionary, TestModelMetadataProvider.CreateDefaultProvider(), GetCompositeBinder(binders), valueProvider, new List <IInputFormatter>(), new DefaultObjectValidator(new IExcludeTypeValidationFilter[0], metadataProvider), validator, m => m.IncludedProperty, m => m.MyProperty); // Assert Assert.True(result); Assert.Equal("MyPropertyValue", model.MyProperty); Assert.Equal("IncludedPropertyValue", model.IncludedProperty); Assert.Equal("Old-ExcludedPropertyValue", model.ExcludedProperty); }
public void ClearValidationStateForCollectionsModel_EmtpyModelKey(string modelKey) { // Arrange var metadataProvider = new EmptyModelMetadataProvider(); var dictionary = new ModelStateDictionary(); dictionary["[0].Name"] = new ModelState { ValidationState = ModelValidationState.Invalid }; dictionary.AddModelError("[0].Name", "Name invalid."); dictionary["[0].Id"] = new ModelState { ValidationState = ModelValidationState.Invalid }; dictionary.AddModelError("[0].Id", "Id invalid."); dictionary.AddModelError("[0].Id", "Id required."); dictionary["[0].Category"] = new ModelState { ValidationState = ModelValidationState.Valid }; dictionary["[1].Name"] = new ModelState { ValidationState = ModelValidationState.Valid }; dictionary["[1].Id"] = new ModelState { ValidationState = ModelValidationState.Valid }; dictionary["[1].Category"] = new ModelState { ValidationState = ModelValidationState.Invalid }; dictionary.AddModelError("[1].Category", "Category invalid."); // Act ModelBindingHelper.ClearValidationStateForModel( typeof(List <Product>), dictionary, metadataProvider, modelKey); // Assert Assert.Equal(0, dictionary["[0].Name"].Errors.Count); Assert.Equal(ModelValidationState.Unvalidated, dictionary["[0].Name"].ValidationState); Assert.Equal(0, dictionary["[0].Id"].Errors.Count); Assert.Equal(ModelValidationState.Unvalidated, dictionary["[0].Id"].ValidationState); Assert.Equal(0, dictionary["[0].Category"].Errors.Count); Assert.Equal(ModelValidationState.Unvalidated, dictionary["[0].Category"].ValidationState); Assert.Equal(0, dictionary["[1].Name"].Errors.Count); Assert.Equal(ModelValidationState.Unvalidated, dictionary["[1].Name"].ValidationState); Assert.Equal(0, dictionary["[1].Id"].Errors.Count); Assert.Equal(ModelValidationState.Unvalidated, dictionary["[1].Id"].ValidationState); Assert.Equal(0, dictionary["[1].Category"].Errors.Count); Assert.Equal(ModelValidationState.Unvalidated, dictionary["[1].Category"].ValidationState); }
internal static List <TElement> BindComplexCollectionFromIndexes(HttpActionContext actionContext, ModelBindingContext bindingContext, IEnumerable <string> indexNames) { bool indexNamesIsFinite; if (indexNames != null) { indexNamesIsFinite = true; } else { indexNamesIsFinite = false; indexNames = CollectionModelBinderUtil.GetZeroBasedIndexes(); } List <TElement> boundCollection = new List <TElement>(); foreach (string indexName in indexNames) { string fullChildName = ModelBindingHelper.CreateIndexModelName(bindingContext.ModelName, indexName); ModelBindingContext childBindingContext = new ModelBindingContext(bindingContext) { ModelMetadata = actionContext.GetMetadataProvider().GetMetadataForType(null, typeof(TElement)), ModelName = fullChildName }; bool didBind = false; object boundValue = null; IModelBinder childBinder; if (actionContext.TryGetBinder(childBindingContext, out childBinder)) { didBind = childBinder.BindModel(actionContext, childBindingContext); if (didBind) { boundValue = childBindingContext.Model; // merge validation up bindingContext.ValidationNode.ChildNodes.Add(childBindingContext.ValidationNode); } } // infinite size collection stops on first bind failure if (!didBind && !indexNamesIsFinite) { break; } boundCollection.Add(ModelBindingHelper.CastOrDefault <TElement>(boundValue)); } return(boundCollection); }
public async Task TryUpdateModel_UsingIncludePredicateOverload_ReturnsTrue_ModelBindsAndValidatesSuccessfully() { // Arrange var binders = new IModelBinder[] { new TypeConverterModelBinder(), new ComplexModelDtoModelBinder(), new MutableObjectModelBinder() }; var validator = new DataAnnotationsModelValidatorProvider(); var model = new MyModel { MyProperty = "Old-Value", IncludedProperty = "Old-IncludedPropertyValue", ExcludedProperty = "Old-ExcludedPropertyValue" }; var modelStateDictionary = new ModelStateDictionary(); var values = new Dictionary <string, object> { { "", null }, { "MyProperty", "MyPropertyValue" }, { "IncludedProperty", "IncludedPropertyValue" }, { "ExcludedProperty", "ExcludedPropertyValue" } }; Func <ModelBindingContext, string, bool> includePredicate = (context, propertyName) => string.Equals(propertyName, "IncludedProperty", StringComparison.OrdinalIgnoreCase) || string.Equals(propertyName, "MyProperty", StringComparison.OrdinalIgnoreCase); var valueProvider = new DictionaryBasedValueProvider <TestValueBinderMetadata>(values); // Act var result = await ModelBindingHelper.TryUpdateModelAsync( model, "", Mock.Of <HttpContext>(), modelStateDictionary, new DataAnnotationsModelMetadataProvider(), GetCompositeBinder(binders), valueProvider, validator, includePredicate); // Assert Assert.True(result); Assert.Equal("MyPropertyValue", model.MyProperty); Assert.Equal("IncludedPropertyValue", model.IncludedProperty); Assert.Equal("Old-ExcludedPropertyValue", model.ExcludedProperty); }
/// <summary> /// Attempts to convert the values in <paramref name="result"/> to the specified type. /// </summary> /// <typeparam name="T">The <see cref="Type"/> for conversion.</typeparam> /// <param name="result">The <see cref="ValueProviderResult"/>.</param> /// <returns> /// The converted value, or the default value of <typeparamref name="T"/> if the value could not be converted. /// </returns> /// <remarks> /// Copyright (c) .NET Foundation and Contributors /// All rights reserved. /// Licensed under the Apache License, Version 2.0 (the "License"); you may not use /// this file except in compliance with the License.You may obtain a copy of the license at: /// http://www.apache.org/licenses/LICENSE-2.0 /// Unless required by applicable law or agreed to in writing, software distributed /// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR /// CONDITIONS OF ANY KIND, either express or implied. See the License for the /// specific language governing permissions and limitations under the License. /// </remarks> private static T ConvertTo <T>(ValueProviderResult result) { object valueToConvert = null; if (result.Values.Count == 1) { valueToConvert = result.Values[0]; } else if (result.Values.Count > 1) { valueToConvert = result.Values.ToArray(); } return(ModelBindingHelper.ConvertTo <T>(valueToConvert, result.Culture)); }
/// <summary> /// Validate a single node, not including its children. /// </summary> /// <param name="metadata">The <see cref="ModelMetadata"/>.</param> /// <param name="validationContext">The <see cref="BodyModelValidatorContext"/>.</param> /// <param name="container">The object to validate.</param> /// <param name="validators">The collection of <see cref="ModelValidator"/>s.</param> /// <returns> /// <see langword="true"/> if validation succeeds for the given <paramref name="metadata"/> and /// <paramref name="container"/>; <see langword="false"/> otherwise. /// </returns> protected virtual bool ShallowValidate( ModelMetadata metadata, BodyModelValidatorContext validationContext, object container, IEnumerable <ModelValidator> validators) { if (metadata == null) { throw Error.ArgumentNull("metadata"); } if (validationContext == null) { throw Error.ArgumentNull("validationContext"); } if (validators == null) { throw Error.ArgumentNull("validators"); } bool isValid = true; string modelKey = null; // When the are no validators we bail quickly. This saves a GetEnumerator allocation. // In a large array (tens of thousands or more) scenario it's very significant. ICollection validatorsAsCollection = validators as ICollection; if (validatorsAsCollection != null && validatorsAsCollection.Count == 0) { return(isValid); } foreach (ModelValidator validator in validators) { foreach (ModelValidationResult error in validator.Validate(metadata, container)) { if (modelKey == null) { modelKey = validationContext.RootPrefix; foreach (IBodyModelValidatorKeyBuilder keyBuilder in validationContext.KeyBuilders.Reverse()) { modelKey = keyBuilder.AppendTo(modelKey); } } string errorKey = ModelBindingHelper.CreatePropertyModelName(modelKey, error.MemberName); validationContext.ModelState.AddModelError(errorKey, error.Message); isValid = false; } } return(isValid); }
/// <inheritdoc /> public Task BindModelAsync(ModelBindingContext bindingContext) { if (bindingContext == null) { throw new ArgumentNullException(nameof(bindingContext)); } var request = bindingContext.HttpContext.Request; // Property name can be null if the model metadata represents a type (rather than a property or parameter). var headerName = bindingContext.FieldName; object model; if (bindingContext.ModelType == typeof(string)) { var value = request.Headers[headerName]; model = (string)value; } else if (ModelBindingHelper.CanGetCompatibleCollection <string>(bindingContext)) { var values = request.Headers.GetCommaSeparatedValues(headerName); model = GetCompatibleCollection(bindingContext, values); } else { // An unsupported datatype or a new collection is needed (perhaps because target type is an array) but // can't assign it to the property. model = null; } if (model == null) { // Silently fail if unable to create an instance or use the current instance. Also reach here in the // typeof(string) case if the header does not exist in the request and in the // typeof(IEnumerable<string>) case if the header does not exist and this is not a top-level object. bindingContext.Result = ModelBindingResult.Failed(bindingContext.ModelName); } else { bindingContext.ModelState.SetModelValue( bindingContext.ModelName, request.Headers.GetCommaSeparatedValues(headerName), request.Headers[headerName]); bindingContext.Result = ModelBindingResult.Success(bindingContext.ModelName, model); } return(TaskCache.CompletedTask); }
private static bool ValidateProperties(ModelMetadata metadata, ValidationContext validationContext, string prefix) { bool isValid = true; foreach (ModelMetadata childMetadata in metadata.Properties) { string childPrefix = ModelBindingHelper.CreatePropertyModelName(prefix, childMetadata.PropertyName); if (!ValidateNodeAndChildren(childMetadata, validationContext, metadata.Model, childPrefix)) { isValid = false; } } return(isValid); }
public void GetPropertyName_FieldExpression_Throws() { // Arrange Expression <Func <User, object> > expression = m => m._userId; // Act & Assert var ex = Assert.Throws <InvalidOperationException>(() => ModelBindingHelper.GetPropertyName(expression.Body)); Assert.Equal(string.Format("The passed expression of expression node type '{0}' is invalid." + " Only simple member access expressions for model properties are supported.", expression.Body.NodeType), ex.Message); }
public override IModelBinder GetBinder(HttpActionContext actionContext, ModelBindingContext bindingContext) { ModelBindingHelper.ValidateBindingContext(bindingContext); if (bindingContext.ModelType == ModelType) { if (SuppressPrefixCheck || bindingContext.ValueProvider.ContainsPrefix(bindingContext.ModelName)) { return(_modelBinderFactory()); } } return(null); }
public async Task TryUpdateModel_UsingDefaultIncludeOverload_IncludesAllProperties() { // Arrange var binders = new IModelBinder[] { new TypeConverterModelBinder(), new ComplexModelDtoModelBinder(), new MutableObjectModelBinder() }; var validator = new DataAnnotationsModelValidatorProvider(); var model = new MyModel { MyProperty = "Old-Value", IncludedProperty = "Old-IncludedPropertyValue", ExcludedProperty = "Old-ExcludedPropertyValue" }; var modelStateDictionary = new ModelStateDictionary(); var values = new Dictionary <string, object> { { "", null }, { "MyProperty", "MyPropertyValue" }, { "IncludedProperty", "IncludedPropertyValue" }, { "ExcludedProperty", "ExcludedPropertyValue" } }; var valueProvider = new TestValueProvider(values); var metadataProvider = TestModelMetadataProvider.CreateDefaultProvider(); // Act var result = await ModelBindingHelper.TryUpdateModelAsync( model, "", Mock.Of <HttpContext>(), modelStateDictionary, metadataProvider, GetCompositeBinder(binders), valueProvider, new DefaultObjectValidator(Mock.Of <IValidationExcludeFiltersProvider>(), metadataProvider), validator); // Assert // Includes everything. Assert.True(result); Assert.Equal("MyPropertyValue", model.MyProperty); Assert.Equal("IncludedPropertyValue", model.IncludedProperty); Assert.Equal("ExcludedPropertyValue", model.ExcludedProperty); }
private Task <bool> TryUpdateModel( object model, string prefix, ModelBindingTestContext testContext) { return(ModelBindingHelper.TryUpdateModelAsync( model, model.GetType(), prefix, testContext, testContext.MetadataProvider, TestModelBinderFactory.CreateDefault(), new CompositeValueProvider(testContext.ValueProviders), ModelBindingTestHelper.GetObjectValidator(testContext.MetadataProvider))); }
public void LogError(string errorPath, Exception exception) { if (errorPath == null) { throw Error.ArgumentNull("errorPath"); } if (exception == null) { throw Error.ArgumentNull("exception"); } string key = ModelBindingHelper.ConcatenateKeys(_prefix, errorPath); _modelState.AddModelError(key, exception); }
public void LogError(string errorPath, string errorMessage) { if (errorPath == null) { throw Error.ArgumentNull("errorPath"); } if (errorMessage == null) { throw Error.ArgumentNull("errorMessage"); } string key = ModelBindingHelper.ConcatenateKeys(_prefix, errorPath); _modelState.AddModelError(key, errorMessage); }
internal void ProcessDto(HttpActionContext actionContext, ModelBindingContext bindingContext, ComplexModelDto dto) { HashSet <string> requiredProperties; Dictionary <string, ModelValidator> requiredValidators; HashSet <string> skipProperties; GetRequiredPropertiesCollection(actionContext, bindingContext, out requiredProperties, out requiredValidators, out skipProperties); // Eliminate provided properties from requiredProperties; leaving just *missing* required properties. requiredProperties.ExceptWith(dto.Results.Select(r => r.Key.PropertyName)); foreach (string missingRequiredProperty in requiredProperties) { string modelStateKey = ModelBindingHelper.CreatePropertyModelName( bindingContext.ValidationNode.ModelStateKey, missingRequiredProperty); // Update Model as SetProperty() would: Place null value where validator will check for non-null. This // ensures a failure result from a required validator (if any) even for a non-nullable property. // (Otherwise, propertyMetadata.Model is likely already null.) ModelMetadata propertyMetadata = bindingContext.PropertyMetadata[missingRequiredProperty]; propertyMetadata.Model = null; // Execute validator (if any) to get custom error message. ModelValidator validator = requiredValidators[missingRequiredProperty]; bool addedError = RunValidator(validator, bindingContext, propertyMetadata, modelStateKey); // Fall back to default message if HttpBindingBehaviorAttribute required this property or validator // (oddly) succeeded. if (!addedError) { bindingContext.ModelState.AddModelError(modelStateKey, Error.Format(SRResources.MissingRequiredMember, missingRequiredProperty)); } } // for each property that was bound, call the setter, recording exceptions as necessary foreach (var entry in dto.Results) { ModelMetadata propertyMetadata = entry.Key; ComplexModelDtoResult dtoResult = entry.Value; if (dtoResult != null) { SetProperty(actionContext, bindingContext, propertyMetadata, dtoResult, requiredValidators[propertyMetadata.PropertyName]); bindingContext.ValidationNode.ChildNodes.Add(dtoResult.ValidationNode); } } }
/// <summary> /// Attempt to bind against the given ActionContext. /// </summary> /// <param name="actionContext">The action context.</param> /// <param name="bindingContext">The binding context.</param> /// <param name="binders">set of binders to use for binding</param> /// <returns>True if the bind was successful, else false.</returns> public static bool Bind( this HttpActionContext actionContext, ModelBindingContext bindingContext, IEnumerable <IModelBinder> binders ) { if (actionContext == null) { throw Error.ArgumentNull("actionContext"); } if (bindingContext == null) { throw Error.ArgumentNull("bindingContext"); } // Protects against stack overflow for deeply nested model binding RuntimeHelpers.EnsureSufficientExecutionStack(); Type modelType = bindingContext.ModelType; HttpConfiguration config = actionContext.ControllerContext.Configuration; ModelBinderProvider providerFromAttr; if (ModelBindingHelper.TryGetProviderFromAttributes(modelType, out providerFromAttr)) { IModelBinder binder = providerFromAttr.GetBinder(config, modelType); if (binder != null) { return(binder.BindModel(actionContext, bindingContext)); } } foreach (IModelBinder binder in binders) { if (binder != null) { if (binder.BindModel(actionContext, bindingContext)) { return(true); } } } // Either we couldn't find a binder, or the binder couldn't bind. Distinction is not important. return(false); }
// Used when the ValueProvider contains the collection to be bound as a single element, e.g. the raw value // is [ "1", "2" ] and needs to be converted to an int[]. internal static List <TElement> BindSimpleCollection( HttpActionContext actionContext, ModelBindingContext bindingContext, object rawValue, CultureInfo culture ) { if (rawValue == null) { return(null); // nothing to do } List <TElement> boundCollection = new List <TElement>(); object[] rawValueArray = ModelBindingHelper.RawValueToObjectArray(rawValue); foreach (object rawValueElement in rawValueArray) { ModelBindingContext innerBindingContext = new ModelBindingContext(bindingContext) { ModelMetadata = actionContext .GetMetadataProvider() .GetMetadataForType(null, typeof(TElement)), ModelName = bindingContext.ModelName, ValueProvider = new CompositeValueProvider { new ElementalValueProvider( bindingContext.ModelName, rawValueElement, culture ), // our temporary provider goes at the front of the list bindingContext.ValueProvider } }; object boundValue = null; if (actionContext.Bind(innerBindingContext)) { boundValue = innerBindingContext.Model; bindingContext.ValidationNode.ChildNodes.Add( innerBindingContext.ValidationNode ); } boundCollection.Add(ModelBindingHelper.CastOrDefault <TElement>(boundValue)); } return(boundCollection); }
private void ValidateProperties(HttpActionContext actionContext) { // Based off CompositeModelValidator. ModelStateDictionary modelState = actionContext.ModelState; // DevDiv Bugs #227802 - Caching problem in ModelMetadata requires us to manually regenerate // the ModelMetadata. object model = ModelMetadata.Model; ModelMetadata updatedMetadata = actionContext .GetMetadataProvider() .GetMetadataForType(() => model, ModelMetadata.ModelType); foreach (ModelMetadata propertyMetadata in updatedMetadata.Properties) { // Only want to add errors to ModelState if something doesn't already exist for the property node, // else we could end up with duplicate or irrelevant error messages. string propertyKeyRoot = ModelBindingHelper.CreatePropertyModelName( ModelStateKey, propertyMetadata.PropertyName ); if (modelState.IsValidField(propertyKeyRoot)) { foreach ( ModelValidator propertyValidator in actionContext.GetValidators( propertyMetadata ) ) { foreach ( ModelValidationResult propertyResult in propertyValidator.Validate( propertyMetadata, model ) ) { string thisErrorKey = ModelBindingHelper.CreatePropertyModelName( propertyKeyRoot, propertyResult.MemberName ); modelState.AddModelError(thisErrorKey, propertyResult.Message); } } } } }
public void GetPropertyName_NonParameterBasedExpression_Throws() { // Arrange var someUser = new User(); // PropertyAccessor with a property name invalid as it originates from a variable accessor. Expression <Func <User, object> > expression = m => someUser.Address; // Act & Assert var ex = Assert.Throws <InvalidOperationException>(() => ModelBindingHelper.GetPropertyName(expression.Body)); Assert.Equal(string.Format("The passed expression of expression node type '{0}' is invalid." + " Only simple member access expressions for model properties are supported.", expression.Body.NodeType), ex.Message); }
public override IModelBinder GetBinder(HttpActionContext actionContext, ModelBindingContext bindingContext) { ModelBindingHelper.ValidateBindingContext(bindingContext); string keyFieldName = ModelBindingHelper.CreatePropertyModelName(bindingContext.ModelName, "key"); string valueFieldName = ModelBindingHelper.CreatePropertyModelName(bindingContext.ModelName, "value"); if (bindingContext.ValueProvider.ContainsPrefix(keyFieldName) && bindingContext.ValueProvider.ContainsPrefix(valueFieldName)) { return(ModelBindingHelper.GetPossibleBinderInstance(bindingContext.ModelType, typeof(KeyValuePair <,>) /* supported model type */, typeof(KeyValuePairModelBinder <,>) /* binder type */)); } else { // 'key' or 'value' missing return(null); } }
public bool BindModel(HttpActionContext actionContext, ModelBindingContext bindingContext) { ValueProviderResult valueProviderResult = GetCompatibleValueProviderResult(bindingContext); if (valueProviderResult == null) { return(false); // conversion would have failed } bindingContext.ModelState.SetModelValue(bindingContext.ModelName, valueProviderResult); object model = valueProviderResult.RawValue; ModelBindingHelper.ReplaceEmptyStringWithNull(bindingContext.ModelMetadata, ref model); bindingContext.Model = model; return(true); }
private async Task <bool> TryUpdateModelAsync( object model, string prefix, ModelBindingTestContext testContext) { var valueProvider = await CompositeValueProvider.CreateAsync(testContext); return(await ModelBindingHelper.TryUpdateModelAsync( model, model.GetType(), prefix, testContext, testContext.MetadataProvider, TestModelBinderFactory.CreateDefault(), valueProvider, ModelBindingTestHelper.GetObjectValidator(testContext.MetadataProvider))); }
private void ValidateThis(HttpActionContext actionContext, ModelValidationNode parentNode) { ModelStateDictionary modelState = actionContext.ModelState; if (!modelState.IsValidField(ModelStateKey)) { return; // short-circuit } // If 'this' is null and there is no parent, we cannot validate, and // the DataAnnotationsModelValidator will throw. So we intercept here // to provide a catch-all value-required validation error if (parentNode == null && ModelMetadata.Model == null) { string trueModelStateKey = ModelBindingHelper.CreatePropertyModelName( ModelStateKey, ModelMetadata.GetDisplayName() ); modelState.AddModelError(trueModelStateKey, SRResources.Validation_ValueNotFound); return; } _validators = actionContext.GetValidators(ModelMetadata); object container = TryConvertContainerToMetadataType(parentNode); // Optimize for the common case where the validators are in an array ModelValidator[] validators = _validators.AsArray(); for (int i = 0; i < validators.Length; i++) { ModelValidator validator = validators[i]; foreach ( ModelValidationResult validationResult in validator.Validate( ModelMetadata, container ) ) { string trueModelStateKey = ModelBindingHelper.CreatePropertyModelName( ModelStateKey, validationResult.MemberName ); modelState.AddModelError(trueModelStateKey, validationResult.Message); } } }