public void ProcessResults_ValueTypeProperty_TriesToSetNullModel_CapturesException() { // Arrange var model = new Person(); var containerMetadata = GetMetadataForType(model.GetType()); var bindingContext = CreateContext(containerMetadata, model); var modelStateDictionary = bindingContext.ModelState; var results = containerMetadata.Properties.ToDictionary( property => property, property => new ModelBindingResult(model: null, key: property.PropertyName, isModelSet: false)); var testableBinder = new TestableMutableObjectModelBinder(); // The [DefaultValue] on ValueTypeRequiredWithDefaultValue is ignored by model binding. var expectedValue = 0; // Make ValueTypeRequired invalid. var propertyMetadata = containerMetadata.Properties[nameof(Person.ValueTypeRequired)]; results[propertyMetadata] = new ModelBindingResult( model: null, isModelSet: true, key: "theModel." + nameof(Person.ValueTypeRequired)); // Make ValueTypeRequiredWithDefaultValue invalid propertyMetadata = containerMetadata.Properties[nameof(Person.ValueTypeRequiredWithDefaultValue)]; results[propertyMetadata] = new ModelBindingResult( model: null, isModelSet: true, key: "theModel." + nameof(Person.ValueTypeRequiredWithDefaultValue)); var modelValidationNode = new ModelValidationNode(string.Empty, containerMetadata, model); // Act testableBinder.ProcessResults(bindingContext, results, modelValidationNode); // Assert Assert.False(modelStateDictionary.IsValid); // Check ValueTypeRequired error. var modelStateEntry = Assert.Single( modelStateDictionary, entry => entry.Key == "theModel." + nameof(Person.ValueTypeRequired)); Assert.Equal("theModel." + nameof(Person.ValueTypeRequired), modelStateEntry.Key); var modelState = modelStateEntry.Value; Assert.Equal(ModelValidationState.Invalid, modelState.ValidationState); var error = Assert.Single(modelState.Errors); Assert.Equal(string.Empty, error.ErrorMessage); Assert.IsType<NullReferenceException>(error.Exception); // Check ValueTypeRequiredWithDefaultValue error. modelStateEntry = Assert.Single( modelStateDictionary, entry => entry.Key == "theModel." + nameof(Person.ValueTypeRequiredWithDefaultValue)); Assert.Equal("theModel." + nameof(Person.ValueTypeRequiredWithDefaultValue), modelStateEntry.Key); modelState = modelStateEntry.Value; Assert.Equal(ModelValidationState.Invalid, modelState.ValidationState); error = Assert.Single(modelState.Errors); Assert.Equal(string.Empty, error.ErrorMessage); Assert.IsType<NullReferenceException>(error.Exception); Assert.Equal(0, model.ValueTypeRequired); Assert.Equal(expectedValue, model.ValueTypeRequiredWithDefaultValue); }
public void ProcessResults_ValueTypePropertyWithBindRequired_SetToNull_CapturesException() { // Arrange var model = new ModelWithBindRequired { Name = "original value", Age = -20 }; var containerMetadata = GetMetadataForType(model.GetType()); var bindingContext = new ModelBindingContext() { Model = model, ModelMetadata = containerMetadata, ModelName = "theModel", ModelState = new ModelStateDictionary(), OperationBindingContext = new OperationBindingContext { MetadataProvider = TestModelMetadataProvider.CreateDefaultProvider(), ValidatorProvider = Mock.Of<IModelValidatorProvider>() } }; var results = containerMetadata.Properties.ToDictionary( property => property, property => new ModelBindingResult(model: null, key: property.PropertyName, isModelSet: false)); var propertyMetadata = containerMetadata.Properties[nameof(model.Name)]; results[propertyMetadata] = new ModelBindingResult("John Doe", isModelSet: true, key: "theModel.Name"); // Attempt to set non-Nullable property to null. BindRequiredAttribute should not be relevant in this // case because the binding exists. propertyMetadata = containerMetadata.Properties[nameof(model.Age)]; results[propertyMetadata] = new ModelBindingResult(model: null, isModelSet: true, key: "theModel.Age"); var testableBinder = new TestableMutableObjectModelBinder(); var modelValidationNode = new ModelValidationNode(string.Empty, containerMetadata, model); // Act testableBinder.ProcessResults(bindingContext, results, modelValidationNode); // Assert var modelStateDictionary = bindingContext.ModelState; Assert.False(modelStateDictionary.IsValid); Assert.Equal(1, modelStateDictionary.Count); // Check Age error. ModelState modelState; Assert.True(modelStateDictionary.TryGetValue("theModel.Age", out modelState)); Assert.Equal(ModelValidationState.Invalid, modelState.ValidationState); var modelError = Assert.Single(modelState.Errors); Assert.Equal(string.Empty, modelError.ErrorMessage); Assert.IsType<NullReferenceException>(modelError.Exception); }
public void ProcessResults_NullableValueTypeProperty_NoValueSet_NoError() { // Arrange var model = new NullableValueTypeProperty(); var containerMetadata = GetMetadataForType(model.GetType()); var bindingContext = CreateContext(containerMetadata, model); var results = containerMetadata.Properties.ToDictionary( property => property, property => new ModelBindingResult(model: null, key: property.PropertyName, isModelSet: false)); var testableBinder = new TestableMutableObjectModelBinder(); var modelValidationNode = new ModelValidationNode(string.Empty, containerMetadata, model); // Act testableBinder.ProcessResults(bindingContext, results, modelValidationNode); // Assert var modelStateDictionary = bindingContext.ModelState; Assert.True(modelStateDictionary.IsValid); }
public void ProcessResults_Success() { // Arrange var dob = new DateTime(2001, 1, 1); var model = new PersonWithBindExclusion { DateOfBirth = dob }; var containerMetadata = GetMetadataForType(model.GetType()); var bindingContext = CreateContext(containerMetadata, model); var results = containerMetadata.Properties.ToDictionary( property => property, property => new ModelBindingResult(model: null, key: property.PropertyName, isModelSet: false)); var firstNameProperty = containerMetadata.Properties[nameof(model.FirstName)]; results[firstNameProperty] = new ModelBindingResult( model: "John", isModelSet: true, key: nameof(model.FirstName)); var lastNameProperty = containerMetadata.Properties[nameof(model.LastName)]; results[lastNameProperty] = new ModelBindingResult( model: "Doe", isModelSet: true, key: nameof(model.LastName)); var modelValidationNode = new ModelValidationNode(string.Empty, containerMetadata, model); var testableBinder = new TestableMutableObjectModelBinder(); // Act testableBinder.ProcessResults(bindingContext, results, modelValidationNode); // Assert Assert.Equal("John", model.FirstName); Assert.Equal("Doe", model.LastName); Assert.Equal(dob, model.DateOfBirth); Assert.True(bindingContext.ModelState.IsValid); // Ensure that we add child nodes for all the nodes which have a result (irrespective of if they // are bound or not). Assert.Equal(5, modelValidationNode.ChildNodes.Count); Assert.Collection(modelValidationNode.ChildNodes, child => { Assert.Equal(nameof(model.DateOfBirth), child.Key); Assert.Equal(null, child.Model); }, child => { Assert.Equal(nameof(model.DateOfDeath), child.Key); Assert.Equal(null, child.Model); }, child => { Assert.Equal(nameof(model.FirstName), child.Key); Assert.Equal("John", child.Model); }, child => { Assert.Equal(nameof(model.LastName), child.Key); Assert.Equal("Doe", child.Model); }, child => { Assert.Equal(nameof(model.NonUpdateableProperty), child.Key); Assert.Equal(null, child.Model); }); }
public void ProcessResults_DataMemberIsRequiredFieldMissing_RaisesModelError() { // Arrange var model = new ModelWithDataMemberIsRequired { Name = "original value", Age = -20 }; var containerMetadata = GetMetadataForType(model.GetType()); var bindingContext = new ModelBindingContext { Model = model, ModelMetadata = containerMetadata, ModelName = "theModel", OperationBindingContext = new OperationBindingContext { MetadataProvider = TestModelMetadataProvider.CreateDefaultProvider(), ValidatorProvider = Mock.Of<IModelValidatorProvider>() } }; var results = containerMetadata.Properties.ToDictionary( property => property, property => new ModelBindingResult(model: null, key: property.PropertyName, isModelSet: false)); var nameProperty = containerMetadata.Properties[nameof(model.Name)]; results[nameProperty] = new ModelBindingResult("John Doe", isModelSet: true, key: string.Empty); var modelValidationNode = new ModelValidationNode(string.Empty, containerMetadata, model); var testableBinder = new TestableMutableObjectModelBinder(); // Act testableBinder.ProcessResults(bindingContext, results, modelValidationNode); // Assert var modelStateDictionary = bindingContext.ModelState; Assert.False(modelStateDictionary.IsValid); Assert.Single(modelStateDictionary); // Check Age error. ModelState modelState; Assert.True(modelStateDictionary.TryGetValue("theModel.Age", out modelState)); var modelError = Assert.Single(modelState.Errors); Assert.Null(modelError.Exception); Assert.NotNull(modelError.ErrorMessage); Assert.Equal("A value for the 'Age' property was not provided.", modelError.ErrorMessage); }
public void ProcessResults_ReferenceTypePropertyWithBindRequired_RequiredValidatorIgnored() { // Arrange var model = new ModelWithBindRequiredAndRequiredAttribute(); var containerMetadata = GetMetadataForType(model.GetType()); var bindingContext = CreateContext(containerMetadata, model); var modelStateDictionary = bindingContext.ModelState; var results = containerMetadata.Properties.ToDictionary( property => property, property => new ModelBindingResult(model: null, key: property.PropertyName, isModelSet: false)); var testableBinder = new TestableMutableObjectModelBinder(); // Make ValueTypeProperty have a value. var propertyMetadata = containerMetadata .Properties[nameof(ModelWithBindRequiredAndRequiredAttribute.ValueTypeProperty)]; results[propertyMetadata] = new ModelBindingResult( model: 17, isModelSet: true, key: "theModel." + nameof(ModelWithBindRequiredAndRequiredAttribute.ValueTypeProperty)); // Make ReferenceTypeProperty not have a value. propertyMetadata = containerMetadata .Properties[nameof(ModelWithBindRequiredAndRequiredAttribute.ReferenceTypeProperty)]; results[propertyMetadata] = new ModelBindingResult( model: null, isModelSet: false, key: "theModel." + nameof(ModelWithBindRequiredAndRequiredAttribute.ReferenceTypeProperty)); var modelValidationNode = new ModelValidationNode(string.Empty, containerMetadata, model); // Act testableBinder.ProcessResults(bindingContext, results, modelValidationNode); // Assert Assert.False(modelStateDictionary.IsValid); var entry = Assert.Single( modelStateDictionary, kvp => kvp.Key == "theModel." + nameof(ModelWithBindRequiredAndRequiredAttribute.ReferenceTypeProperty)) .Value; var error = Assert.Single(entry.Errors); Assert.Null(error.Exception); Assert.Equal("A value for the 'ReferenceTypeProperty' property was not provided.", error.ErrorMessage); // Model gets provided values. Assert.Equal(17, model.ValueTypeProperty); Assert.Null(model.ReferenceTypeProperty); }
public void ProcessResults_ProvideRequiredFields_Success() { // Arrange var model = new Person(); var containerMetadata = GetMetadataForType(model.GetType()); var bindingContext = CreateContext(containerMetadata, model); var modelStateDictionary = bindingContext.ModelState; var results = containerMetadata.Properties.ToDictionary( property => property, property => new ModelBindingResult(model: null, key: property.PropertyName, isModelSet: false)); var testableBinder = new TestableMutableObjectModelBinder(); // Make ValueTypeRequired valid. var propertyMetadata = containerMetadata.Properties[nameof(Person.ValueTypeRequired)]; results[propertyMetadata] = new ModelBindingResult( model: 41, isModelSet: true, key: "theModel." + nameof(Person.ValueTypeRequired)); // Make ValueTypeRequiredWithDefaultValue valid. propertyMetadata = containerMetadata.Properties[nameof(Person.ValueTypeRequiredWithDefaultValue)]; results[propertyMetadata] = new ModelBindingResult( model: 57, isModelSet: true, key: "theModel." + nameof(Person.ValueTypeRequiredWithDefaultValue)); // Also remind ProcessResults about PropertyWithDefaultValue -- as BindPropertiesAsync() would. propertyMetadata = containerMetadata.Properties[nameof(Person.PropertyWithDefaultValue)]; results[propertyMetadata] = new ModelBindingResult( model: null, isModelSet: false, key: "theModel." + nameof(Person.PropertyWithDefaultValue)); var modelValidationNode = new ModelValidationNode(string.Empty, containerMetadata, model); // Act testableBinder.ProcessResults(bindingContext, results, modelValidationNode); // Assert Assert.True(modelStateDictionary.IsValid); Assert.Empty(modelStateDictionary); // Model gets provided values. Assert.Equal(41, model.ValueTypeRequired); Assert.Equal(57, model.ValueTypeRequiredWithDefaultValue); Assert.Equal(0m, model.PropertyWithDefaultValue); // [DefaultValue] has no effect }
public void ProcessResults_ValueTypeProperty_NoValue_NoError() { // Arrange var model = new Person(); var containerMetadata = GetMetadataForType(model.GetType()); var bindingContext = CreateContext(containerMetadata, model); var modelState = bindingContext.ModelState; var results = containerMetadata.Properties.ToDictionary( property => property, property => new ModelBindingResult(model: null, key: property.PropertyName, isModelSet: false)); var testableBinder = new TestableMutableObjectModelBinder(); // Make ValueTypeRequired invalid. var propertyMetadata = containerMetadata.Properties[nameof(Person.ValueTypeRequired)]; results[propertyMetadata] = new ModelBindingResult( model: null, isModelSet: false, key: "theModel." + nameof(Person.ValueTypeRequired)); // Make ValueTypeRequiredWithDefaultValue invalid propertyMetadata = containerMetadata.Properties[nameof(Person.ValueTypeRequiredWithDefaultValue)]; results[propertyMetadata] = new ModelBindingResult( model: null, isModelSet: false, key: "theModel." + nameof(Person.ValueTypeRequiredWithDefaultValue)); var modelValidationNode = new ModelValidationNode(string.Empty, containerMetadata, model); // Act testableBinder.ProcessResults(bindingContext, results, modelValidationNode); // Assert Assert.True(modelState.IsValid); }
public void ProcessResults_ValueTypeProperty_WithBindingOptional_NoValueSet_NoError() { // Arrange var model = new BindingOptionalProperty(); var containerMetadata = GetMetadataForType(model.GetType()); var bindingContext = CreateContext(containerMetadata, model); var results = containerMetadata.Properties.ToDictionary( property => property, property => ModelBindingResult.Failed(property.PropertyName)); var testableBinder = new TestableMutableObjectModelBinder(); // Act testableBinder.ProcessResults(bindingContext, results); // Assert var modelStateDictionary = bindingContext.ModelState; Assert.True(modelStateDictionary.IsValid); }
public void ProcessResults_Success() { // Arrange var dob = new DateTime(2001, 1, 1); var model = new PersonWithBindExclusion { DateOfBirth = dob }; var containerMetadata = GetMetadataForType(model.GetType()); var bindingContext = CreateContext(containerMetadata, model); var results = containerMetadata.Properties.ToDictionary( property => property, property => ModelBindingResult.Failed(property.PropertyName)); var firstNameProperty = containerMetadata.Properties[nameof(model.FirstName)]; results[firstNameProperty] = ModelBindingResult.Success( nameof(model.FirstName), "John"); var lastNameProperty = containerMetadata.Properties[nameof(model.LastName)]; results[lastNameProperty] = ModelBindingResult.Success( nameof(model.LastName), "Doe"); var testableBinder = new TestableMutableObjectModelBinder(); // Act testableBinder.ProcessResults(bindingContext, results); // Assert Assert.Equal("John", model.FirstName); Assert.Equal("Doe", model.LastName); Assert.Equal(dob, model.DateOfBirth); Assert.True(bindingContext.ModelState.IsValid); }