public void BindModel() {
            // Arrange
            ControllerContext controllerContext = new ControllerContext();
            ExtensibleModelBindingContext bindingContext = new ExtensibleModelBindingContext() {
                ModelMetadata = new EmptyModelMetadataProvider().GetMetadataForType(null, typeof(IDictionary<int, string>)),
                ModelName = "someName",
                ModelBinderProviders = new ModelBinderProviderCollection(),
                ValueProvider = new SimpleValueProvider() {
                    { "someName[0]", new KeyValuePair<int, string>(42, "forty-two") },
                    { "someName[1]", new KeyValuePair<int, string>(84, "eighty-four") }
                }
            };

            Mock<IExtensibleModelBinder> mockKvpBinder = new Mock<IExtensibleModelBinder>();
            mockKvpBinder
                .Expect(o => o.BindModel(controllerContext, It.IsAny<ExtensibleModelBindingContext>()))
                .Returns(
                    delegate(ControllerContext cc, ExtensibleModelBindingContext mbc) {
                        mbc.Model = mbc.ValueProvider.GetValue(mbc.ModelName).ConvertTo(mbc.ModelType);
                        return true;
                    });
            bindingContext.ModelBinderProviders.RegisterBinderForType(typeof(KeyValuePair<int, string>), mockKvpBinder.Object, false /* suppressPrefixCheck */);

            // Act
            bool retVal = new DictionaryModelBinder<int, string>().BindModel(controllerContext, bindingContext);

            // Assert
            Assert.IsTrue(retVal);

            IDictionary<int, string> dictionary = bindingContext.Model as IDictionary<int, string>;
            Assert.IsNotNull(dictionary);
            Assert.AreEqual(2, dictionary.Count);
            Assert.AreEqual("forty-two", dictionary[42]);
            Assert.AreEqual("eighty-four", dictionary[84]);
        }
        public async Task BindModel_Succeeds(bool isReadOnly)
        {
            // Arrange
            var values = new Dictionary<string, string>()
            {
                { "someName[0].Key", "42" },
                { "someName[0].Value", "forty-two" },
                { "someName[1].Key", "84" },
                { "someName[1].Value", "eighty-four" },
            };

            // Value Provider

            var bindingContext = GetModelBindingContext(isReadOnly, values);
            bindingContext.ValueProvider = CreateEnumerableValueProvider("{0}", values);

            var binder = new DictionaryModelBinder<int, string>(
                new SimpleTypeModelBinder(typeof(int)), 
                new SimpleTypeModelBinder(typeof(string)));

            // Act
            await binder.BindModelAsync(bindingContext);

            // Assert
            Assert.True(bindingContext.Result.IsModelSet);

            var dictionary = Assert.IsAssignableFrom<IDictionary<int, string>>(bindingContext.Result.Model);
            Assert.NotNull(dictionary);
            Assert.Equal(2, dictionary.Count);
            Assert.Equal("forty-two", dictionary[42]);
            Assert.Equal("eighty-four", dictionary[84]);

            // This uses the default IValidationStrategy
            Assert.DoesNotContain(bindingContext.Result.Model, bindingContext.ValidationState.Keys);
        }
        public async Task BindModel()
        {
            // Arrange
            var metadataProvider = new EmptyModelMetadataProvider();
            ModelBindingContext bindingContext = new ModelBindingContext
            {
                ModelMetadata = metadataProvider.GetMetadataForType(typeof(IDictionary<int, string>)),
                ModelName = "someName",
                ValueProvider = new SimpleHttpValueProvider
                {
                    { "someName[0]", new KeyValuePair<int, string>(42, "forty-two") },
                    { "someName[1]", new KeyValuePair<int, string>(84, "eighty-four") }
                },
                OperationBindingContext = new OperationBindingContext
                {
                    ModelBinder = CreateKvpBinder(),
                    MetadataProvider = metadataProvider
                }
            };
            var binder = new DictionaryModelBinder<int, string>();

            // Act
            var retVal = await binder.BindModelAsync(bindingContext);

            // Assert
            Assert.NotNull(retVal);

            var dictionary = Assert.IsAssignableFrom<IDictionary<int, string>>(retVal.Model);
            Assert.NotNull(dictionary);
            Assert.Equal(2, dictionary.Count);
            Assert.Equal("forty-two", dictionary[42]);
            Assert.Equal("eighty-four", dictionary[84]);
        }
        public void BindModel()
        {
            // Arrange
            ControllerContext             controllerContext = new ControllerContext();
            ExtensibleModelBindingContext bindingContext    = new ExtensibleModelBindingContext
            {
                ModelMetadata = new EmptyModelMetadataProvider().GetMetadataForType(
                    null,
                    typeof(IDictionary <int, string>)
                    ),
                ModelName            = "someName",
                ModelBinderProviders = new ModelBinderProviderCollection(),
                ValueProvider        = new SimpleValueProvider
                {
                    { "someName[0]", new KeyValuePair <int, string>(42, "forty-two") },
                    { "someName[1]", new KeyValuePair <int, string>(84, "eighty-four") }
                }
            };

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

            mockKvpBinder
            .Setup(
                o => o.BindModel(controllerContext, It.IsAny <ExtensibleModelBindingContext>())
                )
            .Returns(
                delegate(ControllerContext cc, ExtensibleModelBindingContext mbc)
            {
                mbc.Model = mbc.ValueProvider
                            .GetValue(mbc.ModelName)
                            .ConvertTo(mbc.ModelType);
                return(true);
            }
                );
            bindingContext.ModelBinderProviders.RegisterBinderForType(
                typeof(KeyValuePair <int, string>),
                mockKvpBinder.Object,
                false /* suppressPrefixCheck */
                );

            // Act
            bool retVal = new DictionaryModelBinder <int, string>().BindModel(
                controllerContext,
                bindingContext
                );

            // Assert
            Assert.True(retVal);

            var dictionary = Assert.IsAssignableFrom <IDictionary <int, string> >(
                bindingContext.Model
                );

            Assert.NotNull(dictionary);
            Assert.Equal(2, dictionary.Count);
            Assert.Equal("forty-two", dictionary[42]);
            Assert.Equal("eighty-four", dictionary[84]);
        }
