public async Task BindModel_ComplexCollection_Succeeds(bool isReadOnly)
        {
            // Arrange
            var valueProvider = new SimpleHttpValueProvider
            {
                { "someName.index", new[] { "foo", "bar", "baz" } },
                { "someName[foo]", "42" },
                { "someName[bar]", "100" },
                { "someName[baz]", "200" }
            };
            var bindingContext = GetModelBindingContext(valueProvider, isReadOnly);
            var modelState = bindingContext.ModelState;
            var binder = new CollectionModelBinder<int>();

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

            // Assert
            Assert.NotNull(result);
            Assert.True(result.IsModelSet);

            var list = Assert.IsAssignableFrom<IList<int>>(result.Model);
            Assert.Equal(new[] { 42, 100, 200 }, list.ToArray());

            Assert.True(modelState.IsValid);
        }
        public async Task BindComplexCollectionFromIndexes_FiniteIndexes()
        {
            // Arrange
            var valueProvider = new SimpleHttpValueProvider
            {
                { "someName[foo]", "42" },
                { "someName[baz]", "200" }
            };
            var bindingContext = GetModelBindingContext(valueProvider);
            var binder = new CollectionModelBinder<int>();

            // Act
            var boundCollection = await binder.BindComplexCollectionFromIndexes(bindingContext, new[] { "foo", "bar", "baz" });

            // Assert
            Assert.Equal(new[] { 42, 0, 200 }, boundCollection.ToArray());
        }
        public async Task BindComplexCollectionFromIndexes_InfiniteIndexes()
        {
            // Arrange
            var valueProvider = new SimpleHttpValueProvider
            {
                { "someName[0]", "42" },
                { "someName[1]", "100" },
                { "someName[3]", "400" }
            };
            var bindingContext = GetModelBindingContext(valueProvider);
            var binder = new CollectionModelBinder<int>();

            // Act
            var boundCollection = await binder.BindComplexCollectionFromIndexes(bindingContext, indexNames: null);

            // Assert
            Assert.Equal(new[] { 42, 100 }, boundCollection.ToArray());
        }
        public async Task BindModel_ComplexCollection()
        {
            // Arrange
            var valueProvider = new SimpleHttpValueProvider
            {
                { "someName.index", new[] { "foo", "bar", "baz" } },
                { "someName[foo]", "42" },
                { "someName[bar]", "100" },
                { "someName[baz]", "200" }
            };
            var bindingContext = GetModelBindingContext(valueProvider);
            var binder = new CollectionModelBinder<int>();

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

            // Assert
            Assert.Equal(new[] { 42, 100, 200 }, ((List<int>)bindingContext.Model).ToArray());
        }
        public async Task BindComplexCollectionFromIndexes_InfiniteIndexes()
        {
            // Arrange
            var valueProvider = new SimpleValueProvider
            {
                { "someName[0]", "42" },
                { "someName[1]", "100" },
                { "someName[3]", "400" }
            };
            var bindingContext = GetModelBindingContext(valueProvider);
            var binder = new CollectionModelBinder<int>(CreateIntBinder());

            // Act
            var boundCollection = await binder.BindComplexCollectionFromIndexes(bindingContext, indexNames: null);

            // Assert
            Assert.Equal(new[] { 42, 100 }, boundCollection.Model.ToArray());

            // This uses the default IValidationStrategy
            Assert.DoesNotContain(boundCollection, bindingContext.ValidationState.Keys);
        }
