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);
        }
Example #2
0
        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 ConstructorSetsProperties() {
            // Arrange
            ModelMetadata modelMetadata = GetModelMetadata();
            ModelMetadata[] propertyMetadata = new ModelMetadata[0];

            // Act
            ComplexModelDto dto = new ComplexModelDto(modelMetadata, propertyMetadata);

            // Assert
            Assert.AreEqual(modelMetadata, dto.ModelMetadata);
            CollectionAssert.AreEqual(propertyMetadata, dto.PropertyMetadata);
            Assert.AreEqual(0, dto.Results.Count, "Results dictionary should have been empty.");
        }
        public void ConstructorSetsProperties()
        {
            // Arrange
            ModelMetadata modelMetadata = GetModelMetadata();
            ModelMetadata[] propertyMetadata = new ModelMetadata[0];

            // Act
            ComplexModelDto dto = new ComplexModelDto(modelMetadata, propertyMetadata);

            // Assert
            Assert.Equal(modelMetadata, dto.ModelMetadata);
            Assert.Equal(propertyMetadata, dto.PropertyMetadata.ToArray());
            Assert.Empty(dto.Results);
        }
Example #5
0
        public void ConstructorSetsProperties()
        {
            // Arrange
            ModelMetadata modelMetadata = GetModelMetadata();

            ModelMetadata[] propertyMetadata = new ModelMetadata[0];

            // Act
            ComplexModelDto dto = new ComplexModelDto(modelMetadata, propertyMetadata);

            // Assert
            Assert.AreEqual(modelMetadata, dto.ModelMetadata);
            CollectionAssert.AreEqual(propertyMetadata, dto.PropertyMetadata);
            Assert.AreEqual(0, dto.Results.Count, "Results dictionary should have been empty.");
        }
Example #6
0
        public void ConstructorSetsProperties()
        {
            // Arrange
            ModelMetadata modelMetadata = GetModelMetadata();

            ModelMetadata[] propertyMetadata = new ModelMetadata[0];

            // Act
            ComplexModelDto dto = new ComplexModelDto(modelMetadata, propertyMetadata);

            // Assert
            Assert.Equal(modelMetadata, dto.ModelMetadata);
            Assert.Equal(propertyMetadata, dto.PropertyMetadata.ToArray());
            Assert.Empty(dto.Results);
        }