Example #5
0
        public async Task BindModel_FallsBackToBindingValues_WithComplexValues()
        {
            // Arrange
            var dictionary = new Dictionary <int, ModelWithProperties>
            {
                { 23, new ModelWithProperties {
                      Id = 43, Name = "Wilma"
                  } },
                { 27, new ModelWithProperties {
                      Id = 98, Name = "Fred"
                  } },
            };
            var stringDictionary = new Dictionary <string, string>
            {
                { "prefix[23].Id", "43" },
                { "prefix[23].Name", "Wilma" },
                { "prefix[27].Id", "98" },
                { "prefix[27].Name", "Fred" },
            };
            var binder  = new DictionaryModelBinder <int, ModelWithProperties>();
            var context = CreateContext();

            context.ModelName = "prefix";
            context.OperationBindingContext.ModelBinder   = CreateCompositeBinder();
            context.OperationBindingContext.ValueProvider = CreateEnumerableValueProvider("{0}", stringDictionary);
            context.ValueProvider = context.OperationBindingContext.ValueProvider;

            var metadataProvider = context.OperationBindingContext.MetadataProvider;

            context.ModelMetadata = metadataProvider.GetMetadataForProperty(
                typeof(ModelWithDictionaryProperties),
                nameof(ModelWithDictionaryProperties.DictionaryWithComplexValuesProperty));

            // Act
            var result = await binder.BindModelAsync(context);

            // Assert
            Assert.NotNull(result);
            Assert.False(result.IsFatalError);
            Assert.True(result.IsModelSet);
            Assert.Equal("prefix", result.Key);
            Assert.NotNull(result.ValidationNode);

            var resultDictionary = Assert.IsAssignableFrom <IDictionary <int, ModelWithProperties> >(result.Model);

            Assert.Equal(dictionary, resultDictionary);
        }
        public async Task DictionaryModelBinder_DoesNotCreateCollection_ForTopLevelModel_OnFirstPass()
        {
            // Arrange
            var binder = new DictionaryModelBinder<string, string>();

            var context = CreateContext();
            context.ModelName = "param";

            var metadataProvider = context.OperationBindingContext.MetadataProvider;
            context.ModelMetadata = metadataProvider.GetMetadataForType(typeof(Dictionary<string, string>));

            context.ValueProvider = new TestValueProvider(new Dictionary<string, object>());

            // Act
            var result = await binder.BindModelAsync(context);

            // Assert
            Assert.Null(result);
        }
        public async Task BindModel_Succeeds(bool isReadOnly)
        {
            // Arrange
            var bindingContext = GetModelBindingContext(isReadOnly);
            var modelState = bindingContext.ModelState;
            var binder = new DictionaryModelBinder<int, string>();

            // Act
            var result = await binder.BindModelAsync(bindingContext);

            // Assert
            Assert.NotNull(result);
            Assert.True(result.IsModelSet);
            var dictionary = Assert.IsAssignableFrom<IDictionary<int, string>>(result.Model);
            Assert.True(modelState.IsValid);

            Assert.NotNull(dictionary);
            Assert.Equal(2, dictionary.Count);
            Assert.Equal("forty-two", dictionary[42]);
            Assert.Equal("eighty-four", dictionary[84]);
        }