Exemple #6
0
        public async Task BindComplexCollectionFromIndexes_InfiniteIndexes()
        {
            // Arrange
            var valueProvider = new SimpleValueProvider
            {
                { "someName[0]", "42" },
                { "someName[1]", "100" },
                { "someName[3]", "400" }
            };
            var bindingContext = GetModelBindingContext(valueProvider);
            var binder         = new CollectionModelBinder <int>();

            // Act
            var boundCollection = await binder.BindComplexCollectionFromIndexes(bindingContext, indexNames : null);

            // Assert
            Assert.Equal(new[] { 42, 100 }, boundCollection.Model.ToArray());

            // This uses the default IValidationStrategy
            Assert.DoesNotContain(boundCollection, bindingContext.ValidationState.Keys);
        }
    public async Task CollectionModelBinder_CreatesEmptyCollectionAndAddsError_IfIsTopLevelObject()
    {
        // Arrange
        var binder = new CollectionModelBinder <string>(
            new StubModelBinder(result: ModelBindingResult.Failed()),
            NullLoggerFactory.Instance,
            allowValidatingTopLevelNodes: true);

        var bindingContext = CreateContext();

        bindingContext.IsTopLevelObject = true;
        bindingContext.FieldName        = "fieldName";
        bindingContext.ModelName        = "modelName";

        var metadataProvider = new TestModelMetadataProvider();
        var parameter        = typeof(CollectionModelBinderTest)
                               .GetMethod(nameof(ActionWithListParameter), BindingFlags.Instance | BindingFlags.NonPublic)
                               .GetParameters()[0];

        metadataProvider
        .ForParameter(parameter)
        .BindingDetails(b => b.IsBindingRequired = true);
        bindingContext.ModelMetadata             = metadataProvider.GetMetadataForParameter(parameter);

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

        // Act
        await binder.BindModelAsync(bindingContext);

        // Assert
        Assert.Empty(Assert.IsType <List <string> >(bindingContext.Result.Model));
        Assert.True(bindingContext.Result.IsModelSet);

        var keyValuePair = Assert.Single(bindingContext.ModelState);

        Assert.Equal("modelName", keyValuePair.Key);
        var error = Assert.Single(keyValuePair.Value.Errors);

        Assert.Equal("A value for the 'fieldName' parameter or property was not provided.", error.ErrorMessage);
    }
        public async Task BindModel_SimpleCollection_Succeeds(bool isReadOnly)
        {
            // Arrange
            var valueProvider = new SimpleValueProvider
            {
                { "someName", new[] { "42", "100", "200" } }
            };
            var bindingContext = GetModelBindingContext(valueProvider, isReadOnly);
            var modelState     = bindingContext.ModelState;
            var binder         = new CollectionModelBinder <int>();

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

            // Assert
            Assert.NotEqual(ModelBindingResult.NoResult, result);
            Assert.True(result.IsModelSet);

            var list = Assert.IsAssignableFrom <IList <int> >(result.Model);

            Assert.Equal(new[] { 42, 100, 200 }, list.ToArray());
        }