Example #7
0
        public bool BindModel(HttpActionContext actionContext, ModelBindingContext bindingContext)
        {
            ComplexModelDto dto = bindingContext.Model as ComplexModelDto;

            if (dto == null)
            {
                return(false);
            }
            foreach (ModelMetadata property in dto.PropertyMetadata)
            {
                ModelBindingContext subContext = new ModelBindingContext(bindingContext)
                {
                    ModelMetadata = property,
                    ModelName     = ModelNameBuiler.CreatePropertyModelName(bindingContext.ModelName, property.PropertyName)
                };
                if (actionContext.Bind(subContext))
                {
                    dto.Results[property] = new ComplexModelDtoResult(subContext.Model, subContext.ValidationNode);
                }
            }
            return(true);
        }
        public bool BindModel(HttpActionContext actionContext, ModelBindingContext bindingContext)
        {
            if (!CanBindType(bindingContext.ModelType))
            {
                return(false);
            }
            if (!bindingContext.ValueProvider.ContainsPrefix(bindingContext.ModelName))
            {
                return(false);
            }

            bindingContext.Model = Activator.CreateInstance(bindingContext.ModelType);
            ComplexModelDto     dto        = new ComplexModelDto(bindingContext.ModelMetadata, bindingContext.PropertyMetadata.Values);
            ModelBindingContext subContext = new ModelBindingContext(bindingContext)
            {
                ModelMetadata = actionContext.GetMetadataProvider().GetMetadataForType(() => dto, typeof(ComplexModelDto)),
                ModelName     = bindingContext.ModelName,
            };

            actionContext.Bind(subContext);

            foreach (KeyValuePair <ModelMetadata, ComplexModelDtoResult> item in dto.Results)
            {
                ModelMetadata         propertyMetadata = item.Key;
                ComplexModelDtoResult dtoResult        = item.Value;
                if (dtoResult != null)
                {
                    PropertyInfo propertyInfo = bindingContext.ModelType.GetProperty(propertyMetadata.PropertyName);
                    if (propertyInfo.CanWrite)
                    {
                        propertyInfo.SetValue(bindingContext.Model, dtoResult.Model);
                    }
                }
            }
            return(true);
        }
        public void BindModel() {
            // Arrange
            ControllerContext controllerContext = new ControllerContext();
            MyModel model = new MyModel();
            ModelMetadata modelMetadata = new EmptyModelMetadataProvider().GetMetadataForType(() => model, typeof(MyModel));
            ComplexModelDto dto = new ComplexModelDto(modelMetadata, modelMetadata.Properties);

            Mock<IExtensibleModelBinder> mockStringBinder = new Mock<IExtensibleModelBinder>();
            mockStringBinder
                .Expect(b => b.BindModel(controllerContext, It.IsAny<ExtensibleModelBindingContext>()))
                .Returns(
                    delegate(ControllerContext cc, ExtensibleModelBindingContext mbc) {
                        Assert.AreEqual(typeof(string), mbc.ModelType);
                        Assert.AreEqual("theModel.StringProperty", mbc.ModelName);
                        mbc.ValidationNode = new ModelValidationNode(mbc.ModelMetadata, "theModel.StringProperty");
                        mbc.Model = "someStringValue";
                        return true;
                    });

            Mock<IExtensibleModelBinder> mockIntBinder = new Mock<IExtensibleModelBinder>();
            mockIntBinder
                .Expect(b => b.BindModel(controllerContext, It.IsAny<ExtensibleModelBindingContext>()))
                .Returns(
                    delegate(ControllerContext cc, ExtensibleModelBindingContext mbc) {
                        Assert.AreEqual(typeof(int), mbc.ModelType);
                        Assert.AreEqual("theModel.IntProperty", mbc.ModelName);
                        mbc.ValidationNode = new ModelValidationNode(mbc.ModelMetadata, "theModel.IntProperty");
                        mbc.Model = 42;
                        return true;
                    });

            Mock<IExtensibleModelBinder> mockDateTimeBinder = new Mock<IExtensibleModelBinder>();
            mockDateTimeBinder
                .Expect(b => b.BindModel(controllerContext, It.IsAny<ExtensibleModelBindingContext>()))
                .Returns(
                    delegate(ControllerContext cc, ExtensibleModelBindingContext mbc) {
                        Assert.AreEqual(typeof(DateTime), mbc.ModelType);
                        Assert.AreEqual("theModel.DateTimeProperty", mbc.ModelName);
                        return false;
                    });

            ModelBinderProviderCollection binders = new ModelBinderProviderCollection();
            binders.RegisterBinderForType(typeof(string), mockStringBinder.Object, true /* suppressPrefixCheck */);
            binders.RegisterBinderForType(typeof(int), mockIntBinder.Object, true /* suppressPrefixCheck */);
            binders.RegisterBinderForType(typeof(DateTime), mockDateTimeBinder.Object, true /* suppressPrefixCheck */);

            ExtensibleModelBindingContext parentBindingContext = new ExtensibleModelBindingContext() {
                ModelMetadata = new EmptyModelMetadataProvider().GetMetadataForType(() => dto, typeof(ComplexModelDto)),
                ModelName = "theModel",
                ModelBinderProviders = binders
            };

            ComplexModelDtoModelBinder binder = new ComplexModelDtoModelBinder();

            // Act
            bool retVal = binder.BindModel(controllerContext, parentBindingContext);

            // Assert
            Assert.IsTrue(retVal);
            Assert.AreEqual(dto, parentBindingContext.Model, "The return model should have been the original DTO.");

            ComplexModelDtoResult stringDtoResult = dto.Results[dto.PropertyMetadata.Where(m => m.ModelType == typeof(string)).First()];
            Assert.AreEqual("someStringValue", stringDtoResult.Model);
            Assert.AreEqual("theModel.StringProperty", stringDtoResult.ValidationNode.ModelStateKey);

            ComplexModelDtoResult intDtoResult = dto.Results[dto.PropertyMetadata.Where(m => m.ModelType == typeof(int)).First()];
            Assert.AreEqual(42, intDtoResult.Model);
            Assert.AreEqual("theModel.IntProperty", intDtoResult.ValidationNode.ModelStateKey);

            ComplexModelDtoResult dateTimeDtoResult = dto.Results[dto.PropertyMetadata.Where(m => m.ModelType == typeof(DateTime)).First()];
            Assert.IsNull(dateTimeDtoResult);
        }
        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_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);
        }