Example #8
0
        public async Task BindModel_DoesNotFallBack_WithoutEnumerableValueProvider()
        {
            // Arrange
            var dictionary = new Dictionary <string, string>(StringComparer.Ordinal)
            {
                { "one", "one" },
                { "two", "two" },
                { "three", "three" },
            };

            var binder  = new DictionaryModelBinder <string, string>();
            var context = CreateContext();

            context.ModelName = "prefix";
            context.OperationBindingContext.ModelBinder   = CreateCompositeBinder();
            context.OperationBindingContext.ValueProvider = CreateTestValueProvider("prefix[{0}]", dictionary);
            context.ValueProvider = context.OperationBindingContext.ValueProvider;

            var metadataProvider = context.OperationBindingContext.MetadataProvider;

            context.ModelMetadata = metadataProvider.GetMetadataForProperty(
                typeof(ModelWithDictionaryProperties),
                nameof(ModelWithDictionaryProperties.DictionaryProperty));

            // Act
            var result = await binder.BindModelAsync(context);

            // Assert
            Assert.NotNull(result);
            Assert.False(result.IsFatalError);
            Assert.True(result.IsModelSet);
            Assert.Equal("prefix", result.Key);
            Assert.NotNull(result.ValidationNode);

            var resultDictionary = Assert.IsAssignableFrom <IDictionary <string, string> >(result.Model);

            Assert.Empty(resultDictionary);
        }
        public void BindModel()
        {
            // Arrange
            Mock<IModelBinder> mockKvpBinder = new Mock<IModelBinder>();
            ModelBindingContext bindingContext = new ModelBindingContext
            {
                ModelMetadata = new EmptyModelMetadataProvider().GetMetadataForType(null, typeof(IDictionary<int, string>)),
                ModelName = "someName",
                ValueProvider = new SimpleHttpValueProvider
                {
                    { "someName[0]", new KeyValuePair<int, string>(42, "forty-two") },
                    { "someName[1]", new KeyValuePair<int, string>(84, "eighty-four") }
                }
            };
            HttpActionContext context = ContextUtil.CreateActionContext();
            context.ControllerContext.Configuration.Services.Replace(typeof(ModelBinderProvider), (new SimpleModelBinderProvider(typeof(KeyValuePair<int, string>), mockKvpBinder.Object)));

            mockKvpBinder
                .Setup(o => o.BindModel(context, It.IsAny<ModelBindingContext>()))
                .Returns((HttpActionContext cc, ModelBindingContext mbc) =>
                {
                    mbc.Model = mbc.ValueProvider.GetValue(mbc.ModelName).ConvertTo(mbc.ModelType);
                    return true;
                });

            // Act
            bool retVal = new DictionaryModelBinder<int, string>().BindModel(context, bindingContext);

            // Assert
            Assert.True(retVal);

            var dictionary = Assert.IsAssignableFrom<IDictionary<int, string>>(bindingContext.Model);
            Assert.NotNull(dictionary);
            Assert.Equal(2, dictionary.Count);
            Assert.Equal("forty-two", dictionary[42]);
            Assert.Equal("eighty-four", dictionary[84]);
        }
