public void SetProperty_PropertyHasDefaultValue_SetsDefaultValue() { // Arrange HttpActionContext context = ContextUtil.CreateActionContext(); ModelBindingContext bindingContext = new ModelBindingContext { ModelMetadata = GetMetadataForObject(new Person()) }; ModelMetadata propertyMetadata = bindingContext.ModelMetadata.Properties.Single(o => o.PropertyName == "PropertyWithDefaultValue"); ModelValidationNode validationNode = new ModelValidationNode(propertyMetadata, "foo"); ComplexModelDtoResult dtoResult = new ComplexModelDtoResult(null /* model */, validationNode); ModelValidator requiredValidator = context.GetValidators(propertyMetadata).Where(v => v.IsRequired).FirstOrDefault(); TestableMutableObjectModelBinder testableBinder = new TestableMutableObjectModelBinder(); // Act testableBinder.SetPropertyPublic(context, bindingContext, propertyMetadata, dtoResult, requiredValidator); // Assert var person = Assert.IsType <Person>(bindingContext.Model); Assert.Equal(123.456m, person.PropertyWithDefaultValue); Assert.True(context.ModelState.IsValid); }
public void SetProperty_PropertyIsSettable_CallsSetter() { // Arrange Person model = new Person(); HttpActionContext context = ContextUtil.CreateActionContext(); ModelBindingContext bindingContext = new ModelBindingContext { ModelMetadata = GetMetadataForObject(model) }; ModelMetadata propertyMetadata = bindingContext.ModelMetadata.Properties.Single(o => o.PropertyName == "DateOfBirth"); ModelValidationNode validationNode = new ModelValidationNode(propertyMetadata, "foo"); ComplexModelDtoResult dtoResult = new ComplexModelDtoResult(new DateTime(2001, 1, 1), validationNode); ModelValidator requiredValidator = context.GetValidators(propertyMetadata).Where(v => v.IsRequired).FirstOrDefault(); TestableMutableObjectModelBinder testableBinder = new TestableMutableObjectModelBinder(); // Act testableBinder.SetPropertyPublic(context, bindingContext, propertyMetadata, dtoResult, requiredValidator); // Assert validationNode.Validate(context); Assert.True(context.ModelState.IsValid); Assert.Equal(new DateTime(2001, 1, 1), model.DateOfBirth); }
public void SetProperty_SettingNullableTypeToNull_RequiredValidatorPresent_PropertySetterThrows_AddsRequiredMessageString() { // Arrange HttpActionContext context = ContextUtil.CreateActionContext(); ModelBindingContext bindingContext = new ModelBindingContext { ModelMetadata = GetMetadataForObject(new ModelWhosePropertySetterThrows()), ModelName = "foo" }; ModelMetadata propertyMetadata = bindingContext.ModelMetadata.Properties.Single(o => o.PropertyName == "Name"); ModelValidationNode validationNode = new ModelValidationNode(propertyMetadata, "foo.Name"); ComplexModelDtoResult dtoResult = new ComplexModelDtoResult(null /* model */, validationNode); ModelValidator requiredValidator = context.GetValidators(propertyMetadata).Where(v => v.IsRequired).FirstOrDefault(); TestableMutableObjectModelBinder testableBinder = new TestableMutableObjectModelBinder(); // Act testableBinder.SetPropertyPublic(context, bindingContext, propertyMetadata, dtoResult, requiredValidator); // Assert Assert.False(bindingContext.ModelState.IsValid); Assert.Equal(1, bindingContext.ModelState["foo.Name"].Errors.Count); Assert.Equal("This message comes from the [Required] attribute.", bindingContext.ModelState["foo.Name"].Errors[0].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); // Are all of the required fields accounted for? HashSet <string> missingRequiredProperties = new HashSet <string>(requiredProperties.Except(dto.Results.Select(r => r.Key.PropertyName))); foreach (string missingRequiredProperty in missingRequiredProperties) { string key = ModelBindingHelper.CreatePropertyModelName(bindingContext.ValidationNode.ModelStateKey, missingRequiredProperty); bindingContext.ModelState.AddModelError(key, 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); } } }
public void SetProperty_PropertyIsReadOnly_DoesNothing() { // Arrange ModelBindingContext bindingContext = new ModelBindingContext { ModelMetadata = GetMetadataForType(typeof(Person)) }; ModelMetadata propertyMetadata = bindingContext.ModelMetadata.Properties.Single( o => o.PropertyName == "NonUpdateableProperty" ); ModelValidationNode validationNode = new ModelValidationNode(propertyMetadata, "foo"); ComplexModelDtoResult dtoResult = new ComplexModelDtoResult( null /* model */ , validationNode ); TestableMutableObjectModelBinder testableBinder = new TestableMutableObjectModelBinder(); // Act testableBinder.SetPropertyPublic( null, bindingContext, propertyMetadata, dtoResult, requiredValidator: null ); // Assert // If didn't throw, success! }
public void SetProperty_SettingNullableTypeToNull_RequiredValidatorNotPresent_PropertySetterThrows_AddsRequiredMessageString() { // Arrange HttpActionContext context = ContextUtil.CreateActionContext(); ModelBindingContext bindingContext = new ModelBindingContext { ModelMetadata = GetMetadataForObject(new ModelWhosePropertySetterThrows()), ModelName = "foo" }; ModelMetadata propertyMetadata = bindingContext.ModelMetadata.Properties.Single(o => o.PropertyName == "NameNoAttribute"); ModelValidationNode validationNode = new ModelValidationNode(propertyMetadata, "foo.NameNoAttribute"); ComplexModelDtoResult dtoResult = new ComplexModelDtoResult(null /* model */, validationNode); ModelValidator requiredValidator = context.GetValidators(propertyMetadata).Where(v => v.IsRequired).FirstOrDefault(); TestableMutableObjectModelBinder testableBinder = new TestableMutableObjectModelBinder(); // Act testableBinder.SetPropertyPublic(context, bindingContext, propertyMetadata, dtoResult, requiredValidator); // Assert Assert.False(bindingContext.ModelState.IsValid); ModelError modelError = Assert.Single(bindingContext.ModelState["foo.NameNoAttribute"].Errors); Assert.Equal( "This is a different exception." + Environment.NewLine + "Parameter name: value", modelError.Exception.Message); }
public void SetProperty_PropertyIsSettable_SetterThrows_RecordsError() { // Arrange Person model = new Person { DateOfBirth = new DateTime(1900, 1, 1) }; ModelBindingContext bindingContext = new ModelBindingContext { ModelMetadata = GetMetadataForObject(model) }; ModelMetadata propertyMetadata = bindingContext.ModelMetadata.Properties.Single(o => o.PropertyName == "DateOfDeath"); ModelValidationNode validationNode = new ModelValidationNode(propertyMetadata, "foo"); ComplexModelDtoResult dtoResult = new ComplexModelDtoResult(new DateTime(1800, 1, 1), validationNode); TestableMutableObjectModelBinder testableBinder = new TestableMutableObjectModelBinder(); // Act testableBinder.SetPropertyPublic(null, bindingContext, propertyMetadata, dtoResult, requiredValidator: null); // Assert Assert.Equal(@"Date of death can't be before date of birth. Parameter name: value", bindingContext.ModelState["foo"].Errors[0].Exception.Message); }
public void Constructor_SetsProperties() { // Arrange ModelValidationNode validationNode = GetValidationNode(); // Act ComplexModelDtoResult result = new ComplexModelDtoResult("some string", validationNode); // Assert Assert.Equal("some string", result.Model); Assert.Equal(validationNode, result.ValidationNode); }
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); } } }
public virtual void SetPropertyPublic( HttpActionContext context, ModelBindingContext bindingContext, ModelMetadata propertyMetadata, ComplexModelDtoResult dtoResult, ModelValidator requiredValidator ) { base.SetProperty( context, bindingContext, propertyMetadata, dtoResult, requiredValidator ); }
protected override void SetProperty( HttpActionContext actionContext, ModelBindingContext bindingContext, ModelMetadata propertyMetadata, ComplexModelDtoResult dtoResult, ModelValidator requiredValidator ) { SetPropertyPublic( actionContext, bindingContext, propertyMetadata, dtoResult, requiredValidator ); }
public void SetProperty_SettingNonNullableValueTypeToNull_RequiredValidatorPresent_AddsModelError() { // Arrange HttpActionContext context = ContextUtil.CreateActionContext(); ModelBindingContext bindingContext = new ModelBindingContext { ModelMetadata = GetMetadataForObject(new Person()), ModelName = "foo" }; ModelMetadata propertyMetadata = bindingContext.ModelMetadata.Properties.Single( o => o.PropertyName == "ValueTypeRequired" ); ModelValidationNode validationNode = new ModelValidationNode( propertyMetadata, "foo.ValueTypeRequired" ); ComplexModelDtoResult dtoResult = new ComplexModelDtoResult( null /* model */ , validationNode ); ModelValidator requiredValidator = context .GetValidators(propertyMetadata) .Where(v => v.IsRequired) .FirstOrDefault(); TestableMutableObjectModelBinder testableBinder = new TestableMutableObjectModelBinder(); // Act testableBinder.SetPropertyPublic( context, bindingContext, propertyMetadata, dtoResult, requiredValidator ); // Assert Assert.False(bindingContext.ModelState.IsValid); Assert.Equal( "Sample message", bindingContext.ModelState["foo.ValueTypeRequired"].Errors[0].ErrorMessage ); }
public void SetProperty_SettingNonNullableValueTypeToNull_RequiredValidatorNotPresent_RegistersValidationCallback() { // Arrange HttpActionContext context = ContextUtil.CreateActionContext(); ModelBindingContext bindingContext = new ModelBindingContext { ModelMetadata = GetMetadataForObject(new Person()), }; ModelMetadata propertyMetadata = bindingContext.ModelMetadata.Properties.Single( o => o.PropertyName == "DateOfBirth" ); ModelValidationNode validationNode = new ModelValidationNode(propertyMetadata, "foo"); ComplexModelDtoResult dtoResult = new ComplexModelDtoResult( null /* model */ , validationNode ); ModelValidator requiredValidator = context .GetValidators(propertyMetadata) .Where(v => v.IsRequired) .FirstOrDefault(); TestableMutableObjectModelBinder testableBinder = new TestableMutableObjectModelBinder(); // Act testableBinder.SetPropertyPublic( context, bindingContext, propertyMetadata, dtoResult, requiredValidator ); // Assert Assert.True(context.ModelState.IsValid); validationNode.Validate(context, bindingContext.ValidationNode); Assert.False(context.ModelState.IsValid); }
protected override void SetProperty(HttpActionContext actionContext, ModelBindingContext bindingContext, ModelMetadata propertyMetadata, ComplexModelDtoResult dtoResult, ModelValidator requiredValidator) { SetPropertyPublic(actionContext, bindingContext, propertyMetadata, dtoResult, requiredValidator); }
public virtual void SetPropertyPublic(HttpActionContext context, ModelBindingContext bindingContext, ModelMetadata propertyMetadata, ComplexModelDtoResult dtoResult, ModelValidator requiredValidator) { base.SetProperty(context, bindingContext, propertyMetadata, dtoResult, requiredValidator); }
public void SetProperty_SettingNonNullableValueTypeToNull_RequiredValidatorPresent_AddsModelError() { // Arrange HttpActionContext context = ContextUtil.CreateActionContext(); ModelBindingContext bindingContext = new ModelBindingContext { ModelMetadata = GetMetadataForObject(new Person()), ModelName = "foo" }; ModelMetadata propertyMetadata = bindingContext.ModelMetadata.Properties.Single(o => o.PropertyName == "ValueTypeRequired"); ModelValidationNode validationNode = new ModelValidationNode(propertyMetadata, "foo.ValueTypeRequired"); ComplexModelDtoResult dtoResult = new ComplexModelDtoResult(null /* model */, validationNode); ModelValidator requiredValidator = context.GetValidators(propertyMetadata).Where(v => v.IsRequired).FirstOrDefault(); TestableMutableObjectModelBinder testableBinder = new TestableMutableObjectModelBinder(); // Act testableBinder.SetPropertyPublic(context, bindingContext, propertyMetadata, dtoResult, requiredValidator); // Assert Assert.False(bindingContext.ModelState.IsValid); Assert.Equal("Sample message", bindingContext.ModelState["foo.ValueTypeRequired"].Errors[0].ErrorMessage); }
public void SetProperty_SettingNonNullableValueTypeToNull_RequiredValidatorNotPresent_RegistersValidationCallback() { // Arrange HttpActionContext context = ContextUtil.CreateActionContext(); ModelBindingContext bindingContext = new ModelBindingContext { ModelMetadata = GetMetadataForObject(new Person()), }; ModelMetadata propertyMetadata = bindingContext.ModelMetadata.Properties.Single(o => o.PropertyName == "DateOfBirth"); ModelValidationNode validationNode = new ModelValidationNode(propertyMetadata, "foo"); ComplexModelDtoResult dtoResult = new ComplexModelDtoResult(null /* model */, validationNode); ModelValidator requiredValidator = context.GetValidators(propertyMetadata).Where(v => v.IsRequired).FirstOrDefault(); TestableMutableObjectModelBinder testableBinder = new TestableMutableObjectModelBinder(); // Act testableBinder.SetPropertyPublic(context, bindingContext, propertyMetadata, dtoResult, requiredValidator); // Assert Assert.True(context.ModelState.IsValid); validationNode.Validate(context, bindingContext.ValidationNode); Assert.False(context.ModelState.IsValid); }
public void SetProperty_PropertyIsSettable_SetterThrows_RecordsError() { // Arrange Person model = new Person { DateOfBirth = new DateTime(1900, 1, 1) }; ModelBindingContext bindingContext = new ModelBindingContext { ModelMetadata = GetMetadataForObject(model) }; ModelMetadata propertyMetadata = bindingContext.ModelMetadata.Properties.Single(o => o.PropertyName == "DateOfDeath"); ModelValidationNode validationNode = new ModelValidationNode(propertyMetadata, "foo"); ComplexModelDtoResult dtoResult = new ComplexModelDtoResult(new DateTime(1800, 1, 1), validationNode); TestableMutableObjectModelBinder testableBinder = new TestableMutableObjectModelBinder(); // Act testableBinder.SetPropertyPublic(null, bindingContext, propertyMetadata, dtoResult, requiredValidator: null); // Assert Assert.Equal("Date of death can't be before date of birth." + Environment.NewLine + "Parameter name: value", bindingContext.ModelState["foo"].Errors[0].Exception.Message); }
public void SetProperty_PropertyIsReadOnly_DoesNothing() { // Arrange ModelBindingContext bindingContext = new ModelBindingContext { ModelMetadata = GetMetadataForType(typeof(Person)) }; ModelMetadata propertyMetadata = bindingContext.ModelMetadata.Properties.Single(o => o.PropertyName == "NonUpdateableProperty"); ModelValidationNode validationNode = new ModelValidationNode(propertyMetadata, "foo"); ComplexModelDtoResult dtoResult = new ComplexModelDtoResult(null /* model */, validationNode); TestableMutableObjectModelBinder testableBinder = new TestableMutableObjectModelBinder(); // Act testableBinder.SetPropertyPublic(null, bindingContext, propertyMetadata, dtoResult, requiredValidator: null); // Assert // If didn't throw, success! }
public void SetProperty_PropertyHasDefaultValue_SetsDefaultValue() { // Arrange HttpActionContext context = ContextUtil.CreateActionContext(); ModelBindingContext bindingContext = new ModelBindingContext { ModelMetadata = GetMetadataForObject(new Person()) }; ModelMetadata propertyMetadata = bindingContext.ModelMetadata.Properties.Single(o => o.PropertyName == "PropertyWithDefaultValue"); ModelValidationNode validationNode = new ModelValidationNode(propertyMetadata, "foo"); ComplexModelDtoResult dtoResult = new ComplexModelDtoResult(null /* model */, validationNode); ModelValidator requiredValidator = context.GetValidators(propertyMetadata).Where(v => v.IsRequired).FirstOrDefault(); TestableMutableObjectModelBinder testableBinder = new TestableMutableObjectModelBinder(); // Act testableBinder.SetPropertyPublic(context, bindingContext, propertyMetadata, dtoResult, requiredValidator); // Assert var person = Assert.IsType<Person>(bindingContext.Model); Assert.Equal(123.456m, person.PropertyWithDefaultValue); Assert.True(context.ModelState.IsValid); }
protected virtual void SetProperty(HttpActionContext actionContext, ModelBindingContext bindingContext, ModelMetadata propertyMetadata, ComplexModelDtoResult dtoResult, ModelValidator requiredValidator) { PropertyDescriptor propertyDescriptor = TypeDescriptorHelper.Get(bindingContext.ModelType).GetProperties().Find(propertyMetadata.PropertyName, true /* ignoreCase */); if (propertyDescriptor == null || propertyDescriptor.IsReadOnly) { return; // nothing to do } object value = dtoResult.Model ?? GetPropertyDefaultValue(propertyDescriptor); propertyMetadata.Model = value; // 'Required' validators need to run first so that we can provide useful error messages if // the property setters throw, e.g. if we're setting entity keys to null. See comments in // DefaultModelBinder.SetProperty() for more information. if (value == null) { string modelStateKey = dtoResult.ValidationNode.ModelStateKey; if (bindingContext.ModelState.IsValidField(modelStateKey)) { if (requiredValidator != null) { foreach (ModelValidationResult validationResult in requiredValidator.Validate(propertyMetadata, bindingContext.Model)) { bindingContext.ModelState.AddModelError(modelStateKey, validationResult.Message); } } } } if (value != null || TypeHelper.TypeAllowsNullValue(propertyDescriptor.PropertyType)) { try { propertyDescriptor.SetValue(bindingContext.Model, value); } catch (Exception ex) { // don't display a duplicate error message if a binding error has already occurred for this field string modelStateKey = dtoResult.ValidationNode.ModelStateKey; if (bindingContext.ModelState.IsValidField(modelStateKey)) { bindingContext.ModelState.AddModelError(modelStateKey, ex); } } } else { // trying to set a non-nullable value type to null, need to make sure there's a message string modelStateKey = dtoResult.ValidationNode.ModelStateKey; if (bindingContext.ModelState.IsValidField(modelStateKey)) { dtoResult.ValidationNode.Validated += CreateNullCheckFailedHandler(propertyMetadata, value); } } }
public void BindModel() { // Arrange MyModel model = new MyModel(); ModelMetadata modelMetadata = new EmptyModelMetadataProvider().GetMetadataForType(() => model, typeof(MyModel)); ComplexModelDto dto = new ComplexModelDto(modelMetadata, modelMetadata.Properties); Mock <IModelBinder> mockStringBinder = new Mock <IModelBinder>(); Mock <IModelBinder> mockIntBinder = new Mock <IModelBinder>(); Mock <IModelBinder> mockDateTimeBinder = new Mock <IModelBinder>(); HttpActionContext context = ContextUtil.CreateActionContext(); context.ControllerContext.Configuration.Services.ReplaceRange(typeof(ModelBinderProvider), new ModelBinderProvider[] { new SimpleModelBinderProvider(typeof(string), mockStringBinder.Object) { SuppressPrefixCheck = true }, new SimpleModelBinderProvider(typeof(int), mockIntBinder.Object) { SuppressPrefixCheck = true }, new SimpleModelBinderProvider(typeof(DateTime), mockDateTimeBinder.Object) { SuppressPrefixCheck = true } }); mockStringBinder .Setup(b => b.BindModel(context, It.IsAny <ModelBindingContext>())) .Returns((HttpActionContext ec, ModelBindingContext mbc) => { Assert.Equal(typeof(string), mbc.ModelType); Assert.Equal("theModel.StringProperty", mbc.ModelName); mbc.ValidationNode = new ModelValidationNode(mbc.ModelMetadata, "theModel.StringProperty"); mbc.Model = "someStringValue"; return(true); }); mockIntBinder .Setup(b => b.BindModel(context, It.IsAny <ModelBindingContext>())) .Returns((HttpActionContext ec, ModelBindingContext mbc) => { Assert.Equal(typeof(int), mbc.ModelType); Assert.Equal("theModel.IntProperty", mbc.ModelName); mbc.ValidationNode = new ModelValidationNode(mbc.ModelMetadata, "theModel.IntProperty"); mbc.Model = 42; return(true); }); mockDateTimeBinder .Setup(b => b.BindModel(context, It.IsAny <ModelBindingContext>())) .Returns((HttpActionContext ec, ModelBindingContext mbc) => { Assert.Equal(typeof(DateTime), mbc.ModelType); Assert.Equal("theModel.DateTimeProperty", mbc.ModelName); return(false); }); ModelBindingContext parentBindingContext = new ModelBindingContext { ModelMetadata = new EmptyModelMetadataProvider().GetMetadataForType(() => dto, typeof(ComplexModelDto)), ModelName = "theModel", }; ComplexModelDtoModelBinder binder = new ComplexModelDtoModelBinder(); // Act bool retVal = binder.BindModel(context, parentBindingContext); // Assert Assert.True(retVal); Assert.Equal(dto, parentBindingContext.Model); ComplexModelDtoResult stringDtoResult = dto.Results[dto.PropertyMetadata.Where(m => m.ModelType == typeof(string)).First()]; Assert.Equal("someStringValue", stringDtoResult.Model); Assert.Equal("theModel.StringProperty", stringDtoResult.ValidationNode.ModelStateKey); ComplexModelDtoResult intDtoResult = dto.Results[dto.PropertyMetadata.Where(m => m.ModelType == typeof(int)).First()]; Assert.Equal(42, intDtoResult.Model); Assert.Equal("theModel.IntProperty", intDtoResult.ValidationNode.ModelStateKey); // Bind failed, so DateTime won't even be in the DTO dictionary bool containsMissingKey = dto.Results.ContainsKey(dto.PropertyMetadata.Where(m => m.ModelType == typeof(DateTime)).First()); Assert.False(containsMissingKey); }
protected virtual void SetProperty(HttpActionContext actionContext, ModelBindingContext bindingContext, ModelMetadata propertyMetadata, ComplexModelDtoResult dtoResult, ModelValidator requiredValidator) { PropertyDescriptor propertyDescriptor = TypeDescriptorHelper.Get(bindingContext.ModelType).GetProperties().Find(propertyMetadata.PropertyName, true /* ignoreCase */); if (propertyDescriptor == null || propertyDescriptor.IsReadOnly) { return; // nothing to do } object value = dtoResult.Model ?? GetPropertyDefaultValue(propertyDescriptor); propertyMetadata.Model = value; // 'Required' validators need to run first so that we can provide useful error messages if // the property setters throw, e.g. if we're setting entity keys to null. See comments in // DefaultModelBinder.SetProperty() for more information. if (value == null) { string modelStateKey = dtoResult.ValidationNode.ModelStateKey; if (bindingContext.ModelState.IsValidField(modelStateKey)) { RunValidator(requiredValidator, bindingContext, propertyMetadata, modelStateKey); } } if (value != null || TypeHelper.TypeAllowsNullValue(propertyDescriptor.PropertyType)) { try { propertyDescriptor.SetValue(bindingContext.Model, value); } catch (Exception ex) { // don't display a duplicate error message if a binding error has already occurred for this field string modelStateKey = dtoResult.ValidationNode.ModelStateKey; if (bindingContext.ModelState.IsValidField(modelStateKey)) { bindingContext.ModelState.AddModelError(modelStateKey, ex); } } } else { // trying to set a non-nullable value type to null, need to make sure there's a message string modelStateKey = dtoResult.ValidationNode.ModelStateKey; if (bindingContext.ModelState.IsValidField(modelStateKey)) { dtoResult.ValidationNode.Validated += CreateNullCheckFailedHandler(propertyMetadata, value); } } }