Example #12
0
        public void BindModel()
        {
            // Arrange
            ControllerContext controllerContext = new ControllerContext();
            MyModel           model             = new MyModel();
            ModelMetadata     modelMetadata     = new EmptyModelMetadataProvider().GetMetadataForType(() => model, typeof(MyModel));
            ComplexModelDto   dto = new ComplexModelDto(modelMetadata, modelMetadata.Properties);

            Mock <IExtensibleModelBinder> mockStringBinder = new Mock <IExtensibleModelBinder>();

            mockStringBinder
            .Setup(b => b.BindModel(controllerContext, It.IsAny <ExtensibleModelBindingContext>()))
            .Returns(
                delegate(ControllerContext cc, ExtensibleModelBindingContext mbc) {
                Assert.AreEqual(typeof(string), mbc.ModelType);
                Assert.AreEqual("theModel.StringProperty", mbc.ModelName);
                mbc.ValidationNode = new ModelValidationNode(mbc.ModelMetadata, "theModel.StringProperty");
                mbc.Model          = "someStringValue";
                return(true);
            });

            Mock <IExtensibleModelBinder> mockIntBinder = new Mock <IExtensibleModelBinder>();

            mockIntBinder
            .Setup(b => b.BindModel(controllerContext, It.IsAny <ExtensibleModelBindingContext>()))
            .Returns(
                delegate(ControllerContext cc, ExtensibleModelBindingContext mbc) {
                Assert.AreEqual(typeof(int), mbc.ModelType);
                Assert.AreEqual("theModel.IntProperty", mbc.ModelName);
                mbc.ValidationNode = new ModelValidationNode(mbc.ModelMetadata, "theModel.IntProperty");
                mbc.Model          = 42;
                return(true);
            });

            Mock <IExtensibleModelBinder> mockDateTimeBinder = new Mock <IExtensibleModelBinder>();

            mockDateTimeBinder
            .Setup(b => b.BindModel(controllerContext, It.IsAny <ExtensibleModelBindingContext>()))
            .Returns(
                delegate(ControllerContext cc, ExtensibleModelBindingContext mbc) {
                Assert.AreEqual(typeof(DateTime), mbc.ModelType);
                Assert.AreEqual("theModel.DateTimeProperty", mbc.ModelName);
                return(false);
            });

            ModelBinderProviderCollection binders = new ModelBinderProviderCollection();

            binders.RegisterBinderForType(typeof(string), mockStringBinder.Object, true /* suppressPrefixCheck */);
            binders.RegisterBinderForType(typeof(int), mockIntBinder.Object, true /* suppressPrefixCheck */);
            binders.RegisterBinderForType(typeof(DateTime), mockDateTimeBinder.Object, true /* suppressPrefixCheck */);

            ExtensibleModelBindingContext parentBindingContext = new ExtensibleModelBindingContext()
            {
                ModelMetadata        = new EmptyModelMetadataProvider().GetMetadataForType(() => dto, typeof(ComplexModelDto)),
                ModelName            = "theModel",
                ModelBinderProviders = binders
            };

            ComplexModelDtoModelBinder binder = new ComplexModelDtoModelBinder();

            // Act
            bool retVal = binder.BindModel(controllerContext, parentBindingContext);

            // Assert
            Assert.IsTrue(retVal);
            Assert.AreEqual(dto, parentBindingContext.Model, "The return model should have been the original DTO.");

            ComplexModelDtoResult stringDtoResult = dto.Results[dto.PropertyMetadata.Where(m => m.ModelType == typeof(string)).First()];

            Assert.AreEqual("someStringValue", stringDtoResult.Model);
            Assert.AreEqual("theModel.StringProperty", stringDtoResult.ValidationNode.ModelStateKey);

            ComplexModelDtoResult intDtoResult = dto.Results[dto.PropertyMetadata.Where(m => m.ModelType == typeof(int)).First()];

            Assert.AreEqual(42, intDtoResult.Model);
            Assert.AreEqual("theModel.IntProperty", intDtoResult.ValidationNode.ModelStateKey);

            ComplexModelDtoResult dateTimeDtoResult = dto.Results[dto.PropertyMetadata.Where(m => m.ModelType == typeof(DateTime)).First()];

            Assert.IsNull(dateTimeDtoResult);
        }