Exemple #9
0
        public void BindModel_ComplexCollection()
        {
            // Arrange
            ControllerContext             controllerContext = new ControllerContext();
            CultureInfo                   culture           = CultureInfo.GetCultureInfo("fr-FR");
            ExtensibleModelBindingContext bindingContext    = new ExtensibleModelBindingContext
            {
                ModelMetadata        = new EmptyModelMetadataProvider().GetMetadataForType(null, typeof(int)),
                ModelName            = "someName",
                ModelBinderProviders = new ModelBinderProviderCollection(),
                ValueProvider        = new SimpleValueProvider
                {
                    { "someName.index", new[] { "foo", "bar", "baz" } },
                    { "someName[foo]", "42" },
                    { "someName[bar]", "100" },
                    { "someName[baz]", "200" }
                }
            };

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

            mockIntBinder
            .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(int), mockIntBinder.Object, true /* suppressPrefixCheck */);

            CollectionModelBinder <int> modelBinder = new CollectionModelBinder <int>();

            // Act
            bool retVal = modelBinder.BindModel(controllerContext, bindingContext);

            // Assert
            Assert.Equal(new[] { 42, 100, 200 }, ((List <int>)bindingContext.Model).ToArray());
        }
    public async Task BindSimpleCollection_SubBindingSucceeds()
    {
        // Arrange
        var culture        = new CultureInfo("fr-FR");
        var bindingContext = GetModelBindingContext(new SimpleValueProvider());

        var elementBinder = new StubModelBinder(mbc =>
        {
            Assert.Equal("someName", mbc.ModelName);
            mbc.Result = ModelBindingResult.Success(42);
        });

        var modelBinder = new CollectionModelBinder <int>(elementBinder, NullLoggerFactory.Instance);

        // Act
        var boundCollection = await modelBinder.BindSimpleCollection(
            bindingContext,
            new ValueProviderResult(new string[] { "0" }));

        // Assert
        Assert.Equal(new[] { 42 }, boundCollection.Model.ToArray());
    }
        public void BindModel_ComplexCollection()
        {
            // Arrange
            CultureInfo         culture        = CultureInfo.GetCultureInfo("fr-FR");
            Mock <IModelBinder> mockIntBinder  = new Mock <IModelBinder>();
            ModelBindingContext bindingContext = new ModelBindingContext
            {
                ModelMetadata = new EmptyModelMetadataProvider().GetMetadataForType(null, typeof(int)),
                ModelName     = "someName",
                ValueProvider = new SimpleHttpValueProvider
                {
                    { "someName.index", new[] { "foo", "bar", "baz" } },
                    { "someName[foo]", "42" },
                    { "someName[bar]", "100" },
                    { "someName[baz]", "200" }
                }
            };

            HttpActionContext context = ContextUtil.CreateActionContext();

            context.ControllerContext.Configuration.Services.Replace(typeof(ModelBinderProvider), new SimpleModelBinderProvider(typeof(int), mockIntBinder.Object));

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

            CollectionModelBinder <int> modelBinder = new CollectionModelBinder <int>();

            // Act
            bool retVal = modelBinder.BindModel(context, bindingContext);

            // Assert
            Assert.Equal(new[] { 42, 100, 200 }, ((List <int>)bindingContext.Model).ToArray());
        }
        public async Task CollectionModelBinder_DoesNotCreateCollection_IfNotIsTopLevelObject(string prefix)
        {
            // Arrange
            var binder = new CollectionModelBinder <string>();

            var context = CreateContext();

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

            var metadataProvider = context.OperationBindingContext.MetadataProvider;

            context.ModelMetadata = metadataProvider.GetMetadataForProperty(
                typeof(ModelWithListProperty),
                nameof(ModelWithListProperty.ListProperty));

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

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

            // Assert
            Assert.Equal(ModelBindingResult.NoResult, result);
        }
        public async Task BindSimpleCollection_SubBindingSucceeds()
        {
            // Arrange
            var culture        = new CultureInfo("fr-FR");
            var bindingContext = GetModelBindingContext(new SimpleValueProvider());

            Mock.Get <IModelBinder>(bindingContext.OperationBindingContext.ModelBinder)
            .Setup(o => o.BindModelAsync(It.IsAny <ModelBindingContext>()))
            .Returns((ModelBindingContext mbc) =>
            {
                Assert.Equal("someName", mbc.ModelName);
                return(ModelBindingResult.SuccessAsync(mbc.ModelName, 42));
            });
            var modelBinder = new CollectionModelBinder <int>();

            // Act
            var boundCollection = await modelBinder.BindSimpleCollection(
                bindingContext,
                new ValueProviderResult(new string[] { "0" }));

            // Assert
            Assert.Equal(new[] { 42 }, boundCollection.Model.ToArray());
        }
        public async Task BindModelAsync_SimpleCollectionWithNullValue_Succeeds()
        {
            // Arrange
            var binder        = new CollectionModelBinder <int>();
            var valueProvider = new SimpleValueProvider
            {
                { "someName", null },
            };
            var bindingContext = GetModelBindingContext(valueProvider, isReadOnly: false);
            var modelState     = bindingContext.ModelState;

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

            // Assert
            Assert.NotEqual(ModelBindingResult.NoResult, result);
            Assert.True(result.IsModelSet);
            Assert.NotNull(result.Model);

            var model = Assert.IsType <List <int> >(result.Model);

            Assert.Empty(model);
        }
        public async Task BindComplexCollectionFromIndexes_FiniteIndexes()
        {
            // Arrange
            var valueProvider = new SimpleValueProvider
            {
                { "someName[foo]", "42" },
                { "someName[baz]", "200" }
            };
            var bindingContext = GetModelBindingContext(valueProvider);
            var binder = new CollectionModelBinder<int>(CreateIntBinder());

            // Act
            var collectionResult = await binder.BindComplexCollectionFromIndexes(
                bindingContext,
                new[] { "foo", "bar", "baz" });

            // Assert
            Assert.Equal(new[] { 42, 0, 200 }, collectionResult.Model.ToArray());

            // This requires a non-default IValidationStrategy
            var strategy = Assert.IsType<ExplicitIndexCollectionValidationStrategy>(collectionResult.ValidationStrategy);
            Assert.Equal(new[] { "foo", "bar", "baz" }, strategy.ElementKeys);
        }
    public async Task BindModel_SimpleCollection_BindingContextModelNonNull_Succeeds(bool isReadOnly)
    {
        // Arrange
        var valueProvider = new SimpleValueProvider
        {
            { "someName", new[] { "42", "100", "200" } }
        };
        var bindingContext = GetModelBindingContext(valueProvider, isReadOnly);
        var modelState     = bindingContext.ModelState;
        var list           = new List <int>();

        bindingContext.Model = list;
        var binder = new CollectionModelBinder <int>(CreateIntBinder(), NullLoggerFactory.Instance);

        // Act
        await binder.BindModelAsync(bindingContext);

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

        Assert.Same(list, bindingContext.Result.Model);
        Assert.Equal(new[] { 42, 100, 200 }, list.ToArray());
    }