Example #10
0
        public async Task DictionaryModelBinder_DoesNotCreateCollection_IfIsTopLevelObjectAndIsFirstChanceBinding()
        {
            // Arrange
            var binder = new DictionaryModelBinder<string, string>();

            var context = CreateContext();
            context.IsTopLevelObject = true;
            context.IsFirstChanceBinding = true;

            // Explicit prefix and empty model name both ignored.
            context.BinderModelName = "prefix";
            context.ModelName = string.Empty;

            var metadataProvider = context.OperationBindingContext.MetadataProvider;
            context.ModelMetadata = metadataProvider.GetMetadataForType(typeof(Dictionary<string, string>));

            context.ValueProvider = new TestValueProvider(new Dictionary<string, object>());

            // Act
            var result = await binder.BindModelAsync(context);

            // Assert
            Assert.Null(result);
        }
        public async Task DictionaryModelBinder_CreatesEmptyCollection_ForTopLevelModel_OnFallback()
        {
            // Arrange
            var binder = new DictionaryModelBinder<string, string>();

            var context = CreateContext();
            context.ModelName = string.Empty;

            var metadataProvider = context.OperationBindingContext.MetadataProvider;
            context.ModelMetadata = metadataProvider.GetMetadataForType(typeof(Dictionary<string, string>));

            context.ValueProvider = new TestValueProvider(new Dictionary<string, object>());

            // Act
            var result = await binder.BindModelAsync(context);

            // Assert
            Assert.NotNull(result);

            Assert.Empty(Assert.IsType<Dictionary<string, string>>(result.Model));
            Assert.Equal(string.Empty, result.Key);
            Assert.True(result.IsModelSet);

            Assert.Same(result.ValidationNode.Model, result.Model);
            Assert.Same(result.ValidationNode.Key, result.Key);
            Assert.Same(result.ValidationNode.ModelMetadata, context.ModelMetadata);
        }
Example #12
0
        public void CanCreateInstance_ReturnsExpectedValue(Type modelType, bool expectedResult)
        {
            // Arrange
            var binder = new DictionaryModelBinder<int, int>(
                new SimpleTypeModelBinder(typeof(int)), 
                new SimpleTypeModelBinder(typeof(int)));

            // Act
            var result = binder.CanCreateInstance(modelType);

            // Assert
            Assert.Equal(expectedResult, result);
        }
Example #13
0
        public async Task DictionaryModelBinder_DoesNotCreateCollection_IfNotIsTopLevelObject(string prefix)
        {
            // Arrange
            var binder = new DictionaryModelBinder<int, int>(
                new SimpleTypeModelBinder(typeof(int)), 
                new SimpleTypeModelBinder(typeof(int)));

            var bindingContext = CreateContext();
            bindingContext.ModelName = ModelNames.CreatePropertyModelName(prefix, "ListProperty");

            var metadataProvider = new TestModelMetadataProvider();
            bindingContext.ModelMetadata = metadataProvider.GetMetadataForProperty(
                typeof(ModelWithDictionaryProperties),
                nameof(ModelWithDictionaryProperties.DictionaryProperty));

            bindingContext.ValueProvider = new TestValueProvider(new Dictionary<string, object>());

            // Act
            await binder.BindModelAsync(bindingContext);

            // Assert
            Assert.False(bindingContext.Result.IsModelSet);
        }
Example #14
0
        public async Task DictionaryModelBinder_CreatesEmptyCollection_IfIsTopLevelObject()
        {
            // Arrange
            var binder = new DictionaryModelBinder<string, string>(
                new SimpleTypeModelBinder(typeof(string)), 
                new SimpleTypeModelBinder(typeof(string)));

            var bindingContext = CreateContext();
            bindingContext.IsTopLevelObject = true;

            // Lack of prefix and non-empty model name both ignored.
            bindingContext.ModelName = "modelName";

            var metadataProvider = new TestModelMetadataProvider();
            bindingContext.ModelMetadata = metadataProvider.GetMetadataForType(typeof(Dictionary<string, string>));

            bindingContext.ValueProvider = new TestValueProvider(new Dictionary<string, object>());

            // Act
            await binder.BindModelAsync(bindingContext);

            // Assert
            Assert.Empty(Assert.IsType<Dictionary<string, string>>(bindingContext.Result.Model));
            Assert.True(bindingContext.Result.IsModelSet);
        }
