public void CreateOrReplaceCollection_OriginalModelMutable_UpdatesOriginalInstance() { // Arrange List <int> originalInstance = new List <int> { 10, 20, 30 }; ExtensibleModelBindingContext bindingContext = new ExtensibleModelBindingContext { ModelMetadata = new EmptyModelMetadataProvider().GetMetadataForType( () => originalInstance, typeof(ICollection <int>) ) }; // Act CollectionModelBinderUtil.CreateOrReplaceCollection( bindingContext, new[] { 40, 50, 60 }, () => new List <int>() ); // Assert Assert.Same(originalInstance, bindingContext.Model); Assert.Equal(new[] { 40, 50, 60 }, originalInstance.ToArray()); }
public void CreateOrReplaceDictionary_OriginalModelMutable_UpdatesOriginalInstance() { // Arrange Dictionary <string, string> originalInstance = new Dictionary <string, string> { { "dog", "Canidae" }, { "cat", "Felidae" } }; ExtensibleModelBindingContext bindingContext = new ExtensibleModelBindingContext { ModelMetadata = new EmptyModelMetadataProvider().GetMetadataForType(() => originalInstance, typeof(IDictionary <string, string>)) }; // Act CollectionModelBinderUtil.CreateOrReplaceDictionary( bindingContext, new Dictionary <string, string> { { "horse", "Equidae" }, { "bear", "Ursidae" } }, () => new Dictionary <string, string>()); // Assert Assert.Same(originalInstance, bindingContext.Model); Assert.Equal(new[] { "horse", "bear" }, originalInstance.Keys.ToArray()); Assert.Equal("Equidae", originalInstance["horse"]); Assert.Equal("Ursidae", originalInstance["bear"]); }
public void CreateOrReplaceDictionary_OriginalModelNotDictionary_CreatesNewInstance() { // Arrange ExtensibleModelBindingContext bindingContext = new ExtensibleModelBindingContext { ModelMetadata = new EmptyModelMetadataProvider().GetMetadataForType(null, typeof(IDictionary <string, string>)) }; // Act CollectionModelBinderUtil.CreateOrReplaceDictionary( bindingContext, new Dictionary <string, string> { { "horse", "Equidae" }, { "bear", "Ursidae" } }, () => new Dictionary <string, string>()); // Assert IDictionary <string, string> newModel = bindingContext.Model as IDictionary <string, string>; Assert.Equal(new[] { "horse", "bear" }, newModel.Keys.ToArray()); Assert.Equal("Equidae", newModel["horse"]); Assert.Equal("Ursidae", newModel["bear"]); }
public void CreateOrReplaceDictionary_DisallowsDuplicateKeys() { // Arrange ExtensibleModelBindingContext bindingContext = new ExtensibleModelBindingContext { ModelMetadata = new EmptyModelMetadataProvider().GetMetadataForType(null, typeof(Dictionary <string, int>)) }; // Act CollectionModelBinderUtil.CreateOrReplaceDictionary( bindingContext, new[] { new KeyValuePair <string, int>("forty-two", 40), new KeyValuePair <string, int>("forty-two", 2), new KeyValuePair <string, int>("forty-two", 42) }, () => new Dictionary <string, int>()); // Assert IDictionary <string, int> newModel = bindingContext.Model as IDictionary <string, int>; Assert.Equal(new[] { "forty-two" }, newModel.Keys.ToArray()); Assert.Equal(42, newModel["forty-two"]); }
public void CreateOrReplaceDictionary_OriginalModelImmutable_CreatesNewInstance() { // Arrange ReadOnlyDictionary <string, string> originalModel = new ReadOnlyDictionary <string, string>(); ExtensibleModelBindingContext bindingContext = new ExtensibleModelBindingContext { ModelMetadata = new EmptyModelMetadataProvider().GetMetadataForType(() => originalModel, typeof(IDictionary <string, string>)) }; // Act CollectionModelBinderUtil.CreateOrReplaceDictionary( bindingContext, new Dictionary <string, string> { { "Hello", "World" } }, () => new Dictionary <string, string>()); // Assert IDictionary <string, string> newModel = bindingContext.Model as IDictionary <string, string>; Assert.NotSame(originalModel, newModel); Assert.Equal(new[] { "Hello" }, newModel.Keys.ToArray()); Assert.Equal("World", newModel["Hello"]); }
public void GetZeroBasedIndexes() { // Act string[] indexes = CollectionModelBinderUtil.GetZeroBasedIndexes().Take(5).ToArray(); // Assert Assert.Equal(new[] { "0", "1", "2", "3", "4" }, indexes); }
// Used when the ValueProvider contains the collection to be bound as multiple elements, e.g. foo[0], foo[1]. private static List <TElement> BindComplexCollection(HttpActionContext actionContext, ModelBindingContext bindingContext) { string indexPropertyName = ModelBindingHelper.CreatePropertyModelName(bindingContext.ModelName, "index"); ValueProviderResult valueProviderResultIndex = bindingContext.ValueProvider.GetValue(indexPropertyName); IEnumerable <string> indexNames = CollectionModelBinderUtil.GetIndexNamesFromValueProviderResult(valueProviderResultIndex); return(BindComplexCollectionFromIndexes(actionContext, bindingContext, indexNames)); }
public void GetIndexNamesFromValueProviderResult_ValueProviderResultIsNull_ReturnsNull() { // Act IEnumerable <string> indexNames = CollectionModelBinderUtil.GetIndexNamesFromValueProviderResult(null); // Assert Assert.Null(indexNames); }
internal static List <TElement> BindComplexCollectionFromIndexes( HttpActionContext actionContext, ModelBindingContext bindingContext, IEnumerable <string> indexNames ) { bool indexNamesIsFinite; if (indexNames != null) { indexNamesIsFinite = true; } else { indexNamesIsFinite = false; indexNames = CollectionModelBinderUtil.GetZeroBasedIndexes(); } List <TElement> boundCollection = new List <TElement>(); foreach (string indexName in indexNames) { string fullChildName = ModelBindingHelper.CreateIndexModelName( bindingContext.ModelName, indexName ); ModelBindingContext childBindingContext = new ModelBindingContext(bindingContext) { ModelMetadata = actionContext .GetMetadataProvider() .GetMetadataForType(null, typeof(TElement)), ModelName = fullChildName }; bool didBind = false; object boundValue = null; if (actionContext.Bind(childBindingContext)) { didBind = true; boundValue = childBindingContext.Model; // merge validation up bindingContext.ValidationNode.ChildNodes.Add( childBindingContext.ValidationNode ); } // infinite size collection stops on first bind failure if (!didBind && !indexNamesIsFinite) { break; } boundCollection.Add(ModelBindingHelper.CastOrDefault <TElement>(boundValue)); } return(boundCollection); }
public override IModelBinder GetBinder(HttpConfiguration configuration, Type modelType) { return(CollectionModelBinderUtil.GetGenericBinder( typeof(IDictionary <,>), typeof(Dictionary <,>), typeof(DictionaryModelBinder <,>), modelType )); }
// Used when the ValueProvider contains the collection to be bound as multiple elements, e.g. foo[0], foo[1]. private async Task <List <TElement> > BindComplexCollection(ModelBindingContext bindingContext) { var indexPropertyName = ModelBindingHelper.CreatePropertyModelName(bindingContext.ModelName, "index"); var valueProviderResultIndex = await bindingContext.ValueProvider.GetValueAsync(indexPropertyName); var indexNames = CollectionModelBinderUtil.GetIndexNamesFromValueProviderResult(valueProviderResultIndex); return(await BindComplexCollectionFromIndexes(bindingContext, indexNames)); }
public override IModelBinder GetBinder(HttpConfiguration configuration, Type modelType) { return(CollectionModelBinderUtil.GetGenericBinder( typeof(ICollection <>), typeof(List <>), typeof(CollectionModelBinder <>), modelType )); }
public void GetTypeArgumentsForUpdatableGenericCollection_ModelTypeOpenGeneric_Fail() { // Arrange ModelMetadata modelMetadata = new EmptyModelMetadataProvider().GetMetadataForType(null, typeof(IList <>)); // Act Type[] typeArguments = CollectionModelBinderUtil.GetTypeArgumentsForUpdatableGenericCollection(null, null, modelMetadata); // Assert Assert.Null(typeArguments); }
public void GetTypeArgumentsForUpdatableGenericCollection_ModelTypeWrongNumberOfGenericArguments_Fail() { // Arrange ModelMetadata modelMetadata = new EmptyModelMetadataProvider().GetMetadataForType(null, typeof(KeyValuePair <int, string>)); // Act Type[] typeArguments = CollectionModelBinderUtil.GetTypeArgumentsForUpdatableGenericCollection(typeof(ICollection <>), null, modelMetadata); // Assert Assert.Null(typeArguments); }
public void GetIndexNamesFromValueProviderResult_ValueProviderResultReturnsEmptyArray_ReturnsNull() { // Arrange ValueProviderResult vpResult = new ValueProviderResult(new string[0], "", null); // Act IEnumerable <string> indexNames = CollectionModelBinderUtil.GetIndexNamesFromValueProviderResult(vpResult); // Assert Assert.Null(indexNames); }
public void GetTypeArgumentsForUpdatableGenericCollection_ModelTypeNotGeneric_Fail() { // Arrange ModelMetadata modelMetadata = new EmptyModelMetadataProvider().GetMetadataForType(null, typeof(int)); // Act Type[] typeArguments = CollectionModelBinderUtil.GetTypeArgumentsForUpdatableGenericCollection(null, null, modelMetadata); // Assert Assert.IsNull(typeArguments, "The given model type was not generic."); }
public void GetIndexNamesFromValueProviderResult_ValueProviderResultReturnsNonEmptyArray_ReturnsArray() { // Arrange ValueProviderResult vpResult = new ValueProviderResult(new[] { "foo", "bar", "baz" }, "foo,bar,baz", null); // Act IEnumerable <string> indexNames = CollectionModelBinderUtil.GetIndexNamesFromValueProviderResult(vpResult); // Assert Assert.NotNull(indexNames); Assert.Equal(new[] { "foo", "bar", "baz" }, indexNames.ToArray()); }
public override IModelBinder GetBinder(HttpActionContext actionContext, ModelBindingContext bindingContext) { ModelBindingHelper.ValidateBindingContext(bindingContext); if (bindingContext.ValueProvider.ContainsPrefix(bindingContext.ModelName)) { return(CollectionModelBinderUtil.GetGenericBinder(typeof(ICollection <>), typeof(List <>), typeof(CollectionModelBinder <>), bindingContext.ModelMetadata)); } else { return(null); } }
public void GetTypeArgumentsForUpdatableGenericCollection_ReadWriteReference_NewInstanceAssignableToModelType_Success() { // Arrange ModelMetadata modelMetadata = new EmptyModelMetadataProvider().GetMetadataForType(null, typeof(IList <int>)); modelMetadata.IsReadOnly = false; // Act Type[] typeArguments = CollectionModelBinderUtil.GetTypeArgumentsForUpdatableGenericCollection(typeof(ICollection <>), typeof(List <>), modelMetadata); // Assert CollectionAssert.AreEqual(new Type[] { typeof(int) }, typeArguments, "Mutable reference can be overwritten."); }
public void GetTypeArgumentsForUpdatableGenericCollection_ReadWriteReference_NewInstanceNotAssignableToModelType_MutableInstance_Success() { // Arrange ModelMetadata modelMetadata = new EmptyModelMetadataProvider().GetMetadataForType(() => new Collection <int>(), typeof(Collection <int>)); modelMetadata.IsReadOnly = false; // Act Type[] typeArguments = CollectionModelBinderUtil.GetTypeArgumentsForUpdatableGenericCollection(typeof(ICollection <>), typeof(List <>), modelMetadata); // Assert Assert.Equal(new[] { typeof(int) }, typeArguments); }
public void GetTypeArgumentsForUpdatableGenericCollection_ReadOnlyReference_ModelIsNull_Fail() { // Arrange ModelMetadata modelMetadata = new EmptyModelMetadataProvider().GetMetadataForType(null, typeof(IList <int>)); modelMetadata.IsReadOnly = true; // Act Type[] typeArguments = CollectionModelBinderUtil.GetTypeArgumentsForUpdatableGenericCollection(typeof(ICollection <>), typeof(List <>), modelMetadata); // Assert Assert.Null(typeArguments); }
// Extensibility point that allows the bound collection to be manipulated or transformed before // being returned from the binder. protected virtual bool CreateOrReplaceCollection( HttpActionContext actionContext, ModelBindingContext bindingContext, IList <TElement> newCollection ) { CollectionModelBinderUtil.CreateOrReplaceCollection( bindingContext, newCollection, () => new List <TElement>() ); return(true); }
public void GetTypeArgumentsForUpdatableGenericCollection_ReadOnlyReference_ModelInstanceMutable_Valid() { // Arrange ModelMetadata modelMetadata = new EmptyModelMetadataProvider().GetMetadataForType(() => new List <int>(), typeof(IList <int>)); modelMetadata.IsReadOnly = true; // Act Type[] typeArguments = CollectionModelBinderUtil.GetTypeArgumentsForUpdatableGenericCollection(typeof(IList <>), typeof(List <>), modelMetadata); // Assert Assert.Equal(new[] { typeof(int) }, typeArguments); }
public void GetTypeArgumentsForUpdatableGenericCollection_ReadOnlyReference_ModelInstanceImmutable_Valid() { // Arrange ModelMetadata modelMetadata = new EmptyModelMetadataProvider().GetMetadataForType(() => new int[0], typeof(IList <int>)); modelMetadata.IsReadOnly = true; // Act Type[] typeArguments = CollectionModelBinderUtil.GetTypeArgumentsForUpdatableGenericCollection(typeof(IList <>), typeof(List <>), modelMetadata); // Assert Assert.IsNull(typeArguments, "Collection instance is immutable and reference is readonly."); }
protected override bool CreateOrReplaceCollection( HttpActionContext actionContext, ModelBindingContext bindingContext, IList <KeyValuePair <TKey, TValue> > newCollection ) { CollectionModelBinderUtil.CreateOrReplaceDictionary( bindingContext, newCollection, () => new Dictionary <TKey, TValue>() ); return(true); }
private static Type GetCollectionElementType(Type collectionType) { Contract.Assert(!typeof(IDictionary).IsAssignableFrom(collectionType)); Type elementType = collectionType.GetElementType(); if (elementType == null) { elementType = CollectionModelBinderUtil .GetGenericBinderTypeArgs(typeof(ICollection <>), collectionType) .First(); } return(elementType); }
public void GetTypeArgumentsForUpdatableGenericCollection_ReadOnlyReference_ModelInstanceOfWrongType_Fail() { // Arrange ModelMetadata modelMetadata = new EmptyModelMetadataProvider().GetMetadataForType(() => new HashSet <int>(), typeof(ICollection <int>)); modelMetadata.IsReadOnly = true; // Act Type[] typeArguments = CollectionModelBinderUtil.GetTypeArgumentsForUpdatableGenericCollection(typeof(IList <>), typeof(List <>), modelMetadata); // Assert // HashSet<> is not an IList<>, so we can't update Assert.Null(typeArguments); }
public void CreateOrReplaceCollection_OriginalModelNotCollection_CreatesNewInstance() { // Arrange ExtensibleModelBindingContext bindingContext = new ExtensibleModelBindingContext { ModelMetadata = new EmptyModelMetadataProvider().GetMetadataForType(null, typeof(ICollection <int>)) }; // Act CollectionModelBinderUtil.CreateOrReplaceCollection(bindingContext, new[] { 10, 20, 30 }, () => new List <int>()); // Assert int[] newModel = (bindingContext.Model as ICollection <int>).ToArray(); Assert.Equal(new[] { 10, 20, 30 }, newModel); }
public void CreateOrReplaceCollection_OriginalModelMutable_UpdatesOriginalInstance() { // Arrange List <int> originalInstance = new List <int>() { 10, 20, 30 }; ExtensibleModelBindingContext bindingContext = new ExtensibleModelBindingContext() { ModelMetadata = new EmptyModelMetadataProvider().GetMetadataForType(() => originalInstance, typeof(ICollection <int>)) }; // Act CollectionModelBinderUtil.CreateOrReplaceCollection <int>(bindingContext, new int[] { 40, 50, 60 }, () => new List <int>()); // Assert Assert.AreSame(originalInstance, bindingContext.Model, "Original collection should have been updated."); CollectionAssert.AreEqual(new int[] { 40, 50, 60 }, originalInstance); }