Exemple #17
0
        public void BindComplexCollectionFromIndexes_InfiniteIndexes()
        {
            // Arrange
            ControllerContext             controllerContext = new ControllerContext();
            CultureInfo                   culture           = CultureInfo.GetCultureInfo("fr-FR");
            ExtensibleModelBindingContext bindingContext    = new ExtensibleModelBindingContext
            {
                ModelMetadata        = new EmptyModelMetadataProvider().GetMetadataForType(null, typeof(int)),
                ModelName            = "someName",
                ModelBinderProviders = new ModelBinderProviderCollection(),
                ValueProvider        = new SimpleValueProvider
                {
                    { "someName[0]", "42" },
                    { "someName[1]", "100" },
                    { "someName[3]", "400" }
                }
            };

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

            mockIntBinder
            .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(int), mockIntBinder.Object, false /* suppressPrefixCheck */);

            // Act
            List <int> boundCollection = CollectionModelBinder <int> .BindComplexCollectionFromIndexes(controllerContext, bindingContext, null /* indexNames */);

            // Assert
            Assert.Equal(new[] { 42, 100 }, boundCollection.ToArray());
            Assert.Equal(new[] { "someName[0]", "someName[1]" }, bindingContext.ValidationNode.ChildNodes.Select(o => o.ModelStateKey).ToArray());
        }
        public async Task CollectionModelBinder_DoesNotCreateEmptyCollection_IfModelNonNull()
        {
            // Arrange
            var binder = new CollectionModelBinder <string>();

            var context = CreateContext();

            context.IsTopLevelObject = true;

            var list = new List <string>();

            context.Model = list;

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

            var metadataProvider = context.OperationBindingContext.MetadataProvider;

            context.ModelMetadata = metadataProvider.GetMetadataForType(typeof(List <string>));

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

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

            // Assert
            Assert.NotNull(result);

            Assert.Same(list, result.Model);
            Assert.Empty(list);
            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);
        }
    public async Task CollectionModelBinder_CreatesEmptyCollection_IfIsTopLevelObject(
        bool allowValidatingTopLevelNodes,
        bool isBindingRequired)
    {
        // Arrange
        var binder = new CollectionModelBinder <string>(
            new StubModelBinder(result: ModelBindingResult.Failed()),
            NullLoggerFactory.Instance,
            allowValidatingTopLevelNodes);

        var bindingContext = CreateContext();

        bindingContext.IsTopLevelObject = true;

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

        var metadataProvider = new TestModelMetadataProvider();
        var parameter        = typeof(CollectionModelBinderTest)
                               .GetMethod(nameof(ActionWithListParameter), BindingFlags.Instance | BindingFlags.NonPublic)
                               .GetParameters()[0];

        metadataProvider
        .ForParameter(parameter)
        .BindingDetails(b => b.IsBindingRequired = isBindingRequired);
        bindingContext.ModelMetadata             = metadataProvider.GetMetadataForParameter(parameter);

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

        // Act
        await binder.BindModelAsync(bindingContext);

        // Assert
        Assert.Empty(Assert.IsType <List <string> >(bindingContext.Result.Model));
        Assert.True(bindingContext.Result.IsModelSet);
        Assert.Equal(0, bindingContext.ModelState.ErrorCount);
    }
        public void BindComplexCollectionFromIndexes_InfiniteIndexes()
        {
            // Arrange
            CultureInfo         culture        = CultureInfo.GetCultureInfo("fr-FR");
            Mock <IModelBinder> mockIntBinder  = new Mock <IModelBinder>();
            ModelBindingContext bindingContext = new ModelBindingContext
            {
                ModelMetadata = new EmptyModelMetadataProvider().GetMetadataForType(null, typeof(int)),
                ModelName     = "someName",
                ValueProvider = new SimpleHttpValueProvider
                {
                    { "someName[0]", "42" },
                    { "someName[1]", "100" },
                    { "someName[3]", "400" }
                }
            };

            HttpActionContext context = ContextUtil.CreateActionContext();

            context.ControllerContext.Configuration.Services.Replace(typeof(ModelBinderProvider), new SimpleModelBinderProvider(typeof(int), mockIntBinder.Object));

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

            // Act
            List <int> boundCollection = CollectionModelBinder <int> .BindComplexCollectionFromIndexes(context, bindingContext, null /* indexNames */);

            // Assert
            Assert.Equal(new[] { 42, 100 }, boundCollection.ToArray());
            Assert.Equal(new[] { "someName[0]", "someName[1]" }, bindingContext.ValidationNode.ChildNodes.Select(o => o.ModelStateKey).ToArray());
        }
        public void BindModel_SimpleCollection()
        {
            // Arrange
            ControllerContext             controllerContext = new ControllerContext();
            CultureInfo                   culture           = CultureInfo.GetCultureInfo("fr-FR");
            ExtensibleModelBindingContext bindingContext    = new ExtensibleModelBindingContext()
            {
                ModelMetadata        = new EmptyModelMetadataProvider().GetMetadataForType(null, typeof(int)),
                ModelName            = "someName",
                ModelBinderProviders = new ModelBinderProviderCollection(),
                ValueProvider        = new SimpleValueProvider()
                {
                    { "someName", new string[] { "42", "100", "200" } }
                }
            };

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

            mockIntBinder
            .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(int), mockIntBinder.Object, true /* suppressPrefixCheck */);

            CollectionModelBinder <int> modelBinder = new CollectionModelBinder <int>();

            // Act
            bool retVal = modelBinder.BindModel(controllerContext, bindingContext);

            // Assert
            Assert.IsTrue(retVal);
            CollectionAssert.AreEqual(new int[] { 42, 100, 200 }, bindingContext.Model as ICollection);
        }