Example #15
0
        public async Task BindModel_FallsBackToBindingValues_WithCustomDictionary(
            string modelName,
            string keyFormat,
            IDictionary<string, string> dictionary)
        {
            // Arrange
            var expectedDictionary = new SortedDictionary<string, string>(dictionary);
            var binder = new DictionaryModelBinder<string, string>(
                new SimpleTypeModelBinder(typeof(string)), 
                new SimpleTypeModelBinder(typeof(string)));

            var bindingContext = CreateContext();
            bindingContext.ModelName = modelName;

            bindingContext.ValueProvider = CreateEnumerableValueProvider(keyFormat, dictionary);
            bindingContext.FieldName = bindingContext.ModelName;

            var metadataProvider = new TestModelMetadataProvider();
            bindingContext.ModelMetadata = metadataProvider.GetMetadataForProperty(
                typeof(ModelWithDictionaryProperties),
                nameof(ModelWithDictionaryProperties.CustomDictionaryProperty));

            // Act
            await binder.BindModelAsync(bindingContext);

            // Assert
            Assert.True(bindingContext.Result.IsModelSet);

            var resultDictionary = Assert.IsAssignableFrom<SortedDictionary<string, string>>(bindingContext.Result.Model);
            Assert.Equal(expectedDictionary, resultDictionary);
        }
Example #16
0
        public async Task BindModel_FallsBackToBindingValues_WithComplexValues()
        {
            // Arrange
            var dictionary = new Dictionary<int, ModelWithProperties>
            {
                { 23, new ModelWithProperties { Id = 43, Name = "Wilma" } },
                { 27, new ModelWithProperties { Id = 98, Name = "Fred" } },
            };
            var stringDictionary = new Dictionary<string, string>
            {
                { "prefix[23].Id", "43" },
                { "prefix[23].Name", "Wilma" },
                { "prefix[27].Id", "98" },
                { "prefix[27].Name", "Fred" },
            };

            var bindingContext = CreateContext();
            bindingContext.ModelName = "prefix";
            bindingContext.ValueProvider = CreateEnumerableValueProvider("{0}", stringDictionary);
            bindingContext.FieldName = bindingContext.ModelName;

            var metadataProvider = new TestModelMetadataProvider();
            bindingContext.ModelMetadata = metadataProvider.GetMetadataForProperty(
                typeof(ModelWithDictionaryProperties),
                nameof(ModelWithDictionaryProperties.DictionaryWithComplexValuesProperty));

            var valueMetadata = metadataProvider.GetMetadataForType(typeof(ModelWithProperties));

            var binder = new DictionaryModelBinder<int, ModelWithProperties>(
                new SimpleTypeModelBinder(typeof(int)),
                new ComplexTypeModelBinder(new Dictionary<ModelMetadata, IModelBinder>()
                {
                    { valueMetadata.Properties["Id"], new SimpleTypeModelBinder(typeof(int)) },
                    { valueMetadata.Properties["Name"], new SimpleTypeModelBinder(typeof(string)) },
                }));

            // Act
            await binder.BindModelAsync(bindingContext);

            // Assert
            Assert.True(bindingContext.Result.IsModelSet);

            var resultDictionary = Assert.IsAssignableFrom<IDictionary<int, ModelWithProperties>>(bindingContext.Result.Model);
            Assert.Equal(dictionary, resultDictionary);

            // This requires a non-default IValidationStrategy
            Assert.Contains(bindingContext.Result.Model, bindingContext.ValidationState.Keys);
            var entry = bindingContext.ValidationState[bindingContext.Result.Model];
            var strategy = Assert.IsType<ShortFormDictionaryValidationStrategy<int, ModelWithProperties>>(entry.Strategy);
            Assert.Equal(
                new KeyValuePair<string, int>[]
                {
                    new KeyValuePair<string, int>("23", 23),
                    new KeyValuePair<string, int>("27", 27),
                }.OrderBy(kvp => kvp.Key),
                strategy.KeyMappings.OrderBy(kvp => kvp.Key));
        }