Example #13
0
        public bool BindModel(HttpActionContext actionContext, ModelBindingContext bindingContext)
        {
            if (!CanBindType(bindingContext.ModelType))
            {
                return(false);
            }
            if (!bindingContext.ValueProvider.ContainsPrefix(bindingContext.ModelName))
            {
                return(false);
            }
            //创建针对目标类型的空对象
            var ins = DynamicModelBuilder.GetInstance <IContact>(parent: bindingContext.ModelType, propAttrProvider: () =>
            {
                return(new List <PropertyCustomAttributeUnit>
                {
                    new PropertyCustomAttributeUnit
                    {
                        prop_name = "phone",
                        attrs = new List <PropertyCustomAttribute>
                        {
                            new PropertyCustomAttribute
                            {
                                attr_type = "System.ComponentModel.DataAnnotations.RequiredAttribute,System.ComponentModel.DataAnnotations, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35",
                                ctor_arg_types = "",
                                ctor_arg_values = new object[0],
                                error_msg = "姓名不能为空",
                                error_msg_res_name = "",
                                error_msg_res_type = ""
                            }
                        }
                    }
                });
            });

            //bindingContext.Model = Activator.CreateInstance(bindingContext.ModelType);
            bindingContext.Model = ins;

            //创建针对目标类型的ComplexModelDto
            //创建ModelBindingContext,并将ComplexModelDto作为Model,驱动新一轮的Model绑定
            ComplexModelDto     dto        = new ComplexModelDto(bindingContext.ModelMetadata, bindingContext.PropertyMetadata.Values);
            ModelBindingContext subContext = new ModelBindingContext(bindingContext)
            {
                ModelMetadata = actionContext.GetMetadataProvider().GetMetadataForType(() => dto, typeof(ComplexModelDto)),
                ModelName     = bindingContext.ModelName
            };

            actionContext.Bind(subContext);

            //从ComplexModelDto获取相应的值并为相应的属性赋值
            foreach (KeyValuePair <ModelMetadata, ComplexModelDtoResult> item in dto.Results)
            {
                ModelMetadata         propertyMetadata = item.Key;
                ComplexModelDtoResult dtoResult        = item.Value;
                if (dtoResult != null)
                {
                    PropertyInfo propertyInfo = bindingContext.ModelType.GetProperty(propertyMetadata.PropertyName);
                    if (propertyInfo.CanWrite)
                    {
                        propertyInfo.SetValue(bindingContext.Model, dtoResult.Model);
                    }
                }
            }
            return(true);
        }