public void UpdateDictionaryReturnsNullIfNoValidElementsFound() {
            // Arrange
            ModelBindingContext bindingContext = new ModelBindingContext() {
                ValueProvider = new Dictionary<string, ValueProviderResult>()
            };
            DefaultModelBinder binder = new DefaultModelBinder();

            // Act
            object updatedModel = binder.UpdateDictionary(null, bindingContext, typeof(object), typeof(object));

            // Assert
            Assert.IsNull(updatedModel, "Method should return null if no values exist as part of the request.");
        }
        public void UpdateDictionarySkipsInvalidKeys() {
            // Arrange
            Dictionary<int, string> model = new Dictionary<int, string>{
                { 1, "one" },
                { 2, "two" }
            };
            ModelBindingContext bindingContext = new ModelBindingContext() {
                Model = model,
                ModelName = "foo",
                ValueProvider = new Dictionary<string, ValueProviderResult>() {
                    { "foo[0].key", null }, { "foo[0].value", null },
                    { "foo[1].key", null }, { "foo[1].value", null },
                    { "foo[2].key", null }, { "foo[2].value", null }
                }
            };

            Mock<IModelBinder> mockIntBinder = new Mock<IModelBinder>();
            mockIntBinder
                .Expect(b => b.BindModel(It.IsAny<ControllerContext>(), It.IsAny<ModelBindingContext>()))
                .Returns(
                    delegate(ControllerContext cc, ModelBindingContext bc) {
                        int fooIdx = Int32.Parse(bc.ModelName.Substring(4, 1), CultureInfo.InvariantCulture);
                        return (fooIdx == 1) ? (object)null : fooIdx;
                    });

            Mock<IModelBinder> mockStringBinder = new Mock<IModelBinder>();
            mockStringBinder
                .Expect(b => b.BindModel(It.IsAny<ControllerContext>(), It.IsAny<ModelBindingContext>()))
                .Returns(
                    delegate(ControllerContext cc, ModelBindingContext bc) {
                        return (Int32.Parse(bc.ModelName.Substring(4, 1), CultureInfo.InvariantCulture) + 10) + "Value";
                    });

            DefaultModelBinder binder = new DefaultModelBinder() {
                Binders = new ModelBinderDictionary() {
                    { typeof(int), mockIntBinder.Object },
                    { typeof(string), mockStringBinder.Object }
                }
            };

            // Act
            object updatedModel = binder.UpdateDictionary(null, bindingContext, typeof(int), typeof(string));

            // Assert
            Assert.AreEqual(2, model.Count, "Model is not of correct length.");
            Assert.AreEqual(false, bindingContext.ModelState.IsValidField("foo[1].key"), "Conversion should have failed.");
            Assert.AreEqual("A value is required.", bindingContext.ModelState["foo[1].key"].Errors[0].ErrorMessage, "Error message did not propagate correctly.");
            Assert.AreEqual("10Value", model[0]);
            Assert.AreEqual("12Value", model[2]);
        }
        public void UpdateDictionaryReturnsModifiedDictionaryOnSuccess() {
            // Arrange
            ControllerContext controllerContext = new Mock<ControllerContext>().Object;

            Dictionary<int, string> model = new Dictionary<int, string>{
                { 1, "one" },
                { 2, "two" }
            };
            ModelBindingContext bindingContext = new ModelBindingContext() {
                Model = model,
                ModelName = "foo",
                PropertyFilter = _ => false,
                ValueProvider = new Dictionary<string, ValueProviderResult>() {
                    { "foo[0].key", null }, { "foo[0].value", null },
                    { "foo[1].key", null }, { "foo[1].value", null },
                    { "foo[2].key", null }, { "foo[2].value", null }
                }
            };

            Mock<IModelBinder> mockIntBinder = new Mock<IModelBinder>();
            mockIntBinder
                .Expect(b => b.BindModel(It.IsAny<ControllerContext>(), It.IsAny<ModelBindingContext>()))
                .Returns(
                    delegate(ControllerContext cc, ModelBindingContext bc) {
                        Assert.AreEqual(controllerContext, cc, "ControllerContext was not forwarded correctly.");
                        Assert.AreEqual(typeof(int), bc.ModelType, "ModelType was not forwarded correctly.");
                        Assert.AreEqual(bindingContext.ModelState, bc.ModelState, "ModelState was not forwarded correctly.");
                        Assert.AreEqual(new ModelBindingContext().PropertyFilter, bc.PropertyFilter, "PropertyFilter should not have been set.");
                        Assert.AreEqual(bindingContext.ValueProvider, bc.ValueProvider, "ValueProvider was not forwarded correctly.");
                        return Int32.Parse(bc.ModelName.Substring(4, 1), CultureInfo.InvariantCulture) + 10;
                    });

            Mock<IModelBinder> mockStringBinder = new Mock<IModelBinder>();
            mockStringBinder
                .Expect(b => b.BindModel(It.IsAny<ControllerContext>(), It.IsAny<ModelBindingContext>()))
                .Returns(
                    delegate(ControllerContext cc, ModelBindingContext bc) {
                        Assert.AreEqual(controllerContext, cc, "ControllerContext was not forwarded correctly.");
                        Assert.AreEqual(typeof(string), bc.ModelType, "ModelType was not forwarded correctly.");
                        Assert.AreEqual(bindingContext.ModelState, bc.ModelState, "ModelState was not forwarded correctly.");
                        Assert.AreEqual(bindingContext.PropertyFilter, bc.PropertyFilter, "PropertyFilter was not forwarded correctly.");
                        Assert.AreEqual(bindingContext.ValueProvider, bc.ValueProvider, "ValueProvider was not forwarded correctly.");
                        return (Int32.Parse(bc.ModelName.Substring(4, 1), CultureInfo.InvariantCulture) + 10) + "Value";
                    });

            DefaultModelBinder binder = new DefaultModelBinder() {
                Binders = new ModelBinderDictionary() {
                    { typeof(int), mockIntBinder.Object },
                    { typeof(string), mockStringBinder.Object }
                }
            };

            // Act
            object updatedModel = binder.UpdateDictionary(controllerContext, bindingContext, typeof(int), typeof(string));

            // Assert
            Assert.AreSame(model, updatedModel, "Should have updated the provided model object.");
            Assert.AreEqual(3, model.Count, "Model is not of correct length.");
            Assert.AreEqual("10Value", model[10]);
            Assert.AreEqual("11Value", model[11]);
            Assert.AreEqual("12Value", model[12]);
        }