Example #17
0
        public async Task BindModel_FallsBackToBindingValues_WithValueTypes(IDictionary<long, int> dictionary)
        {
            // Arrange
            var stringDictionary = dictionary.ToDictionary(kvp => kvp.Key.ToString(), kvp => kvp.Value.ToString());

            var binder = new DictionaryModelBinder<long, int>(
                new SimpleTypeModelBinder(typeof(long)), 
                new SimpleTypeModelBinder(typeof(int)));

            var bindingContext = CreateContext();
            bindingContext.ModelName = "prefix";
            bindingContext.ValueProvider = CreateEnumerableValueProvider("prefix[{0}]", stringDictionary);
            bindingContext.FieldName = bindingContext.ModelName;

            var metadataProvider = new TestModelMetadataProvider();
            bindingContext.ModelMetadata = metadataProvider.GetMetadataForProperty(
                typeof(ModelWithDictionaryProperties),
                nameof(ModelWithDictionaryProperties.DictionaryWithValueTypesProperty));

            // Act
            await binder.BindModelAsync(bindingContext);

            // Assert
            Assert.True(bindingContext.Result.IsModelSet);

            var resultDictionary = Assert.IsAssignableFrom<IDictionary<long, int>>(bindingContext.Result.Model);
            Assert.Equal(dictionary, resultDictionary);
        }
Example #18
0
        public async Task BindModel_DoesNotFallBack_WithoutEnumerableValueProvider()
        {
            // Arrange
            var dictionary = new Dictionary<string, string>(StringComparer.Ordinal)
            {
                { "one", "one" },
                { "two", "two" },
                { "three", "three" },
            };

            var binder = new DictionaryModelBinder<string, string>(
                new SimpleTypeModelBinder(typeof(string)), 
                new SimpleTypeModelBinder(typeof(string)));

            var bindingContext = CreateContext();
            bindingContext.ModelName = "prefix";
            bindingContext.ValueProvider = CreateTestValueProvider("prefix[{0}]", dictionary);
            bindingContext.FieldName = bindingContext.ModelName;

            var metadataProvider = new TestModelMetadataProvider();
            bindingContext.ModelMetadata = metadataProvider.GetMetadataForProperty(
                typeof(ModelWithDictionaryProperties),
                nameof(ModelWithDictionaryProperties.DictionaryProperty));

            // Act
            await binder.BindModelAsync(bindingContext);

            // Assert
            Assert.True(bindingContext.Result.IsModelSet);

            var resultDictionary = Assert.IsAssignableFrom<IDictionary<string, string>>(bindingContext.Result.Model);
            Assert.Empty(resultDictionary);
        }
        public async Task DictionaryModelBinder_DoesNotCreateCollection_ForNonTopLevelModel(string prefix)
        {
            // Arrange
            var binder = new DictionaryModelBinder<string, string>();

            var context = CreateContext();
            context.ModelName = ModelNames.CreatePropertyModelName(prefix, "ListProperty");

            var metadataProvider = context.OperationBindingContext.MetadataProvider;
            context.ModelMetadata = metadataProvider.GetMetadataForProperty(
                typeof(ModelWithDictionaryProperty),
                nameof(ModelWithDictionaryProperty.DictionaryProperty));

            context.ValueProvider = new TestValueProvider(new Dictionary<string, object>());

            // Act
            var result = await binder.BindModelAsync(context);

            // Assert
            Assert.Null(result);
        }
Example #20
0
        public async Task DictionaryModelBinder_CreatesEmptyCollection_IfIsTopLevelObjectAndNotIsFirstChanceBinding()
        {
            // Arrange
            var binder = new DictionaryModelBinder<string, string>();

            var context = CreateContext();
            context.IsTopLevelObject = true;

            // Lack of prefix and non-empty model name both ignored.
            context.ModelName = "modelName";

            var metadataProvider = context.OperationBindingContext.MetadataProvider;
            context.ModelMetadata = metadataProvider.GetMetadataForType(typeof(Dictionary<string, string>));

            context.ValueProvider = new TestValueProvider(new Dictionary<string, object>());

            // Act
            var result = await binder.BindModelAsync(context);

            // Assert
            Assert.NotNull(result);

            Assert.Empty(Assert.IsType<Dictionary<string, string>>(result.Model));
            Assert.Equal("modelName", result.Key);
            Assert.True(result.IsModelSet);

            Assert.Same(result.ValidationNode.Model, result.Model);
            Assert.Same(result.ValidationNode.Key, result.Key);
            Assert.Same(result.ValidationNode.ModelMetadata, context.ModelMetadata);
        }