Exemple #22
0
        public async Task BindSimpleCollection_SubBindingSucceeds()
        {
            // Arrange
            var culture        = new CultureInfo("fr-FR");
            var bindingContext = GetModelBindingContext(new SimpleHttpValueProvider());
            ModelValidationNode childValidationNode = null;

            Mock.Get <IModelBinder>(bindingContext.OperationBindingContext.ModelBinder)
            .Setup(o => o.BindModelAsync(It.IsAny <ModelBindingContext>()))
            .Returns((ModelBindingContext mbc) =>
            {
                Assert.Equal("someName", mbc.ModelName);
                childValidationNode = new ModelValidationNode("someName", mbc.ModelMetadata, mbc.Model);
                return(Task.FromResult(new ModelBindingResult(42, mbc.ModelName, true, childValidationNode)));
            });
            var modelBinder = new CollectionModelBinder <int>();

            // Act
            var boundCollection = await modelBinder.BindSimpleCollection(bindingContext, new int[1], culture);

            // Assert
            Assert.Equal(new[] { 42 }, boundCollection.Model.ToArray());
            Assert.Equal(new[] { childValidationNode }, boundCollection.ValidationNode.ChildNodes.ToArray());
        }
    public async Task BindComplexCollectionFromIndexes_FiniteIndexes()
    {
        // Arrange
        var valueProvider = new SimpleValueProvider
        {
            { "someName[foo]", "42" },
            { "someName[baz]", "200" }
        };
        var bindingContext = GetModelBindingContext(valueProvider);
        var binder         = new CollectionModelBinder <int>(CreateIntBinder(), NullLoggerFactory.Instance);

        // Act
        var collectionResult = await binder.BindComplexCollectionFromIndexes(
            bindingContext,
            new[] { "foo", "bar", "baz" });

        // Assert
        Assert.Equal(new[] { 42, 0, 200 }, collectionResult.Model.ToArray());

        // This requires a non-default IValidationStrategy
        var strategy = Assert.IsType <ExplicitIndexCollectionValidationStrategy>(collectionResult.ValidationStrategy);

        Assert.Equal(new[] { "foo", "bar", "baz" }, strategy.ElementKeys);
    }
        public async Task CollectionModelBinder_DoesNotCreateCollection_ForNonTopLevelModel(string prefix)
        {
            // Arrange
            var binder = new CollectionModelBinder<string>();

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

            var metadataProvider = context.OperationBindingContext.MetadataProvider;
            context.ModelMetadata = metadataProvider.GetMetadataForProperty(
                typeof(ModelWithListProperty),
                nameof(ModelWithListProperty.ListProperty));

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

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

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

            var context = CreateContext();
            context.ModelName = "prefix";
            context.BinderModelName = "prefix";

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

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

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

            // Assert
            Assert.NotNull(result);

            Assert.Empty(Assert.IsType<List<string>>(result.Model));
            Assert.Equal("prefix", 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);
        }
        public async Task CollectionModelBinder_DoesNotCreateCollection_ForTopLevelModel_OnFirstPass()
        {
            // Arrange
            var binder = new CollectionModelBinder<string>();

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

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

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

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

            // Assert
            Assert.Null(result);
        }
        public async Task BindModel_SimpleCollection()
        {
            // Arrange
            var valueProvider = new SimpleHttpValueProvider
            {
                { "someName", new[] { "42", "100", "200" } }
            };
            var bindingContext = GetModelBindingContext(valueProvider);
            var binder = new CollectionModelBinder<int>();

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

            // Assert
            Assert.True(retVal);
            Assert.Equal(new[] { 42, 100, 200 }, ((List<int>)bindingContext.Model).ToArray());
        }
        public async Task BindSimpleCollection_RawValueIsEmptyCollection_ReturnsEmptyList()
        {
            // Arrange
            var binder = new CollectionModelBinder<int>(CreateIntBinder());
            var context = GetModelBindingContext(new SimpleValueProvider());

            // Act
            var boundCollection = await binder.BindSimpleCollection(context, new ValueProviderResult(new string[0]));

            // Assert
            Assert.NotNull(boundCollection.Model);
            Assert.Empty(boundCollection.Model);
        }
        public void BindModel_ComplexCollection() {
            // Arrange
            ControllerContext controllerContext = new ControllerContext();
            CultureInfo culture = CultureInfo.GetCultureInfo("fr-FR");
            ExtensibleModelBindingContext bindingContext = new ExtensibleModelBindingContext() {
                ModelMetadata = new EmptyModelMetadataProvider().GetMetadataForType(null, typeof(int)),
                ModelName = "someName",
                ModelBinderProviders = new ModelBinderProviderCollection(),
                ValueProvider = new SimpleValueProvider() {
                    { "someName.index", new string[] { "foo", "bar", "baz" } },
                    { "someName[foo]", "42" },
                    { "someName[bar]", "100" },
                    { "someName[baz]", "200" }
                }
            };

            Mock<IExtensibleModelBinder> mockIntBinder = new Mock<IExtensibleModelBinder>();
            mockIntBinder
                .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(int), mockIntBinder.Object, true /* suppressPrefixCheck */);

            CollectionModelBinder<int> modelBinder = new CollectionModelBinder<int>();

            // Act
            bool retVal = modelBinder.BindModel(controllerContext, bindingContext);

            // Assert
            CollectionAssert.AreEqual(new int[] { 42, 100, 200 }, bindingContext.Model as ICollection);
        }
        public void BindingListsWithIndex_ProducesSingleLengthCollection_WithNullValues()
        {
            // Arrange
            string propertyName = "Addresses";
            ModelMetadata modelMetadata = new EmptyModelMetadataProvider().GetMetadataForProperty(
                                                            modelAccessor: null,
                                                            containerType: typeof(UserWithAddress),
                                                            propertyName: propertyName);
            ModelBindingContext bindingContext = new ModelBindingContext
            {
                ModelMetadata = modelMetadata,
                ModelName = propertyName,
                ValueProvider = new SimpleHttpValueProvider { { "Addresses.index", "10000" } }
            };
            HttpActionContext context = ContextUtil.CreateActionContext();
            CollectionModelBinder<UserWithAddress> binder = new CollectionModelBinder<UserWithAddress>();

            // Act
            bool result = binder.BindModel(context, bindingContext);

            // Assert
            Assert.True(result);
            List<UserWithAddress> boundModel = Assert.IsType<List<UserWithAddress>>(bindingContext.Model);
            UserWithAddress listModel = Assert.Single(boundModel);
            Assert.Null(listModel);
        }
        public void BindingUnboundedCollection_WithRecursiveRelation_ProducesSingleLengthCollection()
        {
            // Arrange
            string propertyName = "People";
            ModelMetadata modelMetadata = new EmptyModelMetadataProvider().GetMetadataForProperty(
                                                            modelAccessor: null,
                                                            containerType: typeof(PeopleModel),
                                                            propertyName: propertyName);
            ModelBindingContext bindingContext = new ModelBindingContext
            {
                ModelMetadata = modelMetadata,
                ModelName = propertyName,
                ValueProvider = new SimpleHttpValueProvider { { propertyName, "test value" } }
            };
            HttpActionContext context = ContextUtil.CreateActionContext();
            CollectionModelBinder<Person> binder =
                new CollectionModelBinder<Person>();

            // Act
            bool result = binder.BindModel(context, bindingContext);

            // Assert
            Assert.True(result);
            List<Person> boundModel =
                Assert.IsType<List<Person>>(bindingContext.Model);
            Person type = Assert.Single(boundModel);
            Assert.Null(type.Name);
        }
        public async Task CollectionModelBinder_DoesNotCreateCollection_IfNotIsTopLevelObject(string prefix)
        {
            // Arrange
            var binder = new CollectionModelBinder<string>(new StubModelBinder(result: ModelBindingResult.Failed()));

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

            var metadataProvider = new TestModelMetadataProvider();
            bindingContext.ModelMetadata = metadataProvider.GetMetadataForProperty(
                typeof(ModelWithListProperty),
                nameof(ModelWithListProperty.ListProperty));

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

            // Act
            await binder.BindModelAsync(bindingContext);

            // Assert
            Assert.False(bindingContext.Result.IsModelSet);
        }
        public void BindModel_ComplexCollection()
        {
            // Arrange
            CultureInfo culture = CultureInfo.GetCultureInfo("fr-FR");
            Mock<IModelBinder> mockIntBinder = new Mock<IModelBinder>();
            ModelBindingContext bindingContext = new ModelBindingContext
            {
                ModelMetadata = new EmptyModelMetadataProvider().GetMetadataForType(null, typeof(int)),
                ModelName = "someName",
                ValueProvider = new SimpleHttpValueProvider
                {
                    { "someName.index", new[] { "foo", "bar", "baz" } },
                    { "someName[foo]", "42" },
                    { "someName[bar]", "100" },
                    { "someName[baz]", "200" }
                }
            };

            HttpActionContext context = ContextUtil.CreateActionContext();
            context.ControllerContext.Configuration.Services.Replace(typeof(ModelBinderProvider), new SimpleModelBinderProvider(typeof(int), mockIntBinder.Object));

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

            CollectionModelBinder<int> modelBinder = new CollectionModelBinder<int>();

            // Act
            bool retVal = modelBinder.BindModel(context, bindingContext);

            // Assert
            Assert.Equal(new[] { 42, 100, 200 }, ((List<int>)bindingContext.Model).ToArray());
        }
        public async Task CollectionModelBinder_DoesNotCreateCollection_IfIsTopLevelObjectAndIsFirstChanceBinding()
        {
            // Arrange
            var binder = new CollectionModelBinder<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(List<string>));

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

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

            // Assert
            Assert.Null(result);
        }
        public async Task BindSimpleCollection_SubBindingSucceeds()
        {
            // Arrange
            var culture = new CultureInfo("fr-FR");
            var bindingContext = GetModelBindingContext(new SimpleHttpValueProvider());
            ModelValidationNode childValidationNode = null;
            Mock.Get<IModelBinder>(bindingContext.OperationBindingContext.ModelBinder)
                .Setup(o => o.BindModelAsync(It.IsAny<ModelBindingContext>()))
                .Returns((ModelBindingContext mbc) =>
                {
                    Assert.Equal("someName", mbc.ModelName);
                    childValidationNode = new ModelValidationNode("someName", mbc.ModelMetadata, mbc.Model);
                    return Task.FromResult(new ModelBindingResult(42, mbc.ModelName, true, childValidationNode));
                });
            var modelBinder = new CollectionModelBinder<int>();

            // Act
            var boundCollection = await modelBinder.BindSimpleCollection(bindingContext, new int[1], culture);

            // Assert
            Assert.Equal(new[] { 42 }, boundCollection.Model.ToArray());
            Assert.Equal(new[] { childValidationNode }, boundCollection.ValidationNode.ChildNodes.ToArray());
        }
        public async Task CollectionModelBinder_DoesNotCreateEmptyCollection_IfModelNonNull()
        {
            // Arrange
            var binder = new CollectionModelBinder<string>(new StubModelBinder(result: ModelBindingResult.Failed()));

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

            var list = new List<string>();
            bindingContext.Model = list;

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

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

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

            // Act
            await binder.BindModelAsync(bindingContext);

            // Assert
            Assert.Same(list, bindingContext.Result.Model);
            Assert.Empty(list);
            Assert.True(bindingContext.Result.IsModelSet);
        }
        public void CanCreateInstance_ReturnsExpectedValue(Type modelType, bool expectedResult)
        {
            // Arrange
            var binder = new CollectionModelBinder<int>(CreateIntBinder());

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

            // Assert
            Assert.Equal(expectedResult, result);
        }
        public void BindingNestedUnboundedCollection_WhenNoValuesArePresent_ProducesEmptyCollection()
        {
            // Arrange
            string propertyName = "Addresses";
            ModelMetadata modelMetadata = new EmptyModelMetadataProvider().GetMetadataForProperty(
                                                            modelAccessor: null,
                                                            containerType: typeof(UserWithAddress),
                                                            propertyName: propertyName);
            ModelBindingContext bindingContext = new ModelBindingContext
            {
                ModelMetadata = modelMetadata,
                ModelName = propertyName,
                ValueProvider = new SimpleHttpValueProvider { { "Addresses.AddressLines", "some value" } }
            };
            HttpActionContext context = ContextUtil.CreateActionContext();
            CollectionModelBinder<UserWithAddress> binder = new CollectionModelBinder<UserWithAddress>();

            // Act
            bool result = binder.BindModel(context, bindingContext);

            // Assert
            Assert.True(result);
            List<UserWithAddress> boundModel = Assert.IsType<List<UserWithAddress>>(bindingContext.Model);
            Assert.Empty(boundModel);
        }
        public async Task BindSimpleCollection_SubBindingSucceeds()
        {
            // Arrange
            var culture = new CultureInfo("fr-FR");
            var bindingContext = GetModelBindingContext(new SimpleValueProvider());

            var elementBinder = new StubModelBinder(mbc =>
            {
                Assert.Equal("someName", mbc.ModelName);
                mbc.Result = ModelBindingResult.Success(42);
            });

            var modelBinder = new CollectionModelBinder<int>(elementBinder);

            // Act
            var boundCollection = await modelBinder.BindSimpleCollection(
                bindingContext,
                new ValueProviderResult(new string[] { "0" }));

            // Assert
            Assert.Equal(new[] { 42 }, boundCollection.Model.ToArray());
        }
        public async Task BindSimpleCollection_RawValueIsEmptyCollection_ReturnsEmptyList()
        {
            // Arrange
            var binder = new CollectionModelBinder<int>();

            var context = new ModelBindingContext()
            {
                OperationBindingContext = new OperationBindingContext()
                {
                    MetadataProvider = TestModelMetadataProvider.CreateDefaultProvider(),
                },
            };

            // Act
            var boundCollection = await binder.BindSimpleCollection(context, rawValue: new object[0], culture: null);

            // Assert
            Assert.NotNull(boundCollection.Model);
            Assert.Empty(boundCollection.Model);
        }
        public async Task BindSimpleCollection_RawValueIsNull_ReturnsNull()
        {
            // Arrange
            var binder = new CollectionModelBinder<int>();

            // Act
            var boundCollection = await binder.BindSimpleCollection(bindingContext: null, rawValue: null, culture: null);

            // Assert
            Assert.Null(boundCollection);
        }
        public async Task BindSimpleCollection_RawValueIsEmptyCollection_ReturnsEmptyList()
        {
            // Arrange
            var binder = new CollectionModelBinder<int>();

            // Act
            var boundCollection = await binder.BindSimpleCollection(bindingContext: null, rawValue: new object[0], culture: null);

            // Assert
            Assert.NotNull(boundCollection);
            Assert.Empty(boundCollection);
        }
        public async Task CollectionModelBinder_CreatesEmptyCollection_IfIsTopLevelObjectAndNotIsFirstChanceBinding()
        {
            // Arrange
            var binder = new CollectionModelBinder<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(List<string>));

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

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

            // Assert
            Assert.NotNull(result);

            Assert.Empty(Assert.IsType<List<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);
        }
        public async Task BindModelAsync_SimpleCollectionWithNullValue_Succeeds()
        {
            // Arrange
            var binder = new CollectionModelBinder<int>(CreateIntBinder());
            var valueProvider = new SimpleValueProvider
            {
                { "someName", null },
            };
            var bindingContext = GetModelBindingContext(valueProvider, isReadOnly: false);

            // Act
            await binder.BindModelAsync(bindingContext);

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

            var model = Assert.IsType<List<int>>(bindingContext.Result.Model);
            Assert.Empty(model);
        }
        public async Task BindModel_SimpleCollection_BindingContextModelNonNull_Succeeds(bool isReadOnly)
        {
            // Arrange
            var valueProvider = new SimpleHttpValueProvider
            {
                { "someName", new[] { "42", "100", "200" } }
            };
            var bindingContext = GetModelBindingContext(valueProvider, isReadOnly);
            var modelState = bindingContext.ModelState;
            var list = new List<int>();
            bindingContext.Model = list;
            var binder = new CollectionModelBinder<int>();

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

            // Assert
            Assert.NotNull(result);
            Assert.True(result.IsModelSet);

            Assert.Same(list, result.Model);
            Assert.Equal(new[] { 42, 100, 200 }, list.ToArray());

            Assert.True(modelState.IsValid);
        }
        public void BindModel_SimpleCollection()
        {
            // Arrange
            ControllerContext controllerContext = new ControllerContext();
            CultureInfo culture = CultureInfo.GetCultureInfo("fr-FR");
            ExtensibleModelBindingContext bindingContext = new ExtensibleModelBindingContext
            {
                ModelMetadata = new EmptyModelMetadataProvider().GetMetadataForType(null, typeof(int)),
                ModelName = "someName",
                ModelBinderProviders = new ModelBinderProviderCollection(),
                ValueProvider = new SimpleValueProvider
                {
                    { "someName", new[] { "42", "100", "200" } }
                }
            };

            Mock<IExtensibleModelBinder> mockIntBinder = new Mock<IExtensibleModelBinder>();
            mockIntBinder
                .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(int), mockIntBinder.Object, true /* suppressPrefixCheck */);

            CollectionModelBinder<int> modelBinder = new CollectionModelBinder<int>();

            // Act
            bool retVal = modelBinder.BindModel(controllerContext, bindingContext);

            // Assert
            Assert.True(retVal);
            Assert.Equal(new[] { 42, 100, 200 }, ((List<int>)bindingContext.Model).ToArray());
        }
        public async Task BindModel_ComplexCollection_BindingContextModelNonNull_Succeeds(bool isReadOnly)
        {
            // Arrange
            var valueProvider = new SimpleValueProvider
            {
                { "someName.index", new[] { "foo", "bar", "baz" } },
                { "someName[foo]", "42" },
                { "someName[bar]", "100" },
                { "someName[baz]", "200" }
            };
            var bindingContext = GetModelBindingContext(valueProvider, isReadOnly);
            var modelState = bindingContext.ModelState;
            var list = new List<int>();
            bindingContext.Model = list;
            var binder = new CollectionModelBinder<int>(CreateIntBinder());

            // Act
            await binder.BindModelAsync(bindingContext);

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

            Assert.Same(list, bindingContext.Result.Model);
            Assert.Equal(new[] { 42, 100, 200 }, list.ToArray());

            Assert.True(modelState.IsValid);
        }