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 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(), new SimpleTypeModelBinder()); 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.BindModelResultAsync(context); // Assert Assert.NotEqual(default(ModelBindingResult), result); Assert.Empty(Assert.IsType <Dictionary <string, string> >(result.Model)); Assert.Equal("modelName", result.Key); Assert.True(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_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_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(), new SimpleTypeModelBinder()); // Act var result = await binder.BindModelResultAsync(bindingContext); // Assert Assert.True(result.IsModelSet); var dictionary = Assert.IsAssignableFrom <IDictionary <int, string> >(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(result.Model, bindingContext.ValidationState.Keys); }
public async Task BindModel_FallsBackToBindingValues( string modelName, string keyFormat, IDictionary <string, string> dictionary) { // Arrange var binder = new DictionaryModelBinder <string, string>(new SimpleTypeModelBinder(), new SimpleTypeModelBinder()); var context = CreateContext(); context.ModelName = modelName; context.OperationBindingContext.ValueProvider = CreateEnumerableValueProvider(keyFormat, dictionary); context.ValueProvider = context.OperationBindingContext.ValueProvider; context.FieldName = modelName; var metadataProvider = context.OperationBindingContext.MetadataProvider; context.ModelMetadata = metadataProvider.GetMetadataForProperty( typeof(ModelWithDictionaryProperties), nameof(ModelWithDictionaryProperties.DictionaryProperty)); // Act var result = await binder.BindModelResultAsync(context); // Assert Assert.True(result.IsModelSet); Assert.Equal(modelName, result.Key); var resultDictionary = Assert.IsAssignableFrom <IDictionary <string, string> >(result.Model); Assert.Equal(dictionary, resultDictionary); }
public void CanCreateInstance_ReturnsExpectedValue(Type modelType, bool expectedResult) { // Arrange var binder = new DictionaryModelBinder <int, int>(new SimpleTypeModelBinder(), new SimpleTypeModelBinder()); // Act var result = binder.CanCreateInstance(modelType); // Assert Assert.Equal(expectedResult, result); }
public async Task DictionaryModelBinder_CreatesEmptyCollectionAndAddsError_IfIsTopLevelObject() { // Arrange var binder = new DictionaryModelBinder <string, string>( new SimpleTypeModelBinder(typeof(string), NullLoggerFactory.Instance), new SimpleTypeModelBinder(typeof(string), NullLoggerFactory.Instance), NullLoggerFactory.Instance, allowValidatingTopLevelNodes: true); var bindingContext = CreateContext(); bindingContext.IsTopLevelObject = true; bindingContext.FieldName = "fieldName"; bindingContext.ModelName = "modelName"; var metadataProvider = new TestModelMetadataProvider(); var parameter = typeof(DictionaryModelBinderTest) .GetMethod(nameof(ActionWithDictionaryParameter), 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 <Dictionary <string, 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_WithExistingModel_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" }, }; var bindingContext = GetModelBindingContext(isReadOnly, values); bindingContext.ValueProvider = CreateEnumerableValueProvider("{0}", values); var dictionary = new Dictionary <int, string>(); bindingContext.Model = dictionary; var binder = new DictionaryModelBinder <int, string>( new SimpleTypeModelBinder(typeof(int), NullLoggerFactory.Instance), new SimpleTypeModelBinder(typeof(string), NullLoggerFactory.Instance), NullLoggerFactory.Instance); // Act await binder.BindModelAsync(bindingContext); // Assert Assert.True(bindingContext.Result.IsModelSet); Assert.Same(dictionary, 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 DictionaryModelBinder_CreatesEmptyCollection_IfIsTopLevelObject( bool allowValidatingTopLevelNodes, bool isBindingRequired) { // Arrange var expectedErrorCount = isBindingRequired ? 1 : 0; var binder = new DictionaryModelBinder <string, string>( new SimpleTypeModelBinder(typeof(string), NullLoggerFactory.Instance), new SimpleTypeModelBinder(typeof(string), NullLoggerFactory.Instance), 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(DictionaryModelBinderTest) .GetMethod(nameof(ActionWithDictionaryParameter), 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 <Dictionary <string, string> >(bindingContext.Result.Model)); Assert.True(bindingContext.Result.IsModelSet); Assert.Equal(expectedErrorCount, bindingContext.ModelState.ErrorCount); }
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 context = CreateContext(); context.ModelName = "prefix"; context.ValueProvider = CreateTestValueProvider("prefix[{0}]", dictionary); context.FieldName = context.ModelName; var metadataProvider = new TestModelMetadataProvider(); context.ModelMetadata = metadataProvider.GetMetadataForProperty( typeof(ModelWithDictionaryProperties), nameof(ModelWithDictionaryProperties.DictionaryProperty)); // Act var result = await binder.BindModelResultAsync(context); // Assert Assert.NotEqual(default(ModelBindingResult), result); Assert.True(result.IsModelSet); Assert.Equal("prefix", result.Key); var resultDictionary = Assert.IsAssignableFrom <IDictionary <string, string> >(result.Model); Assert.Empty(resultDictionary); }
public async Task DictionaryModelBinder_DoesNotCreateCollection_IfNotIsTopLevelObject(string prefix) { // Arrange var binder = new DictionaryModelBinder <int, int>(new SimpleTypeModelBinder(), new SimpleTypeModelBinder()); var context = CreateContext(); context.ModelName = ModelNames.CreatePropertyModelName(prefix, "ListProperty"); var metadataProvider = context.OperationBindingContext.MetadataProvider; context.ModelMetadata = metadataProvider.GetMetadataForProperty( typeof(ModelWithDictionaryProperties), nameof(ModelWithDictionaryProperties.DictionaryProperty)); context.ValueProvider = new TestValueProvider(new Dictionary <string, object>()); // Act var result = await binder.BindModelResultAsync(context); // Assert Assert.Equal(default(ModelBindingResult), result); }
public async Task DictionaryModelBinder_DoesNotCreateCollection_IfNotIsTopLevelObject( string prefix, bool allowValidatingTopLevelNodes, bool isBindingRequired) { // Arrange var binder = new DictionaryModelBinder <int, int>( new SimpleTypeModelBinder(typeof(int), NullLoggerFactory.Instance), new SimpleTypeModelBinder(typeof(int), NullLoggerFactory.Instance), NullLoggerFactory.Instance, allowValidatingTopLevelNodes); var bindingContext = CreateContext(); bindingContext.ModelName = ModelNames.CreatePropertyModelName(prefix, "ListProperty"); var metadataProvider = new TestModelMetadataProvider(); metadataProvider .ForProperty( typeof(ModelWithDictionaryProperties), nameof(ModelWithDictionaryProperties.DictionaryProperty)) .BindingDetails(b => b.IsBindingRequired = isBindingRequired); 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); Assert.Equal(0, bindingContext.ModelState.ErrorCount); }
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)); }