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]); }
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]); }
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]); }
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); }
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); }
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); }
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); }
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); }
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)); }
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); }
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); }
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); }