public async Task CanCreateModel_ReturnsTrue_IfIsTopLevelObjectAndNotIsFirstChanceBinding( bool isTopLevelObject, bool isFirstChanceBinding, string binderModelName, string modelName, bool expectedCanCreate) { var mockValueProvider = new Mock<IValueProvider>(); mockValueProvider .Setup(o => o.ContainsPrefixAsync(It.IsAny<string>())) .Returns(Task.FromResult(false)); var metadataProvider = new TestModelMetadataProvider(); var bindingContext = new MutableObjectBinderContext { ModelBindingContext = new ModelBindingContext { IsTopLevelObject = isTopLevelObject, IsFirstChanceBinding = isFirstChanceBinding, // Random type. ModelMetadata = metadataProvider.GetMetadataForType(typeof(Person)), ValueProvider = mockValueProvider.Object, OperationBindingContext = new OperationBindingContext { ValueProvider = mockValueProvider.Object, MetadataProvider = metadataProvider, ValidatorProvider = Mock.Of<IModelValidatorProvider>(), }, // CanCreateModel() ignores the BinderModelName and ModelName properties. BinderModelName = binderModelName, ModelName = modelName, }, }; var mutableBinder = new TestableMutableObjectModelBinder(); bindingContext.PropertyMetadata = mutableBinder.GetMetadataForProperties(bindingContext.ModelBindingContext).ToArray(); // Act var canCreate = await mutableBinder.CanCreateModel(bindingContext); // Assert Assert.Equal(expectedCanCreate, canCreate); }
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 BindModel() { // Arrange ControllerContext controllerContext = new ControllerContext(); ExtensibleModelBindingContext bindingContext = new ExtensibleModelBindingContext { ModelBinderProviders = new ModelBinderProviderCollection(), ModelMetadata = GetMetadataForObject(new Person()), ModelName = "someName" }; Mock <IExtensibleModelBinder> mockDtoBinder = new Mock <IExtensibleModelBinder>(); mockDtoBinder .Setup(o => o.BindModel(controllerContext, It.IsAny <ExtensibleModelBindingContext>())) .Returns( delegate(ControllerContext cc, ExtensibleModelBindingContext mbc2) { return(true); // just return the DTO unchanged }); bindingContext.ModelBinderProviders.RegisterBinderForType(typeof(ComplexModelDto), mockDtoBinder.Object, true /* suppressPrefixCheck */); Mock <TestableMutableObjectModelBinder> mockTestableBinder = new Mock <TestableMutableObjectModelBinder> { CallBase = true }; mockTestableBinder.Setup(o => o.EnsureModelPublic(controllerContext, bindingContext)).Verifiable(); mockTestableBinder.Setup(o => o.GetMetadataForPropertiesPublic(controllerContext, bindingContext)).Returns(new ModelMetadata[0]).Verifiable(); TestableMutableObjectModelBinder testableBinder = mockTestableBinder.Object; testableBinder.MetadataProvider = new DataAnnotationsModelMetadataProvider(); // Act bool retValue = testableBinder.BindModel(controllerContext, bindingContext); // Assert Assert.True(retValue); Assert.IsType <Person>(bindingContext.Model); Assert.True(bindingContext.ValidationNode.ValidateAllProperties); mockTestableBinder.Verify(); }
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); 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 GetMetadataForProperties_WithoutBindAttribute() { // Arrange string[] expectedPropertyNames = new[] { "DateOfBirth", "DateOfDeath", "ValueTypeRequired", "FirstName", "LastName", "PropertyWithDefaultValue" }; HttpActionContext actionContext = ContextUtil.CreateActionContext(); ModelBindingContext bindingContext = new ModelBindingContext { ModelMetadata = GetMetadataForType(typeof(Person)) }; TestableMutableObjectModelBinder testableBinder = new TestableMutableObjectModelBinder(); // Act IEnumerable <ModelMetadata> propertyMetadatas = testableBinder.GetMetadataForPropertiesPublic(actionContext, bindingContext); string[] returnedPropertyNames = propertyMetadatas.Select(o => o.PropertyName).ToArray(); // Assert Assert.Equal(expectedPropertyNames, returnedPropertyNames); }
public void SetProperty_SettingNullableTypeToNull_RequiredValidatorPresent_PropertySetterThrows_AddsRequiredMessageString() { // Arrange var bindingContext = CreateContext(GetMetadataForObject(new ModelWhosePropertySetterThrows())); bindingContext.ModelName = "foo"; var propertyMetadata = bindingContext.ModelMetadata.Properties.Single(o => o.PropertyName == "Name"); var validationNode = new ModelValidationNode(propertyMetadata, "foo.Name"); var dtoResult = new ComplexModelDtoResult(model: null, validationNode: validationNode); var requiredValidator = GetRequiredValidator(bindingContext, propertyMetadata); var testableBinder = new TestableMutableObjectModelBinder(); // Act testableBinder.SetPropertyPublic(bindingContext, propertyMetadata, dtoResult, requiredValidator); // Assert Assert.Equal(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); }
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_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 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 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_PropertyHasDefaultValue_SetsDefaultValue() { // Arrange ControllerContext controllerContext = new ControllerContext { Controller = new EmptyController() }; ExtensibleModelBindingContext bindingContext = new ExtensibleModelBindingContext { 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 ); TestableMutableObjectModelBinder testableBinder = new TestableMutableObjectModelBinder(); // Act testableBinder.SetPropertyPublic( controllerContext, bindingContext, propertyMetadata, dtoResult ); // Assert var person = Assert.IsType <Person>(bindingContext.Model); Assert.Equal(123.456m, person.PropertyWithDefaultValue); Assert.True(controllerContext.Controller.ViewData.ModelState.IsValid); }
public async Task CanCreateModel_CreatesModel_ForTopLevelObjectIfThereIsExplicitPrefix( Type modelType, bool isPrefixProvided) { var mockValueProvider = new Mock<IValueProvider>(); mockValueProvider.Setup(o => o.ContainsPrefixAsync(It.IsAny<string>())) .Returns(Task.FromResult(false)); var metadataProvider = new TestModelMetadataProvider(); var bindingContext = new MutableObjectBinderContext { ModelBindingContext = new ModelBindingContext { // Random type. ModelMetadata = metadataProvider.GetMetadataForType(typeof(Person)), ValueProvider = mockValueProvider.Object, OperationBindingContext = new OperationBindingContext { ValueProvider = mockValueProvider.Object, MetadataProvider = metadataProvider, ValidatorProvider = Mock.Of<IModelValidatorProvider>(), }, // Setting it to empty ensures that model does not get created becasue of no model name. ModelName = "dummyModelName", BinderModelName = isPrefixProvided ? "prefix" : null, } }; var mutableBinder = new TestableMutableObjectModelBinder(); bindingContext.PropertyMetadata = mutableBinder.GetMetadataForProperties( bindingContext.ModelBindingContext); // Act var retModel = await mutableBinder.CanCreateModel(bindingContext); // Assert Assert.Equal(isPrefixProvided, retModel); }
public void CanCreateModel_ReturnsTrue_IfIsTopLevelObject( bool isTopLevelObject, bool expectedCanCreate) { var mockValueProvider = new Mock<IValueProvider>(); mockValueProvider .Setup(o => o.ContainsPrefix(It.IsAny<string>())) .Returns(false); var metadataProvider = new TestModelMetadataProvider(); var bindingContext = new MutableObjectBinderContext { ModelBindingContext = new ModelBindingContext { IsTopLevelObject = isTopLevelObject, // Random type. ModelMetadata = metadataProvider.GetMetadataForType(typeof(Person)), ValueProvider = mockValueProvider.Object, OperationBindingContext = new OperationBindingContext { ValueProvider = mockValueProvider.Object, MetadataProvider = metadataProvider, ValidatorProvider = Mock.Of<IModelValidatorProvider>(), }, ModelState = new ModelStateDictionary(), }, }; var mutableBinder = new TestableMutableObjectModelBinder(); bindingContext.PropertyMetadata = mutableBinder.GetMetadataForProperties(bindingContext.ModelBindingContext).ToArray(); // Act var canCreate = mutableBinder.CanCreateModel(bindingContext); // Assert Assert.Equal(expectedCanCreate, canCreate); }
public void ProcessDto_RequiredFieldNull_RaisesModelErrorWithMessage() { // Arrange var model = new Person(); var containerMetadata = GetMetadataForObject(model); var bindingContext = CreateContext(containerMetadata); ComplexModelDto dto = new ComplexModelDto(containerMetadata, containerMetadata.Properties); TestableMutableObjectModelBinder testableBinder = new TestableMutableObjectModelBinder(); // Make ValueTypeRequired invalid. var propertyMetadata = dto.PropertyMetadata.Single(p => p.PropertyName == "ValueTypeRequired"); dto.Results[propertyMetadata] = new ComplexModelDtoResult(null, new ModelValidationNode(propertyMetadata, "theModel.ValueTypeRequired")); // Act testableBinder.ProcessDto(bindingContext, dto); // Assert ModelStateDictionary 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); ModelError modelError = modelState.Errors[0]; Assert.Null(modelError.Exception); Assert.NotNull(modelError.ErrorMessage); Assert.Equal("Sample message", 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_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 SetProperty_PropertyIsSettable_CallsSetter() { // Arrange Person model = new Person(); ControllerContext controllerContext = new ControllerContext { Controller = new EmptyController() }; ExtensibleModelBindingContext bindingContext = new ExtensibleModelBindingContext { 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 ); TestableMutableObjectModelBinder testableBinder = new TestableMutableObjectModelBinder(); // Act testableBinder.SetPropertyPublic( controllerContext, bindingContext, propertyMetadata, dtoResult ); // Assert validationNode.Validate(controllerContext); Assert.True(controllerContext.Controller.ViewData.ModelState.IsValid); Assert.Equal(new DateTime(2001, 1, 1), model.DateOfBirth); }
public void SetProperty_SettingNonNullableValueTypeToNull_RequiredValidatorNotPresent_RegistersValidationCallback() { // Arrange ControllerContext controllerContext = new ControllerContext { Controller = new EmptyController() }; ExtensibleModelBindingContext bindingContext = new ExtensibleModelBindingContext { 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 ); TestableMutableObjectModelBinder testableBinder = new TestableMutableObjectModelBinder(); // Act testableBinder.SetPropertyPublic( controllerContext, bindingContext, propertyMetadata, dtoResult ); // Assert Assert.True(controllerContext.Controller.ViewData.ModelState.IsValid); validationNode.Validate(controllerContext, bindingContext.ValidationNode); Assert.False(controllerContext.Controller.ViewData.ModelState.IsValid); }
public void SetProperty_PropertyHasDefaultValue_SetsDefaultValue() { // Arrange var bindingContext = CreateContext(GetMetadataForObject(new Person())); var propertyMetadata = bindingContext.ModelMetadata.Properties.First(o => o.PropertyName == "PropertyWithDefaultValue"); var validationNode = new ModelValidationNode(propertyMetadata, "foo"); var dtoResult = new ComplexModelDtoResult(model: null, validationNode: validationNode); var requiredValidator = bindingContext.ValidatorProvider .GetValidators(propertyMetadata) .FirstOrDefault(v => v.IsRequired); var testableBinder = new TestableMutableObjectModelBinder(); // Act testableBinder.SetPropertyPublic(bindingContext, propertyMetadata, dtoResult, requiredValidator); // Assert var person = Assert.IsType <Person>(bindingContext.Model); Assert.Equal(123.456m, person.PropertyWithDefaultValue); Assert.Equal(true, bindingContext.ModelState.IsValid); }
public void EnsureModel_ModelIsNotNull_DoesNothing() { // Arrange ExtensibleModelBindingContext bindingContext = new ExtensibleModelBindingContext { ModelMetadata = GetMetadataForObject(new Person()) }; Mock <TestableMutableObjectModelBinder> mockTestableBinder = new Mock <TestableMutableObjectModelBinder> { CallBase = true }; TestableMutableObjectModelBinder testableBinder = mockTestableBinder.Object; // Act object originalModel = bindingContext.Model; testableBinder.EnsureModelPublic(null, bindingContext); object newModel = bindingContext.Model; // Assert Assert.Same(originalModel, newModel); mockTestableBinder.Verify(o => o.CreateModelPublic(null, bindingContext), Times.Never()); }
public void GetMetadataForProperties_WithBindAttribute() { // Arrange string[] expectedPropertyNames = new[] { "FirstName", "LastName" }; ExtensibleModelBindingContext bindingContext = new ExtensibleModelBindingContext { ModelMetadata = GetMetadataForType(typeof(PersonWithBindExclusion)) }; TestableMutableObjectModelBinder testableBinder = new TestableMutableObjectModelBinder(); // Act IEnumerable <ModelMetadata> propertyMetadatas = testableBinder.GetMetadataForPropertiesPublic(null, bindingContext); string[] returnedPropertyNames = propertyMetadatas .Select(o => o.PropertyName) .ToArray(); // Assert Assert.Equal(expectedPropertyNames, returnedPropertyNames); }
public void SetProperty_PropertyIsSettable_CallsSetter() { // Arrange var model = new Person(); var bindingContext = CreateContext(GetMetadataForObject(model)); var propertyMetadata = bindingContext.ModelMetadata.Properties.Single(o => o.PropertyName == "DateOfBirth"); var validationNode = new ModelValidationNode(propertyMetadata, "foo"); var dtoResult = new ComplexModelDtoResult(new DateTime(2001, 1, 1), validationNode); var requiredValidator = bindingContext.ValidatorProvider .GetValidators(propertyMetadata) .FirstOrDefault(v => v.IsRequired); var validationContext = new ModelValidationContext(bindingContext, propertyMetadata); var testableBinder = new TestableMutableObjectModelBinder(); // Act testableBinder.SetPropertyPublic(bindingContext, propertyMetadata, dtoResult, requiredValidator); // Assert validationNode.Validate(validationContext); Assert.Equal(true, bindingContext.ModelState.IsValid); Assert.Equal(new DateTime(2001, 1, 1), model.DateOfBirth); }
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 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 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_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_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_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 GetMetadataForProperties_ReturnsOnlyIncludedProperties_UsingBindAttributeInclude() { // Arrange var expectedPropertyNames = new[] { "IncludedExplicitly1", "IncludedExplicitly2" }; var bindingContext = new ModelBindingContext { ModelMetadata = GetMetadataForType(typeof(TypeWithIncludedPropertiesUsingBindAttribute)), OperationBindingContext = new OperationBindingContext { ValidatorProvider = Mock.Of<IModelValidatorProvider>(), MetadataProvider = TestModelMetadataProvider.CreateDefaultProvider(), } }; var testableBinder = new TestableMutableObjectModelBinder(); // Act var propertyMetadatas = testableBinder.GetMetadataForProperties(bindingContext); var returnedPropertyNames = propertyMetadatas.Select(o => o.PropertyName).ToArray(); // Assert Assert.Equal(expectedPropertyNames, returnedPropertyNames); }
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_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 GetMetadataForProperties_WithoutBindAttribute() { // Arrange string[] expectedPropertyNames = new[] { "DateOfBirth", "DateOfDeath", "ValueTypeRequired", "FirstName", "LastName", "PropertyWithDefaultValue" }; HttpActionContext actionContext = ContextUtil.CreateActionContext(); ModelBindingContext bindingContext = new ModelBindingContext { ModelMetadata = GetMetadataForType(typeof(Person)) }; TestableMutableObjectModelBinder testableBinder = new TestableMutableObjectModelBinder(); // Act IEnumerable<ModelMetadata> propertyMetadatas = testableBinder.GetMetadataForPropertiesPublic(actionContext, bindingContext); string[] returnedPropertyNames = propertyMetadatas.Select(o => o.PropertyName).ToArray(); // Assert Assert.Equal(expectedPropertyNames, returnedPropertyNames); }
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 CreateModel() { // Arrange ModelBindingContext bindingContext = new ModelBindingContext { ModelMetadata = GetMetadataForType(typeof(Person)) }; TestableMutableObjectModelBinder testableBinder = new TestableMutableObjectModelBinder(); // Act object retModel = testableBinder.CreateModelPublic(null, bindingContext); // Assert Assert.IsType<Person>(retModel); }
public async Task CanCreateModel_ReturnsTrue_IfIsTopLevelObjectAndModelHasNoProperties() { // Arrange var bindingContext = new MutableObjectBinderContext { ModelBindingContext = new ModelBindingContext { IsTopLevelObject = true, ModelMetadata = GetMetadataForType(typeof(PersonWithNoProperties)) }, }; var mutableBinder = new TestableMutableObjectModelBinder(); bindingContext.PropertyMetadata = mutableBinder.GetMetadataForProperties(bindingContext.ModelBindingContext).ToArray(); // Act var retModel = await mutableBinder.CanCreateModel(bindingContext); // Assert Assert.True(retModel); }
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 async Task CanCreateModel_ForExplicitValueProviderMetadata_UsesOriginalValueProvider( Type modelType, bool originalValueProviderProvidesValue) { var mockValueProvider = new Mock<IValueProvider>(); mockValueProvider.Setup(o => o.ContainsPrefixAsync(It.IsAny<string>())) .Returns(Task.FromResult(false)); var mockOriginalValueProvider = new Mock<IBindingSourceValueProvider>(); mockOriginalValueProvider .Setup(o => o.ContainsPrefixAsync(It.IsAny<string>())) .Returns(Task.FromResult(originalValueProviderProvidesValue)); mockOriginalValueProvider .Setup(o => o.Filter(It.IsAny<BindingSource>())) .Returns<BindingSource>(source => { if (source == BindingSource.Query) { return mockOriginalValueProvider.Object; } return null; }); var modelMetadata = GetMetadataForType(modelType); var bindingContext = new MutableObjectBinderContext { ModelBindingContext = new ModelBindingContext { ModelMetadata = modelMetadata, ValueProvider = mockValueProvider.Object, OperationBindingContext = new OperationBindingContext { ValueProvider = mockOriginalValueProvider.Object, MetadataProvider = TestModelMetadataProvider.CreateDefaultProvider(), ValidatorProvider = Mock.Of<IModelValidatorProvider>(), }, // Setting it to empty ensures that model does not get created becasue of no model name. ModelName = "dummyName", BindingSource = modelMetadata.BindingSource, BinderModelName = modelMetadata.BinderModelName } }; var mutableBinder = new TestableMutableObjectModelBinder(); bindingContext.PropertyMetadata = mutableBinder.GetMetadataForProperties(bindingContext.ModelBindingContext).ToArray(); // Act var retModel = await mutableBinder.CanCreateModel(bindingContext); // Assert Assert.Equal(originalValueProviderProvidesValue, retModel); }
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 async Task CanCreateModel_UnmarkedProperties_UsesCurrentValueProvider( Type modelType, bool valueProviderProvidesValue) { var mockValueProvider = new Mock<IValueProvider>(); mockValueProvider.Setup(o => o.ContainsPrefixAsync(It.IsAny<string>())) .Returns(Task.FromResult(valueProviderProvidesValue)); var mockOriginalValueProvider = new Mock<IValueProvider>(); mockOriginalValueProvider.Setup(o => o.ContainsPrefixAsync(It.IsAny<string>())) .Returns(Task.FromResult(false)); var bindingContext = new MutableObjectBinderContext { ModelBindingContext = new ModelBindingContext { ModelMetadata = GetMetadataForType(modelType), ValueProvider = mockValueProvider.Object, OperationBindingContext = new OperationBindingContext { ValidatorProvider = Mock.Of<IModelValidatorProvider>(), ValueProvider = mockOriginalValueProvider.Object, MetadataProvider = TestModelMetadataProvider.CreateDefaultProvider(), }, // Setting it to empty ensures that model does not get created becasue of no model name. ModelName = "dummyName" } }; var mutableBinder = new TestableMutableObjectModelBinder(); bindingContext.PropertyMetadata = mutableBinder.GetMetadataForProperties(bindingContext.ModelBindingContext).ToArray(); // Act var retModel = await mutableBinder.CanCreateModel(bindingContext); // Assert Assert.Equal(valueProviderProvidesValue, retModel); }
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 CreateModel_InstantiatesInstanceOfMetadataType() { // Arrange var bindingContext = new ModelBindingContext { ModelMetadata = GetMetadataForType(typeof(Person)) }; var testableBinder = new TestableMutableObjectModelBinder(); // Act var retModel = testableBinder.CreateModelPublic(bindingContext); // Assert Assert.IsType<Person>(retModel); }
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 GetMetadataForProperties_WithBindAttribute() { // Arrange var expectedPropertyNames = new[] { "FirstName", "LastName" }; var bindingContext = new ModelBindingContext { ModelMetadata = GetMetadataForType(typeof(PersonWithBindExclusion)), OperationBindingContext = new OperationBindingContext { ValidatorProvider = Mock.Of<IModelValidatorProvider>(), MetadataProvider = TestModelMetadataProvider.CreateDefaultProvider() } }; var testableBinder = new TestableMutableObjectModelBinder(); // Act var propertyMetadatas = testableBinder.GetMetadataForProperties(bindingContext); var returnedPropertyNames = propertyMetadatas.Select(o => o.PropertyName).ToArray(); // Assert Assert.Equal(expectedPropertyNames, returnedPropertyNames); }
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 GetMetadataForProperties_WithoutBindAttribute() { // Arrange var expectedPropertyNames = new[] { nameof(Person.DateOfBirth), nameof(Person.DateOfDeath), nameof(Person.ValueTypeRequired), nameof(Person.ValueTypeRequiredWithDefaultValue), nameof(Person.FirstName), nameof(Person.LastName), nameof(Person.PropertyWithDefaultValue), nameof(Person.PropertyWithInitializedValue), nameof(Person.PropertyWithInitializedValueAndDefault), }; var bindingContext = new ModelBindingContext { ModelMetadata = GetMetadataForType(typeof(Person)), OperationBindingContext = new OperationBindingContext { ValidatorProvider = Mock.Of<IModelValidatorProvider>(), MetadataProvider = TestModelMetadataProvider.CreateDefaultProvider() }, }; var testableBinder = new TestableMutableObjectModelBinder(); // Act var propertyMetadatas = testableBinder.GetMetadataForProperties(bindingContext); var returnedPropertyNames = propertyMetadatas.Select(o => o.PropertyName).ToArray(); // Assert Assert.Equal(expectedPropertyNames, returnedPropertyNames); }
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 GetMetadataForProperties_DoesNotReturn_ExcludedProperties() { // Arrange var expectedPropertyNames = new[] { "IncludedByDefault1", "IncludedByDefault2" }; var bindingContext = new ModelBindingContext { ModelMetadata = GetMetadataForType(typeof(TypeWithExcludedPropertiesUsingBindAttribute)), OperationBindingContext = new OperationBindingContext { HttpContext = new DefaultHttpContext { RequestServices = CreateServices() }, ValidatorProvider = Mock.Of<IModelValidatorProvider>(), MetadataProvider = TestModelMetadataProvider.CreateDefaultProvider(), } }; var testableBinder = new TestableMutableObjectModelBinder(); // Act var propertyMetadatas = testableBinder.GetMetadataForProperties(bindingContext); var returnedPropertyNames = propertyMetadatas.Select(o => o.PropertyName).ToArray(); // Assert Assert.Equal(expectedPropertyNames, returnedPropertyNames); }
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); }
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.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("A value is required.", modelError.ErrorMessage); }