public void ProcessDto_RequiredFieldMissing_RaisesModelErrorWithMessage() { // Arrange var model = new Person(); var containerMetadata = GetMetadataForObject(model); var bindingContext = CreateContext(containerMetadata); // Set no properties though ValueTypeRequired (a non-Nullable struct) property is required. var dto = new ComplexModelDto(containerMetadata, containerMetadata.Properties); var testableBinder = new TestableMutableObjectModelBinder(); // Act testableBinder.ProcessDto(bindingContext, dto); // Assert var modelStateDictionary = bindingContext.ModelState; Assert.Equal(false, modelStateDictionary.IsValid); Assert.Equal(1, modelStateDictionary.Count); // Check ValueTypeRequired error. ModelState modelState; Assert.True(modelStateDictionary.TryGetValue("theModel.ValueTypeRequired", out modelState)); Assert.Equal(1, modelState.Errors.Count); var modelError = modelState.Errors[0]; Assert.Null(modelError.Exception); Assert.NotNull(modelError.ErrorMessage); Assert.Equal("Sample message", modelError.ErrorMessage); }
public void ProcessDto_Success() { // Arrange var dob = new DateTime(2001, 1, 1); var model = new PersonWithBindExclusion { DateOfBirth = dob }; var containerMetadata = GetMetadataForObject(model); var bindingContext = CreateContext(containerMetadata); var dto = new ComplexModelDto(containerMetadata, containerMetadata.Properties); var firstNameProperty = dto.PropertyMetadata.Single(o => o.PropertyName == "FirstName"); dto.Results[firstNameProperty] = new ComplexModelDtoResult("John", new ModelValidationNode(firstNameProperty, "")); var lastNameProperty = dto.PropertyMetadata.Single(o => o.PropertyName == "LastName"); dto.Results[lastNameProperty] = new ComplexModelDtoResult("Doe", new ModelValidationNode(lastNameProperty, "")); var dobProperty = dto.PropertyMetadata.Single(o => o.PropertyName == "DateOfBirth"); dto.Results[dobProperty] = null; var testableBinder = new TestableMutableObjectModelBinder(); // Act testableBinder.ProcessDto(bindingContext, dto); // Assert Assert.Equal("John", model.FirstName); Assert.Equal("Doe", model.LastName); Assert.Equal(dob, model.DateOfBirth); Assert.Equal(true, bindingContext.ModelState.IsValid); }
public void ProcessDto_BindRequiredFieldMissing_RaisesModelError() { // Arrange ModelWithBindRequired model = new ModelWithBindRequired { Name = "original value", Age = -20 }; ModelMetadata containerMetadata = GetMetadataForObject(model); HttpActionContext context = ContextUtil.CreateActionContext(); ModelBindingContext bindingContext = new ModelBindingContext { ModelMetadata = containerMetadata, ModelName = "theModel" }; ComplexModelDto dto = new ComplexModelDto(containerMetadata, containerMetadata.Properties); ModelMetadata nameProperty = dto.PropertyMetadata.Single(o => o.PropertyName == "Name"); dto.Results[nameProperty] = new ComplexModelDtoResult("John Doe", new ModelValidationNode(nameProperty, "")); TestableMutableObjectModelBinder testableBinder = new TestableMutableObjectModelBinder(); // Act & assert testableBinder.ProcessDto(context, bindingContext, dto); Assert.False(bindingContext.ModelState.IsValid); }
public void ProcessDto_BindRequiredFieldMissing_Throws() { // Arrange ModelWithBindRequired model = new ModelWithBindRequired { Name = "original value", Age = -20 }; ModelMetadata containerMetadata = GetMetadataForObject(model); ControllerContext controllerContext = new ControllerContext(); ExtensibleModelBindingContext bindingContext = new ExtensibleModelBindingContext { ModelMetadata = containerMetadata, ModelName = "theModel" }; ComplexModelDto dto = new ComplexModelDto(containerMetadata, containerMetadata.Properties); ModelMetadata nameProperty = dto.PropertyMetadata.Single(o => o.PropertyName == "Name"); dto.Results[nameProperty] = new ComplexModelDtoResult("John Doe", new ModelValidationNode(nameProperty, "")); TestableMutableObjectModelBinder testableBinder = new TestableMutableObjectModelBinder(); // Act & assert Assert.Throws <InvalidOperationException>( delegate { testableBinder.ProcessDto(controllerContext, bindingContext, dto); }, @"A value for 'theModel.Age' is required but was not present in the request."); Assert.Equal("original value", model.Name); Assert.Equal(-20, model.Age); }
public void ProcessDto_RequiredFieldNull_RaisesModelError() { // Arrange ModelWithRequired model = new ModelWithRequired(); ModelMetadata containerMetadata = GetMetadataForObject(model); HttpActionContext context = ContextUtil.CreateActionContext(); ModelBindingContext bindingContext = new ModelBindingContext { ModelMetadata = containerMetadata, ModelName = "theModel" }; ComplexModelDto dto = new ComplexModelDto( containerMetadata, containerMetadata.Properties ); TestableMutableObjectModelBinder testableBinder = new TestableMutableObjectModelBinder(); // Make Age valid and City invalid. ModelMetadata propertyMetadata = dto.PropertyMetadata.Single( p => p.PropertyName == "Age" ); dto.Results[propertyMetadata] = new ComplexModelDtoResult( 23, new ModelValidationNode(propertyMetadata, "theModel.Age") ); propertyMetadata = dto.PropertyMetadata.Single(p => p.PropertyName == "City"); dto.Results[propertyMetadata] = new ComplexModelDtoResult( null, new ModelValidationNode(propertyMetadata, "theModel.City") ); // Act testableBinder.ProcessDto(context, bindingContext, dto); // Assert ModelStateDictionary modelStateDictionary = bindingContext.ModelState; Assert.False(modelStateDictionary.IsValid); Assert.Single(modelStateDictionary); // Check City error. ModelState modelState; Assert.True(modelStateDictionary.TryGetValue("theModel.City", out modelState)); ModelError modelError = Assert.Single(modelState.Errors); Assert.Null(modelError.Exception); Assert.NotNull(modelError.ErrorMessage); Assert.Equal("The City field is required.", modelError.ErrorMessage); }
public void ProcessDto_BindRequiredFieldNull_RaisesModelError() { // Arrange ModelWithBindRequired model = new ModelWithBindRequired { Name = "original value", Age = -20 }; ModelMetadata containerMetadata = GetMetadataForObject(model); HttpActionContext context = ContextUtil.CreateActionContext(); ModelBindingContext bindingContext = new ModelBindingContext() { ModelMetadata = containerMetadata, ModelName = "theModel", ModelState = context.ModelState, }; ComplexModelDto dto = new ComplexModelDto(containerMetadata, containerMetadata.Properties); TestableMutableObjectModelBinder testableBinder = new TestableMutableObjectModelBinder(); ModelMetadata propertyMetadata = dto.PropertyMetadata.Single(o => o.PropertyName == "Name"); dto.Results[propertyMetadata] = new ComplexModelDtoResult("John Doe", new ModelValidationNode(propertyMetadata, "theModel.Name")); // Attempt to set non-Nullable property to null. HttpBindRequiredAttribute should not be relevant in this // case because the binding exists. propertyMetadata = dto.PropertyMetadata.Single(o => o.PropertyName == "Age"); dto.Results[propertyMetadata] = new ComplexModelDtoResult(null, new ModelValidationNode(propertyMetadata, "theModel.Age")); // Act; must also Validate because null-check error handler is late-bound testableBinder.ProcessDto(context, bindingContext, dto); bindingContext.ValidationNode.Validate(context); // Assert ModelStateDictionary 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(1, modelState.Errors.Count); ModelError modelError = modelState.Errors[0]; Assert.Null(modelError.Exception); Assert.NotNull(modelError.ErrorMessage); Assert.Equal("A value is required.", modelError.ErrorMessage); }
public void ProcessDto_Success() { // Arrange DateTime dob = new DateTime(2001, 1, 1); Person model = new Person { DateOfBirth = dob }; ModelMetadata containerMetadata = GetMetadataForObject(model); ControllerContext controllerContext = new ControllerContext(); ExtensibleModelBindingContext bindingContext = new ExtensibleModelBindingContext { ModelMetadata = containerMetadata }; ComplexModelDto dto = new ComplexModelDto( containerMetadata, containerMetadata.Properties ); ModelMetadata firstNameProperty = dto.PropertyMetadata.Single( o => o.PropertyName == "FirstName" ); dto.Results[firstNameProperty] = new ComplexModelDtoResult( "John", new ModelValidationNode(firstNameProperty, "") ); ModelMetadata lastNameProperty = dto.PropertyMetadata.Single( o => o.PropertyName == "LastName" ); dto.Results[lastNameProperty] = new ComplexModelDtoResult( "Doe", new ModelValidationNode(lastNameProperty, "") ); ModelMetadata dobProperty = dto.PropertyMetadata.Single( o => o.PropertyName == "DateOfBirth" ); dto.Results[dobProperty] = null; TestableMutableObjectModelBinder testableBinder = new TestableMutableObjectModelBinder(); // Act testableBinder.ProcessDto(controllerContext, bindingContext, dto); // Assert Assert.Equal("John", model.FirstName); Assert.Equal("Doe", model.LastName); Assert.Equal(dob, model.DateOfBirth); Assert.True(bindingContext.ModelState.IsValid); }
public void ProcessDto_BindRequiredFieldMissing_RaisesModelError() { // Arrange ModelWithBindRequired model = new ModelWithBindRequired { Name = "original value", Age = -20 }; ModelMetadata containerMetadata = GetMetadataForObject(model); HttpActionContext context = ContextUtil.CreateActionContext(); ModelBindingContext bindingContext = new ModelBindingContext { ModelMetadata = containerMetadata, ModelName = "theModel" }; ComplexModelDto dto = new ComplexModelDto( containerMetadata, containerMetadata.Properties ); ModelMetadata nameProperty = dto.PropertyMetadata.Single(o => o.PropertyName == "Name"); dto.Results[nameProperty] = new ComplexModelDtoResult( "John Doe", new ModelValidationNode(nameProperty, "") ); TestableMutableObjectModelBinder testableBinder = new TestableMutableObjectModelBinder(); // Act testableBinder.ProcessDto(context, bindingContext, dto); // Assert ModelStateDictionary modelStateDictionary = bindingContext.ModelState; Assert.False(modelStateDictionary.IsValid); Assert.Single(modelStateDictionary); // Check Age error. ModelState modelState; Assert.True(modelStateDictionary.TryGetValue("theModel.Age", out modelState)); ModelError modelError = Assert.Single(modelState.Errors); Assert.Null(modelError.Exception); Assert.NotNull(modelError.ErrorMessage); Assert.Equal("The Age property is required.", modelError.ErrorMessage); }
public void ProcessDto_RequiredFieldMissing_RaisesModelError() { // Arrange ModelWithRequired model = new ModelWithRequired(); ModelMetadata containerMetadata = GetMetadataForObject(model); HttpActionContext context = ContextUtil.CreateActionContext(); ModelBindingContext bindingContext = new ModelBindingContext { ModelMetadata = containerMetadata, ModelName = "theModel" }; // Set no properties though Age (a non-Nullable struct) and City (a class) properties are required. ComplexModelDto dto = new ComplexModelDto( containerMetadata, containerMetadata.Properties ); TestableMutableObjectModelBinder testableBinder = new TestableMutableObjectModelBinder(); // Act testableBinder.ProcessDto(context, bindingContext, dto); // Assert ModelStateDictionary modelStateDictionary = bindingContext.ModelState; Assert.False(modelStateDictionary.IsValid); Assert.Equal(2, modelStateDictionary.Count); // Check Age error. ModelState modelState; Assert.True(modelStateDictionary.TryGetValue("theModel.Age", out modelState)); ModelError modelError = Assert.Single(modelState.Errors); Assert.Null(modelError.Exception); Assert.NotNull(modelError.ErrorMessage); Assert.Equal("The Age field is required.", modelError.ErrorMessage); // Check City error. Assert.True(modelStateDictionary.TryGetValue("theModel.City", out modelState)); modelError = Assert.Single(modelState.Errors); Assert.Null(modelError.Exception); Assert.NotNull(modelError.ErrorMessage); Assert.Equal("The City field is required.", modelError.ErrorMessage); }
public void ProcessDto_BindRequiredFieldMissing_RaisesModelError() { // Arrange var model = new ModelWithBindRequired { Name = "original value", Age = -20 }; var containerMetadata = GetMetadataForObject(model); var bindingContext = new ModelBindingContext { ModelMetadata = containerMetadata, ModelName = "theModel", ValidatorProvider = Mock.Of <IModelValidatorProvider>() }; var dto = new ComplexModelDto(containerMetadata, containerMetadata.Properties); var nameProperty = dto.PropertyMetadata.Single(o => o.PropertyName == "Name"); dto.Results[nameProperty] = new ComplexModelDtoResult("John Doe", new ModelValidationNode(nameProperty, "")); var testableBinder = new TestableMutableObjectModelBinder(); // Act testableBinder.ProcessDto(bindingContext, dto); // Assert var modelStateDictionary = bindingContext.ModelState; Assert.Equal(false, modelStateDictionary.IsValid); Assert.Equal(1, modelStateDictionary.Count); // Check Age error. ModelState modelState; Assert.True(modelStateDictionary.TryGetValue("theModel.Age", out modelState)); Assert.Equal(1, modelState.Errors.Count); var modelError = modelState.Errors[0]; Assert.Null(modelError.Exception); Assert.NotNull(modelError.ErrorMessage); Assert.Equal("The 'Age' property is required.", modelError.ErrorMessage); }
public void ProcessDto_RequiredFieldMissing_RaisesModelError() { // Arrange var model = new ModelWithRequired(); var containerMetadata = GetMetadataForObject(model); var bindingContext = CreateContext(containerMetadata); // Set no properties though Age (a non-Nullable struct) and City (a class) properties are required. var dto = new ComplexModelDto(containerMetadata, containerMetadata.Properties); var testableBinder = new TestableMutableObjectModelBinder(); // Act testableBinder.ProcessDto(bindingContext, dto); // Assert var modelStateDictionary = bindingContext.ModelState; Assert.Equal(false, modelStateDictionary.IsValid); Assert.Equal(2, modelStateDictionary.Count); // Check Age error. ModelState modelState; Assert.True(modelStateDictionary.TryGetValue("theModel.Age", out modelState)); Assert.Equal(1, modelState.Errors.Count); var modelError = modelState.Errors[0]; Assert.Null(modelError.Exception); Assert.NotNull(modelError.ErrorMessage); var expected = ValidationAttributeUtil.GetRequiredErrorMessage(nameof(ModelWithRequired.Age)); Assert.Equal(expected, modelError.ErrorMessage); // Check City error. Assert.True(modelStateDictionary.TryGetValue("theModel.City", out modelState)); Assert.Equal(1, modelState.Errors.Count); modelError = modelState.Errors[0]; Assert.Null(modelError.Exception); Assert.NotNull(modelError.ErrorMessage); expected = ValidationAttributeUtil.GetRequiredErrorMessage(nameof(ModelWithRequired.City)); Assert.Equal(expected, modelError.ErrorMessage); }
public void ProcessDto_RequiredFieldMissing_RaisesModelErrorWithMessage() { // Arrange Person model = new Person(); ModelMetadata containerMetadata = GetMetadataForObject(model); HttpActionContext context = ContextUtil.CreateActionContext(); ModelBindingContext bindingContext = new ModelBindingContext { ModelMetadata = containerMetadata, ModelName = "theModel" }; // Set no properties though ValueTypeRequired (a non-Nullable struct) property is required. ComplexModelDto dto = new ComplexModelDto( containerMetadata, containerMetadata.Properties ); TestableMutableObjectModelBinder testableBinder = new TestableMutableObjectModelBinder(); // Act testableBinder.ProcessDto(context, bindingContext, dto); // Assert ModelStateDictionary modelStateDictionary = bindingContext.ModelState; Assert.False(modelStateDictionary.IsValid); Assert.Single(modelStateDictionary); // Check ValueTypeRequired error. ModelState modelState; Assert.True( modelStateDictionary.TryGetValue("theModel.ValueTypeRequired", out modelState) ); ModelError modelError = Assert.Single(modelState.Errors); Assert.Null(modelError.Exception); Assert.NotNull(modelError.ErrorMessage); Assert.Equal("Sample message", modelError.ErrorMessage); }
public void ProcessDto_RequiredFieldNull_RaisesModelErrorWithMessage() { // Arrange Person model = new Person(); ModelMetadata containerMetadata = GetMetadataForObject(model); HttpActionContext context = ContextUtil.CreateActionContext(); ModelBindingContext bindingContext = new ModelBindingContext { ModelMetadata = containerMetadata, ModelName = "theModel" }; ComplexModelDto dto = new ComplexModelDto(containerMetadata, containerMetadata.Properties); TestableMutableObjectModelBinder testableBinder = new TestableMutableObjectModelBinder(); // Make ValueTypeRequired invalid. ModelMetadata propertyMetadata = dto.PropertyMetadata.Single(p => p.PropertyName == "ValueTypeRequired"); dto.Results[propertyMetadata] = new ComplexModelDtoResult(null, new ModelValidationNode(propertyMetadata, "theModel.ValueTypeRequired")); // Act testableBinder.ProcessDto(context, bindingContext, dto); // Assert ModelStateDictionary modelStateDictionary = bindingContext.ModelState; Assert.False(modelStateDictionary.IsValid); Assert.Equal(1, modelStateDictionary.Count); // Check ValueTypeRequired error. ModelState modelState; Assert.True(modelStateDictionary.TryGetValue("theModel.ValueTypeRequired", out modelState)); Assert.Equal(1, modelState.Errors.Count); ModelError modelError = modelState.Errors[0]; Assert.Null(modelError.Exception); Assert.NotNull(modelError.ErrorMessage); Assert.Equal("Sample message", modelError.ErrorMessage); }
public void ProcessDto_RequiredFieldNull_RaisesModelError() { // Arrange var model = new ModelWithRequired(); var containerMetadata = GetMetadataForObject(model); var bindingContext = CreateContext(containerMetadata); var dto = new ComplexModelDto(containerMetadata, containerMetadata.Properties); var testableBinder = new TestableMutableObjectModelBinder(); // Make Age valid and City invalid. var propertyMetadata = dto.PropertyMetadata.Single(p => p.PropertyName == "Age"); dto.Results[propertyMetadata] = new ComplexModelDtoResult(23, new ModelValidationNode(propertyMetadata, "theModel.Age")); propertyMetadata = dto.PropertyMetadata.Single(p => p.PropertyName == "City"); dto.Results[propertyMetadata] = new ComplexModelDtoResult(null, new ModelValidationNode(propertyMetadata, "theModel.City")); // Act testableBinder.ProcessDto(bindingContext, dto); // Assert var modelStateDictionary = bindingContext.ModelState; Assert.Equal(false, modelStateDictionary.IsValid); Assert.Equal(1, modelStateDictionary.Count); // Check City error. ModelState modelState; Assert.True(modelStateDictionary.TryGetValue("theModel.City", out modelState)); Assert.Equal(1, modelState.Errors.Count); var modelError = modelState.Errors[0]; Assert.Null(modelError.Exception); Assert.NotNull(modelError.ErrorMessage); var expected = ValidationAttributeUtil.GetRequiredErrorMessage(nameof(ModelWithRequired.City)); Assert.Equal(expected, modelError.ErrorMessage); }
public void ProcessDto_ProvideRequiredFields_Success() { // Arrange var model = new Person(); var containerMetadata = GetMetadataForType(model.GetType()); var bindingContext = CreateContext(containerMetadata, model); var modelStateDictionary = bindingContext.ModelState; var dto = new ComplexModelDto(containerMetadata, containerMetadata.Properties); var testableBinder = new TestableMutableObjectModelBinder(); // Make ValueTypeRequired valid. var propertyMetadata = dto.PropertyMetadata .Single(p => p.PropertyName == nameof(Person.ValueTypeRequired)); dto.Results[propertyMetadata] = new ModelBindingResult( 41, isModelSet: true, key: "theModel." + nameof(Person.ValueTypeRequired)); // Make ValueTypeRequiredWithDefaultValue valid. propertyMetadata = dto.PropertyMetadata .Single(p => p.PropertyName == nameof(Person.ValueTypeRequiredWithDefaultValue)); dto.Results[propertyMetadata] = new ModelBindingResult( model: 57, isModelSet: true, key: "theModel." + nameof(Person.ValueTypeRequiredWithDefaultValue)); // Also remind ProcessDto about PropertyWithDefaultValue -- as ComplexModelDtoModelBinder would. propertyMetadata = dto.PropertyMetadata .Single(p => p.PropertyName == nameof(Person.PropertyWithDefaultValue)); dto.Results[propertyMetadata] = new ModelBindingResult( model: null, isModelSet: false, key: "theModel." + nameof(Person.PropertyWithDefaultValue)); var modelValidationNode = new ModelValidationNode(string.Empty, containerMetadata, model); // Act testableBinder.ProcessDto(bindingContext, dto, 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 ProcessDto_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 dto = new ComplexModelDto(containerMetadata, containerMetadata.Properties); var testableBinder = new TestableMutableObjectModelBinder(); var propertyMetadata = dto.PropertyMetadata.Single(o => o.PropertyName == "Name"); dto.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 = dto.PropertyMetadata.Single(o => o.PropertyName == "Age"); dto.Results[propertyMetadata] = new ModelBindingResult( null, isModelSet: true, key: "theModel.Age"); var modelValidationNode = new ModelValidationNode(string.Empty, containerMetadata, model); // Act testableBinder.ProcessDto(bindingContext, dto, 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 ProcessDto_RequiredFieldMissing_RaisesModelError() { // Arrange ModelWithRequired model = new ModelWithRequired(); ModelMetadata containerMetadata = GetMetadataForObject(model); HttpActionContext context = ContextUtil.CreateActionContext(); ModelBindingContext bindingContext = new ModelBindingContext { ModelMetadata = containerMetadata, ModelName = "theModel" }; // Set no properties though Age (a non-Nullable struct) and City (a class) properties are required. ComplexModelDto dto = new ComplexModelDto(containerMetadata, containerMetadata.Properties); TestableMutableObjectModelBinder testableBinder = new TestableMutableObjectModelBinder(); // Act testableBinder.ProcessDto(context, bindingContext, dto); // Assert ModelStateDictionary modelStateDictionary = bindingContext.ModelState; Assert.False(modelStateDictionary.IsValid); Assert.Equal(2, modelStateDictionary.Count); // Check Age error. ModelState modelState; Assert.True(modelStateDictionary.TryGetValue("theModel.Age", out modelState)); Assert.Equal(1, modelState.Errors.Count); ModelError modelError = modelState.Errors[0]; Assert.Null(modelError.Exception); Assert.NotNull(modelError.ErrorMessage); Assert.Equal("The Age field is required.", modelError.ErrorMessage); // Check City error. Assert.True(modelStateDictionary.TryGetValue("theModel.City", out modelState)); Assert.Equal(1, modelState.Errors.Count); modelError = modelState.Errors[0]; Assert.Null(modelError.Exception); Assert.NotNull(modelError.ErrorMessage); Assert.Equal("The City field is required.", modelError.ErrorMessage); }
public void ProcessDto_BindRequiredFieldMissing_RaisesModelError() { // Arrange ModelWithBindRequired model = new ModelWithBindRequired { Name = "original value", Age = -20 }; ModelMetadata containerMetadata = GetMetadataForObject(model); HttpActionContext context = ContextUtil.CreateActionContext(); ModelBindingContext bindingContext = new ModelBindingContext { ModelMetadata = containerMetadata, ModelName = "theModel" }; ComplexModelDto dto = new ComplexModelDto(containerMetadata, containerMetadata.Properties); ModelMetadata nameProperty = dto.PropertyMetadata.Single(o => o.PropertyName == "Name"); dto.Results[nameProperty] = new ComplexModelDtoResult("John Doe", new ModelValidationNode(nameProperty, "")); TestableMutableObjectModelBinder testableBinder = new TestableMutableObjectModelBinder(); // Act testableBinder.ProcessDto(context, bindingContext, dto); // Assert ModelStateDictionary 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(1, modelState.Errors.Count); ModelError modelError = modelState.Errors[0]; Assert.Null(modelError.Exception); Assert.NotNull(modelError.ErrorMessage); Assert.Equal("The Age property is required.", modelError.ErrorMessage); }
public void ProcessDto_RequiredFieldNull_RaisesModelError() { // Arrange var model = new ModelWithRequired(); var containerMetadata = GetMetadataForType(model.GetType()); var bindingContext = CreateContext(containerMetadata, model); var dto = new ComplexModelDto(containerMetadata, containerMetadata.Properties); var testableBinder = new TestableMutableObjectModelBinder(); // Make Age valid and City invalid. var propertyMetadata = dto.PropertyMetadata.Single(p => p.PropertyName == "Age"); dto.Results[propertyMetadata] = new ModelBindingResult( 23, isModelSet: true, key: "theModel.Age"); propertyMetadata = dto.PropertyMetadata.Single(p => p.PropertyName == "City"); dto.Results[propertyMetadata] = new ModelBindingResult( null, isModelSet: true, key: "theModel.City"); // Act testableBinder.ProcessDto(bindingContext, dto); // Assert var modelStateDictionary = bindingContext.ModelState; Assert.False(modelStateDictionary.IsValid); Assert.Single(modelStateDictionary); // Check City error. ModelState modelState; Assert.True(modelStateDictionary.TryGetValue("theModel." + nameof(ModelWithRequired.City), out modelState)); var modelError = Assert.Single(modelState.Errors); Assert.Null(modelError.Exception); Assert.NotNull(modelError.ErrorMessage); var expected = ValidationAttributeUtil.GetRequiredErrorMessage(nameof(ModelWithRequired.City)); Assert.Equal(expected, modelError.ErrorMessage); }
public void ProcessDto_BindRequiredFieldMissing_RaisesModelError() { // Arrange ModelWithBindRequired model = new ModelWithBindRequired { Name = "original value", Age = -20 }; ModelMetadata containerMetadata = GetMetadataForObject(model); HttpActionContext context = ContextUtil.CreateActionContext(); ModelBindingContext bindingContext = new ModelBindingContext { ModelMetadata = containerMetadata, ModelName = "theModel" }; ComplexModelDto dto = new ComplexModelDto(containerMetadata, containerMetadata.Properties); ModelMetadata nameProperty = dto.PropertyMetadata.Single(o => o.PropertyName == "Name"); dto.Results[nameProperty] = new ComplexModelDtoResult("John Doe", new ModelValidationNode(nameProperty, "")); TestableMutableObjectModelBinder testableBinder = new TestableMutableObjectModelBinder(); // Act & assert testableBinder.ProcessDto(context, bindingContext, dto); Assert.False(bindingContext.ModelState.IsValid); }
public void ProcessDto_RequiredFieldMissing_RaisesModelErrorWithMessage() { // Arrange var model = new Person(); var containerMetadata = GetMetadataForType(model.GetType()); var bindingContext = CreateContext(containerMetadata, model); // Set no properties though ValueTypeRequired (a non-Nullable struct) property is required. var dto = new ComplexModelDto(containerMetadata, containerMetadata.Properties); var testableBinder = new TestableMutableObjectModelBinder(); // Act testableBinder.ProcessDto(bindingContext, dto); // Assert var modelStateDictionary = bindingContext.ModelState; Assert.False(modelStateDictionary.IsValid); Assert.Equal(2, modelStateDictionary.Count); // 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 modelError = Assert.Single(modelState.Errors); Assert.Null(modelError.Exception); Assert.NotNull(modelError.ErrorMessage); Assert.Equal("Sample message", modelError.ErrorMessage); // 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); modelError = Assert.Single(modelState.Errors); Assert.Null(modelError.Exception); Assert.NotNull(modelError.ErrorMessage); Assert.Equal("Another sample message", modelError.ErrorMessage); }
public void ProcessDto_RequiredFieldNull_RaisesModelErrorWithMessage() { // Arrange Person model = new Person(); ModelMetadata containerMetadata = GetMetadataForObject(model); HttpActionContext context = ContextUtil.CreateActionContext(); ModelBindingContext bindingContext = new ModelBindingContext { ModelMetadata = containerMetadata, ModelName = "theModel" }; ComplexModelDto dto = new ComplexModelDto(containerMetadata, containerMetadata.Properties); TestableMutableObjectModelBinder testableBinder = new TestableMutableObjectModelBinder(); // Make ValueTypeRequired invalid. ModelMetadata propertyMetadata = dto.PropertyMetadata.Single(p => p.PropertyName == "ValueTypeRequired"); dto.Results[propertyMetadata] = new ComplexModelDtoResult(null, new ModelValidationNode(propertyMetadata, "theModel.ValueTypeRequired")); // Act testableBinder.ProcessDto(context, bindingContext, dto); // Assert ModelStateDictionary modelStateDictionary = bindingContext.ModelState; Assert.False(modelStateDictionary.IsValid); Assert.Equal(1, modelStateDictionary.Count); // Check ValueTypeRequired error. ModelState modelState; Assert.True(modelStateDictionary.TryGetValue("theModel.ValueTypeRequired", out modelState)); Assert.Equal(1, modelState.Errors.Count); ModelError modelError = modelState.Errors[0]; Assert.Null(modelError.Exception); Assert.NotNull(modelError.ErrorMessage); Assert.Equal("Sample message", modelError.ErrorMessage); }
public void ProcessDto_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 dto = new ComplexModelDto(containerMetadata, containerMetadata.Properties); var firstNameProperty = dto.PropertyMetadata.Single(o => o.PropertyName == "FirstName"); dto.Results[firstNameProperty] = new ModelBindingResult( "John", isModelSet: true, key: ""); var lastNameProperty = dto.PropertyMetadata.Single(o => o.PropertyName == "LastName"); dto.Results[lastNameProperty] = new ModelBindingResult( "Doe", isModelSet: true, key: ""); var dobProperty = dto.PropertyMetadata.Single(o => o.PropertyName == "DateOfBirth"); dto.Results[dobProperty] = null; var modelValidationNode = new ModelValidationNode(string.Empty, containerMetadata, model); var testableBinder = new TestableMutableObjectModelBinder(); // Act testableBinder.ProcessDto(bindingContext, dto, 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(2, modelValidationNode.ChildNodes.Count()); var validationNode = modelValidationNode.ChildNodes[0]; Assert.Equal("", validationNode.Key); Assert.Equal("John", validationNode.Model); validationNode = modelValidationNode.ChildNodes[1]; Assert.Equal("", validationNode.Key); Assert.Equal("Doe", validationNode.Model); }
public void ProcessDto_ValueTypeProperty_TriesToSetNullModel_CapturesException() { // Arrange var model = new Person(); var containerMetadata = GetMetadataForType(model.GetType()); var bindingContext = CreateContext(containerMetadata, model); var modelStateDictionary = bindingContext.ModelState; var dto = new ComplexModelDto(containerMetadata, containerMetadata.Properties); var testableBinder = new TestableMutableObjectModelBinder(); // The [DefaultValue] on ValueTypeRequiredWithDefaultValue is ignored by model binding. var expectedValue = 0; // Make ValueTypeRequired invalid. var propertyMetadata = dto.PropertyMetadata.Single(p => p.PropertyName == nameof(Person.ValueTypeRequired)); dto.Results[propertyMetadata] = new ModelBindingResult( null, isModelSet: true, key: "theModel." + nameof(Person.ValueTypeRequired)); // Make ValueTypeRequiredWithDefaultValue invalid propertyMetadata = dto.PropertyMetadata .Single(p => p.PropertyName == nameof(Person.ValueTypeRequiredWithDefaultValue)); dto.Results[propertyMetadata] = new ModelBindingResult( model: null, isModelSet: true, key: "theModel." + nameof(Person.ValueTypeRequiredWithDefaultValue)); var modelValidationNode = new ModelValidationNode(string.Empty, containerMetadata, model); // Act testableBinder.ProcessDto(bindingContext, dto, 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 ProcessDto_PropertyWithRequiredAttribute_NoPropertiesSet_NoError() { // Arrange var model = new Person(); var containerMetadata = GetMetadataForType(model.GetType()); var bindingContext = CreateContext(containerMetadata, model); // Set no properties though ValueTypeRequired (a non-Nullable struct) property is required. var dto = new ComplexModelDto(containerMetadata, containerMetadata.Properties); var testableBinder = new TestableMutableObjectModelBinder(); var modelValidationNode = new ModelValidationNode(string.Empty, containerMetadata, model); // Act testableBinder.ProcessDto(bindingContext, dto, modelValidationNode); // Assert var modelStateDictionary = bindingContext.ModelState; Assert.True(modelStateDictionary.IsValid); }
public void ProcessDto_ValueTypeProperty_WithRequiredAttribute_SetToNull_NoError() { // Arrange var model = new ModelWithRequired(); var containerMetadata = GetMetadataForType(model.GetType()); var bindingContext = CreateContext(containerMetadata, model); var dto = new ComplexModelDto(containerMetadata, containerMetadata.Properties); var testableBinder = new TestableMutableObjectModelBinder(); // Make Age valid and City invalid. var propertyMetadata = dto.PropertyMetadata.Single(p => p.PropertyName == "Age"); dto.Results[propertyMetadata] = new ModelBindingResult( 23, isModelSet: true, key: "theModel.Age"); propertyMetadata = dto.PropertyMetadata.Single(p => p.PropertyName == "City"); dto.Results[propertyMetadata] = new ModelBindingResult( null, isModelSet: true, key: "theModel.City"); var modelValidationNode = new ModelValidationNode(string.Empty, containerMetadata, model); // Act testableBinder.ProcessDto(bindingContext, dto, modelValidationNode); // Assert var modelStateDictionary = bindingContext.ModelState; Assert.True(modelStateDictionary.IsValid); Assert.Empty(modelStateDictionary); }
public void ProcessDto_MissingDataForRequiredFields_NoErrors() { // Arrange var model = new ModelWithRequired(); var containerMetadata = GetMetadataForType(model.GetType()); var bindingContext = CreateContext(containerMetadata, model); // Set no properties though Age (a non-Nullable struct) and City (a class) properties are required. var dto = new ComplexModelDto(containerMetadata, containerMetadata.Properties); var testableBinder = new TestableMutableObjectModelBinder(); var modelValidationNode = new ModelValidationNode(string.Empty, containerMetadata, model); // Act testableBinder.ProcessDto(bindingContext, dto, modelValidationNode); // Assert var modelStateDictionary = bindingContext.ModelState; Assert.True(modelStateDictionary.IsValid); Assert.Empty(modelStateDictionary); }
public void ProcessDto_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 dto = new ComplexModelDto(containerMetadata, containerMetadata.Properties); var firstNameProperty = dto.PropertyMetadata.Single(o => o.PropertyName == "FirstName"); dto.Results[firstNameProperty] = new ModelBindingResult( "John", isModelSet: true, key: ""); var lastNameProperty = dto.PropertyMetadata.Single(o => o.PropertyName == "LastName"); dto.Results[lastNameProperty] = new ModelBindingResult( "Doe", isModelSet: true, key: ""); var dobProperty = dto.PropertyMetadata.Single(o => o.PropertyName == "DateOfBirth"); dto.Results[dobProperty] = null; var testableBinder = new TestableMutableObjectModelBinder(); // Act testableBinder.ProcessDto(bindingContext, dto); // Assert Assert.Equal("John", model.FirstName); Assert.Equal("Doe", model.LastName); Assert.Equal(dob, model.DateOfBirth); Assert.True(bindingContext.ModelState.IsValid); }
public void ProcessDto_ValueTypeProperty_NoValue_NoError() { // Arrange var model = new Person(); var containerMetadata = GetMetadataForType(model.GetType()); var bindingContext = CreateContext(containerMetadata, model); var modelStateDictionary = bindingContext.ModelState; var dto = new ComplexModelDto(containerMetadata, containerMetadata.Properties); var testableBinder = new TestableMutableObjectModelBinder(); // Make ValueTypeRequired invalid. var propertyMetadata = dto.PropertyMetadata.Single(p => p.PropertyName == nameof(Person.ValueTypeRequired)); dto.Results[propertyMetadata] = new ModelBindingResult( null, isModelSet: false, key: "theModel." + nameof(Person.ValueTypeRequired)); // Make ValueTypeRequiredWithDefaultValue invalid propertyMetadata = dto.PropertyMetadata .Single(p => p.PropertyName == nameof(Person.ValueTypeRequiredWithDefaultValue)); dto.Results[propertyMetadata] = new ModelBindingResult( model: null, isModelSet: false, key: "theModel." + nameof(Person.ValueTypeRequiredWithDefaultValue)); var modelValidationNode = new ModelValidationNode(string.Empty, containerMetadata, model); // Act testableBinder.ProcessDto(bindingContext, dto, modelValidationNode); // Assert Assert.True(modelStateDictionary.IsValid); Assert.Empty(modelStateDictionary); }
public void ProcessDto_BindRequiredFieldMissing_RaisesModelError() { // Arrange var model = new ModelWithBindRequired { Name = "original value", Age = -20 }; var containerMetadata = GetMetadataForObject(model); var bindingContext = new ModelBindingContext { ModelMetadata = containerMetadata, ModelName = "theModel", ValidatorProviders = Enumerable.Empty<IModelValidatorProvider>() }; var dto = new ComplexModelDto(containerMetadata, containerMetadata.Properties); var nameProperty = dto.PropertyMetadata.Single(o => o.PropertyName == "Name"); dto.Results[nameProperty] = new ComplexModelDtoResult("John Doe", new ModelValidationNode(nameProperty, "")); var testableBinder = new TestableMutableObjectModelBinder(); // Act testableBinder.ProcessDto(bindingContext, dto); // Assert var modelStateDictionary = bindingContext.ModelState; Assert.Equal(false, modelStateDictionary.IsValid); Assert.Equal(1, modelStateDictionary.Count); // Check Age error. ModelState modelState; Assert.True(modelStateDictionary.TryGetValue("theModel.Age", out modelState)); Assert.Equal(1, modelState.Errors.Count); var modelError = modelState.Errors[0]; Assert.Null(modelError.Exception); Assert.NotNull(modelError.ErrorMessage); Assert.Equal("The 'Age' property is required.", modelError.ErrorMessage); }
public void ProcessDto_Success() { // Arrange DateTime dob = new DateTime(2001, 1, 1); Person model = new Person() { DateOfBirth = dob }; ModelMetadata containerMetadata = GetMetadataForObject(model); ControllerContext controllerContext = new ControllerContext(); ExtensibleModelBindingContext bindingContext = new ExtensibleModelBindingContext() { ModelMetadata = containerMetadata }; ComplexModelDto dto = new ComplexModelDto(containerMetadata, containerMetadata.Properties); ModelMetadata firstNameProperty = dto.PropertyMetadata.Single(o => o.PropertyName == "FirstName"); dto.Results[firstNameProperty] = new ComplexModelDtoResult("John", new ModelValidationNode(firstNameProperty, "")); ModelMetadata lastNameProperty = dto.PropertyMetadata.Single(o => o.PropertyName == "LastName"); dto.Results[lastNameProperty] = new ComplexModelDtoResult("Doe", new ModelValidationNode(lastNameProperty, "")); ModelMetadata dobProperty = dto.PropertyMetadata.Single(o => o.PropertyName == "DateOfBirth"); dto.Results[dobProperty] = null; TestableMutableObjectModelBinder testableBinder = new TestableMutableObjectModelBinder(); // Act testableBinder.ProcessDto(controllerContext, bindingContext, dto); // Assert Assert.AreEqual("John", model.FirstName); Assert.AreEqual("Doe", model.LastName); Assert.AreEqual(dob, model.DateOfBirth, "DateOfBirth shouldn't have been modified."); Assert.IsTrue(bindingContext.ModelState.IsValid); }
public void ProcessDto_BindRequiredFieldNull_RaisesModelError() { // Arrange var model = new ModelWithBindRequired { Name = "original value", Age = -20 }; var containerMetadata = GetMetadataForObject(model); var bindingContext = new ModelBindingContext() { ModelMetadata = containerMetadata, ModelName = "theModel", ModelState = new ModelStateDictionary(), ValidatorProviders = Enumerable.Empty<IModelValidatorProvider>() }; var validationContext = new ModelValidationContext(new EmptyModelMetadataProvider(), bindingContext.ValidatorProviders, bindingContext.ModelState, containerMetadata, null); var dto = new ComplexModelDto(containerMetadata, containerMetadata.Properties); var testableBinder = new TestableMutableObjectModelBinder(); var propertyMetadata = dto.PropertyMetadata.Single(o => o.PropertyName == "Name"); dto.Results[propertyMetadata] = new ComplexModelDtoResult("John Doe", new ModelValidationNode(propertyMetadata, "theModel.Name")); // Attempt to set non-Nullable property to null. BindRequiredAttribute should not be relevant in this // case because the binding exists. propertyMetadata = dto.PropertyMetadata.Single(o => o.PropertyName == "Age"); dto.Results[propertyMetadata] = new ComplexModelDtoResult(null, new ModelValidationNode(propertyMetadata, "theModel.Age")); // Act; must also Validate because null-check error handler is late-bound testableBinder.ProcessDto(bindingContext, dto); bindingContext.ValidationNode.Validate(validationContext); // Assert var modelStateDictionary = bindingContext.ModelState; Assert.Equal(false, modelStateDictionary.IsValid); Assert.Equal(2, modelStateDictionary.Count); // Check Name field ModelState modelState; Assert.True(modelStateDictionary.TryGetValue("theModel.Name", out modelState)); Assert.Equal(0, modelState.Errors.Count); Assert.Equal(ModelValidationState.Valid, modelState.ValidationState); // Check Age error. Assert.True(modelStateDictionary.TryGetValue("theModel.Age", out modelState)); Assert.Equal(1, modelState.Errors.Count); Assert.Equal(ModelValidationState.Invalid, modelState.ValidationState); var modelError = modelState.Errors[0]; Assert.Null(modelError.Exception); Assert.NotNull(modelError.ErrorMessage); Assert.Equal("A value is required.", modelError.ErrorMessage); }
public void ProcessDto_BindRequiredFieldMissing_Throws() { // Arrange ModelWithBindRequired model = new ModelWithBindRequired { Name = "original value", Age = -20 }; ModelMetadata containerMetadata = GetMetadataForObject(model); ControllerContext controllerContext = new ControllerContext(); ExtensibleModelBindingContext bindingContext = new ExtensibleModelBindingContext { ModelMetadata = containerMetadata, ModelName = "theModel" }; ComplexModelDto dto = new ComplexModelDto(containerMetadata, containerMetadata.Properties); ModelMetadata nameProperty = dto.PropertyMetadata.Single(o => o.PropertyName == "Name"); dto.Results[nameProperty] = new ComplexModelDtoResult("John Doe", new ModelValidationNode(nameProperty, "")); TestableMutableObjectModelBinder testableBinder = new TestableMutableObjectModelBinder(); // Act & assert Assert.Throws<InvalidOperationException>( delegate { testableBinder.ProcessDto(controllerContext, bindingContext, dto); }, @"A value for 'theModel.Age' is required but was not present in the request."); Assert.Equal("original value", model.Name); Assert.Equal(-20, model.Age); }
public void ProcessDto_RequiredFieldNull_RaisesModelError() { // Arrange var model = new ModelWithRequired(); var containerMetadata = GetMetadataForObject(model); var bindingContext = CreateContext(containerMetadata); var dto = new ComplexModelDto(containerMetadata, containerMetadata.Properties); var testableBinder = new TestableMutableObjectModelBinder(); // Make Age valid and City invalid. var propertyMetadata = dto.PropertyMetadata.Single(p => p.PropertyName == "Age"); dto.Results[propertyMetadata] = new ComplexModelDtoResult(23, new ModelValidationNode(propertyMetadata, "theModel.Age")); propertyMetadata = dto.PropertyMetadata.Single(p => p.PropertyName == "City"); dto.Results[propertyMetadata] = new ComplexModelDtoResult(null, new ModelValidationNode(propertyMetadata, "theModel.City")); // Act testableBinder.ProcessDto(bindingContext, dto); // Assert var modelStateDictionary = bindingContext.ModelState; Assert.Equal(false, modelStateDictionary.IsValid); Assert.Equal(1, modelStateDictionary.Count); // Check City error. ModelState modelState; Assert.True(modelStateDictionary.TryGetValue("theModel.City", out modelState)); Assert.Equal(1, modelState.Errors.Count); var modelError = modelState.Errors[0]; Assert.Null(modelError.Exception); Assert.NotNull(modelError.ErrorMessage); Assert.Equal("The City field is required.", modelError.ErrorMessage); }
public void ProcessDto_RequiredFieldMissing_RaisesModelError() { // Arrange var model = new ModelWithRequired(); var containerMetadata = GetMetadataForType(model.GetType()); var bindingContext = CreateContext(containerMetadata, model); // Set no properties though Age (a non-Nullable struct) and City (a class) properties are required. var dto = new ComplexModelDto(containerMetadata, containerMetadata.Properties); var testableBinder = new TestableMutableObjectModelBinder(); // Act testableBinder.ProcessDto(bindingContext, dto); // Assert var modelStateDictionary = bindingContext.ModelState; Assert.False(modelStateDictionary.IsValid); Assert.Equal(2, modelStateDictionary.Count); // Check Age error. ModelState modelState; Assert.True(modelStateDictionary.TryGetValue("theModel." + nameof(ModelWithRequired.Age), out modelState)); var modelError = Assert.Single(modelState.Errors); Assert.Null(modelError.Exception); Assert.NotNull(modelError.ErrorMessage); var expected = ValidationAttributeUtil.GetRequiredErrorMessage(nameof(ModelWithRequired.Age)); Assert.Equal(expected, modelError.ErrorMessage); // Check City error. Assert.True(modelStateDictionary.TryGetValue("theModel." + nameof(ModelWithRequired.City), out modelState)); modelError = Assert.Single(modelState.Errors); Assert.Null(modelError.Exception); Assert.NotNull(modelError.ErrorMessage); expected = ValidationAttributeUtil.GetRequiredErrorMessage(nameof(ModelWithRequired.City)); Assert.Equal(expected, modelError.ErrorMessage); }
public void ProcessDto_ReferenceTypePropertyWithBindRequired_RequiredValidatorIgnored() { // Arrange var model = new ModelWithBindRequiredAndRequiredAttribute(); var containerMetadata = GetMetadataForType(model.GetType()); var bindingContext = CreateContext(containerMetadata, model); var modelStateDictionary = bindingContext.ModelState; var dto = new ComplexModelDto(containerMetadata, containerMetadata.Properties); var testableBinder = new TestableMutableObjectModelBinder(); // Make ValueTypeProperty have a value. var propertyMetadata = containerMetadata .Properties[nameof(ModelWithBindRequiredAndRequiredAttribute.ValueTypeProperty)]; dto.Results[propertyMetadata] = new ModelBindingResult( 17, isModelSet: true, key: "theModel." + nameof(ModelWithBindRequiredAndRequiredAttribute.ValueTypeProperty)); // Make ReferenceTypeProperty not have a value. propertyMetadata = containerMetadata .Properties[nameof(ModelWithBindRequiredAndRequiredAttribute.ReferenceTypeProperty)]; dto.Results[propertyMetadata] = new ModelBindingResult( model: null, isModelSet: false, key: "theModel." + nameof(ModelWithBindRequiredAndRequiredAttribute.ReferenceTypeProperty)); var modelValidationNode = new ModelValidationNode(string.Empty, containerMetadata, model); // Act testableBinder.ProcessDto(bindingContext, dto, 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 ProcessDto_BindRequiredFieldNull_RaisesModelError() { // Arrange ModelWithBindRequired model = new ModelWithBindRequired { Name = "original value", Age = -20 }; ModelMetadata containerMetadata = GetMetadataForObject(model); HttpActionContext context = ContextUtil.CreateActionContext(); ModelBindingContext bindingContext = new ModelBindingContext() { ModelMetadata = containerMetadata, ModelName = "theModel", ModelState = context.ModelState, }; ComplexModelDto dto = new ComplexModelDto(containerMetadata, containerMetadata.Properties); TestableMutableObjectModelBinder testableBinder = new TestableMutableObjectModelBinder(); ModelMetadata propertyMetadata = dto.PropertyMetadata.Single(o => o.PropertyName == "Name"); dto.Results[propertyMetadata] = new ComplexModelDtoResult("John Doe", new ModelValidationNode(propertyMetadata, "theModel.Name")); // Attempt to set non-Nullable property to null. HttpBindRequiredAttribute should not be relevant in this // case because the binding exists. propertyMetadata = dto.PropertyMetadata.Single(o => o.PropertyName == "Age"); dto.Results[propertyMetadata] = new ComplexModelDtoResult(null, new ModelValidationNode(propertyMetadata, "theModel.Age")); // Act; must also Validate because null-check error handler is late-bound testableBinder.ProcessDto(context, bindingContext, dto); bindingContext.ValidationNode.Validate(context); // Assert ModelStateDictionary 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(1, modelState.Errors.Count); ModelError modelError = modelState.Errors[0]; Assert.Null(modelError.Exception); Assert.NotNull(modelError.ErrorMessage); Assert.Equal("A value is required.", modelError.ErrorMessage); }
public void ProcessDto_BindRequiredFieldNull_RaisesModelError() { // Arrange var model = new ModelWithBindRequired { Name = "original value", Age = -20 }; var containerMetadata = GetMetadataForObject(model); var bindingContext = new ModelBindingContext() { ModelMetadata = containerMetadata, ModelName = "theModel", ModelState = new ModelStateDictionary(), ValidatorProvider = Mock.Of <IModelValidatorProvider>() }; var validationContext = new ModelValidationContext(new EmptyModelMetadataProvider(), bindingContext.ValidatorProvider, bindingContext.ModelState, containerMetadata, null); var dto = new ComplexModelDto(containerMetadata, containerMetadata.Properties); var testableBinder = new TestableMutableObjectModelBinder(); var propertyMetadata = dto.PropertyMetadata.Single(o => o.PropertyName == "Name"); dto.Results[propertyMetadata] = new ComplexModelDtoResult("John Doe", new ModelValidationNode(propertyMetadata, "theModel.Name")); // Attempt to set non-Nullable property to null. BindRequiredAttribute should not be relevant in this // case because the binding exists. propertyMetadata = dto.PropertyMetadata.Single(o => o.PropertyName == "Age"); dto.Results[propertyMetadata] = new ComplexModelDtoResult(null, new ModelValidationNode(propertyMetadata, "theModel.Age")); // Act; must also Validate because null-check error handler is late-bound testableBinder.ProcessDto(bindingContext, dto); bindingContext.ValidationNode.Validate(validationContext); // Assert var modelStateDictionary = bindingContext.ModelState; Assert.Equal(false, modelStateDictionary.IsValid); Assert.Equal(2, modelStateDictionary.Count); // Check Name field ModelState modelState; Assert.True(modelStateDictionary.TryGetValue("theModel.Name", out modelState)); Assert.Equal(0, modelState.Errors.Count); Assert.Equal(ModelValidationState.Valid, modelState.ValidationState); // Check Age error. Assert.True(modelStateDictionary.TryGetValue("theModel.Age", out modelState)); Assert.Equal(1, modelState.Errors.Count); Assert.Equal(ModelValidationState.Invalid, modelState.ValidationState); var modelError = modelState.Errors[0]; Assert.Null(modelError.Exception); Assert.NotNull(modelError.ErrorMessage); Assert.Equal("A value is required.", modelError.ErrorMessage); }
public void ProcessDto_RequiredFieldMissing_RaisesModelErrorWithMessage() { // Arrange Person model = new Person(); ModelMetadata containerMetadata = GetMetadataForObject(model); HttpActionContext context = ContextUtil.CreateActionContext(); ModelBindingContext bindingContext = new ModelBindingContext { ModelMetadata = containerMetadata, ModelName = "theModel" }; // Set no properties though ValueTypeRequired (a non-Nullable struct) property is required. ComplexModelDto dto = new ComplexModelDto(containerMetadata, containerMetadata.Properties); TestableMutableObjectModelBinder testableBinder = new TestableMutableObjectModelBinder(); // Act testableBinder.ProcessDto(context, bindingContext, dto); // Assert ModelStateDictionary modelStateDictionary = bindingContext.ModelState; Assert.False(modelStateDictionary.IsValid); Assert.Equal(1, modelStateDictionary.Count); // Check ValueTypeRequired error. ModelState modelState; Assert.True(modelStateDictionary.TryGetValue("theModel.ValueTypeRequired", out modelState)); Assert.Equal(1, modelState.Errors.Count); ModelError modelError = modelState.Errors[0]; Assert.Null(modelError.Exception); Assert.NotNull(modelError.ErrorMessage); Assert.Equal("Sample message", modelError.ErrorMessage); }
public void ProcessDto_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 dto = new ComplexModelDto(containerMetadata, containerMetadata.Properties); var nameProperty = dto.PropertyMetadata.Single(o => o.PropertyName == "Name"); dto.Results[nameProperty] = new ModelBindingResult( "John Doe", isModelSet: true, key: ""); var modelValidationNode = new ModelValidationNode(string.Empty, containerMetadata, model); var testableBinder = new TestableMutableObjectModelBinder(); // Act testableBinder.ProcessDto(bindingContext, dto, 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 ProcessDto_Success() { // Arrange DateTime dob = new DateTime(2001, 1, 1); PersonWithBindExclusion model = new PersonWithBindExclusion { DateOfBirth = dob }; ModelMetadata containerMetadata = GetMetadataForObject(model); HttpActionContext context = ContextUtil.CreateActionContext(); ModelBindingContext bindingContext = new ModelBindingContext { ModelMetadata = containerMetadata }; ComplexModelDto dto = new ComplexModelDto(containerMetadata, containerMetadata.Properties); ModelMetadata firstNameProperty = dto.PropertyMetadata.Single(o => o.PropertyName == "FirstName"); dto.Results[firstNameProperty] = new ComplexModelDtoResult("John", new ModelValidationNode(firstNameProperty, "")); ModelMetadata lastNameProperty = dto.PropertyMetadata.Single(o => o.PropertyName == "LastName"); dto.Results[lastNameProperty] = new ComplexModelDtoResult("Doe", new ModelValidationNode(lastNameProperty, "")); ModelMetadata dobProperty = dto.PropertyMetadata.Single(o => o.PropertyName == "DateOfBirth"); dto.Results[dobProperty] = null; TestableMutableObjectModelBinder testableBinder = new TestableMutableObjectModelBinder(); // Act testableBinder.ProcessDto(context, bindingContext, dto); // Assert Assert.Equal("John", model.FirstName); Assert.Equal("Doe", model.LastName); Assert.Equal(dob, model.DateOfBirth); Assert.True(bindingContext.ModelState.IsValid); }
public void ProcessDto_RequiredFieldNull_RaisesModelErrorWithMessage(bool isModelSet) { // Arrange var model = new Person(); var containerMetadata = GetMetadataForType(model.GetType()); var bindingContext = CreateContext(containerMetadata, model); var modelStateDictionary = bindingContext.ModelState; var dto = new ComplexModelDto(containerMetadata, containerMetadata.Properties); var testableBinder = new TestableMutableObjectModelBinder(); // ValueTypeRequiredWithDefaultValue value comes from [DefaultValue] when !isModelSet. var expectedValue = isModelSet ? 0 : 42; // Make ValueTypeRequired invalid. var propertyMetadata = dto.PropertyMetadata.Single(p => p.PropertyName == nameof(Person.ValueTypeRequired)); dto.Results[propertyMetadata] = new ModelBindingResult( null, isModelSet: isModelSet, key: "theModel." + nameof(Person.ValueTypeRequired)); // Make ValueTypeRequiredWithDefaultValue invalid propertyMetadata = dto.PropertyMetadata .Single(p => p.PropertyName == nameof(Person.ValueTypeRequiredWithDefaultValue)); dto.Results[propertyMetadata] = new ModelBindingResult( model: null, isModelSet: isModelSet, key: "theModel." + nameof(Person.ValueTypeRequiredWithDefaultValue)); // Act testableBinder.ProcessDto(bindingContext, dto); // 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 modelError = Assert.Single(modelState.Errors); Assert.Null(modelError.Exception); Assert.NotNull(modelError.ErrorMessage); Assert.Equal("Sample message", modelError.ErrorMessage); // 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); modelError = Assert.Single(modelState.Errors); Assert.Null(modelError.Exception); Assert.NotNull(modelError.ErrorMessage); Assert.Equal("Another sample message", modelError.ErrorMessage); Assert.Equal(0, model.ValueTypeRequired); Assert.Equal(expectedValue, model.ValueTypeRequiredWithDefaultValue); }