Imported Upstream version 3.6.0

Former-commit-id: da6be194a6b1221998fc28233f2503bd61dd9d14
This commit is contained in:
Jo Shields
2014-08-13 10:39:27 +01:00
commit a575963da9
50588 changed files with 8155799 additions and 0 deletions

View File

@@ -0,0 +1,102 @@
// Copyright (c) Microsoft Corporation. All rights reserved. See License.txt in the project root for license information.
using System.Collections.Generic;
using System.Web.Http.Metadata.Providers;
using System.Web.Http.Util;
using Xunit;
namespace System.Web.Http.ModelBinding.Binders
{
public class ArrayModelBinderProviderTest
{
[Fact]
public void GetBinder_CorrectModelTypeAndValueProviderEntries_ReturnsBinder()
{
// Arrange
ModelBindingContext bindingContext = new ModelBindingContext
{
ModelMetadata = new EmptyModelMetadataProvider().GetMetadataForType(null, typeof(int[])),
ModelName = "foo",
ValueProvider = new SimpleHttpValueProvider
{
{ "foo[0]", "42" },
}
};
ArrayModelBinderProvider binderProvider = new ArrayModelBinderProvider();
// Act
IModelBinder binder = binderProvider.GetBinder(null, bindingContext);
// Assert
Assert.IsType<ArrayModelBinder<int>>(binder);
}
[Fact]
public void GetBinder_ModelMetadataReturnsReadOnly_ReturnsNull()
{
// Arrange
ModelBindingContext bindingContext = new ModelBindingContext
{
ModelMetadata = new EmptyModelMetadataProvider().GetMetadataForType(null, typeof(int[])),
ModelName = "foo",
ValueProvider = new SimpleHttpValueProvider
{
{ "foo[0]", "42" },
}
};
bindingContext.ModelMetadata.IsReadOnly = true;
ArrayModelBinderProvider binderProvider = new ArrayModelBinderProvider();
// Act
IModelBinder binder = binderProvider.GetBinder(null, bindingContext);
// Assert
Assert.Null(binder);
}
[Fact]
public void GetBinder_ModelTypeIsIncorrect_ReturnsNull()
{
// Arrange
ModelBindingContext bindingContext = new ModelBindingContext
{
ModelMetadata = new EmptyModelMetadataProvider().GetMetadataForType(null, typeof(ICollection<int>)),
ModelName = "foo",
ValueProvider = new SimpleHttpValueProvider
{
{ "foo[0]", "42" },
}
};
ArrayModelBinderProvider binderProvider = new ArrayModelBinderProvider();
// Act
IModelBinder binder = binderProvider.GetBinder(null, bindingContext);
// Assert
Assert.Null(binder);
}
[Fact]
public void GetBinder_ValueProviderDoesNotContainPrefix_ReturnsNull()
{
// Arrange
ModelBindingContext bindingContext = new ModelBindingContext
{
ModelMetadata = new EmptyModelMetadataProvider().GetMetadataForType(null, typeof(int[])),
ModelName = "foo",
ValueProvider = new SimpleHttpValueProvider()
};
ArrayModelBinderProvider binderProvider = new ArrayModelBinderProvider();
// Act
IModelBinder binder = binderProvider.GetBinder(null, bindingContext);
// Assert
Assert.Null(binder);
}
}
}

View File

@@ -0,0 +1,49 @@
// Copyright (c) Microsoft Corporation. All rights reserved. See License.txt in the project root for license information.
using System.Web.Http.Controllers;
using System.Web.Http.Metadata.Providers;
using System.Web.Http.Util;
using Moq;
using Xunit;
namespace System.Web.Http.ModelBinding.Binders
{
public class ArrayModelBinderTest
{
[Fact]
public void BindModel()
{
// Arrange
Mock<IModelBinder> mockIntBinder = new Mock<IModelBinder>();
HttpActionContext context = ContextUtil.CreateActionContext();
context.ControllerContext.Configuration.Services.Replace(typeof(ModelBinderProvider), new SimpleModelBinderProvider(typeof(int), mockIntBinder.Object));
ModelBindingContext bindingContext = new ModelBindingContext
{
ModelMetadata = new EmptyModelMetadataProvider().GetMetadataForType(null, typeof(int[])),
ModelName = "someName",
ValueProvider = new SimpleHttpValueProvider
{
{ "someName[0]", "42" },
{ "someName[1]", "84" }
}
};
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
bool retVal = new ArrayModelBinder<int>().BindModel(context, bindingContext);
// Assert
Assert.True(retVal);
int[] array = bindingContext.Model as int[];
Assert.Equal(new[] { 42, 84 }, array);
}
}
}

View File

@@ -0,0 +1,161 @@
// Copyright (c) Microsoft Corporation. All rights reserved. See License.txt in the project root for license information.
using System.Data.Linq;
using System.Web.Http.Metadata.Providers;
using System.Web.Http.Util;
using Xunit;
namespace System.Web.Http.ModelBinding.Binders
{
public class BinaryDataModelBinderProviderTest
{
private static readonly byte[] _base64Bytes = new byte[] { 0x12, 0x20, 0x34, 0x40 };
private const string _base64String = "EiA0QA==";
[Fact]
public void BindModel_BadValue_Fails()
{
// Arrange
ModelBindingContext bindingContext = new ModelBindingContext
{
ModelMetadata = new EmptyModelMetadataProvider().GetMetadataForType(null, typeof(byte[])),
ModelName = "foo",
ValueProvider = new SimpleHttpValueProvider
{
{ "foo", "not base64 encoded!" }
}
};
BinaryDataModelBinderProvider binderProvider = new BinaryDataModelBinderProvider();
// Act
IModelBinder binder = binderProvider.GetBinder(null, bindingContext);
bool retVal = binder.BindModel(null, bindingContext);
// Assert
Assert.False(retVal);
}
[Fact]
public void BindModel_EmptyValue_Fails()
{
// Arrange
ModelBindingContext bindingContext = new ModelBindingContext
{
ModelMetadata = new EmptyModelMetadataProvider().GetMetadataForType(null, typeof(byte[])),
ModelName = "foo",
ValueProvider = new SimpleHttpValueProvider
{
{ "foo", "" }
}
};
BinaryDataModelBinderProvider binderProvider = new BinaryDataModelBinderProvider();
// Act
IModelBinder binder = binderProvider.GetBinder(null, bindingContext);
bool retVal = binder.BindModel(null, bindingContext);
// Assert
Assert.False(retVal);
}
[Fact]
public void BindModel_GoodValue_ByteArray_Succeeds()
{
// Arrange
ModelBindingContext bindingContext = new ModelBindingContext
{
ModelMetadata = new EmptyModelMetadataProvider().GetMetadataForType(null, typeof(byte[])),
ModelName = "foo",
ValueProvider = new SimpleHttpValueProvider
{
{ "foo", _base64String }
}
};
BinaryDataModelBinderProvider binderProvider = new BinaryDataModelBinderProvider();
// Act
IModelBinder binder = binderProvider.GetBinder(null, bindingContext);
bool retVal = binder.BindModel(null, bindingContext);
// Assert
Assert.True(retVal);
Assert.Equal(_base64Bytes, (byte[])bindingContext.Model);
}
[Fact]
public void BindModel_GoodValue_LinqBinary_Succeeds()
{
// Arrange
ModelBindingContext bindingContext = new ModelBindingContext
{
ModelMetadata = new EmptyModelMetadataProvider().GetMetadataForType(null, typeof(Binary)),
ModelName = "foo",
ValueProvider = new SimpleHttpValueProvider
{
{ "foo", _base64String }
}
};
BinaryDataModelBinderProvider binderProvider = new BinaryDataModelBinderProvider();
// Act
IModelBinder binder = binderProvider.GetBinder(null, bindingContext);
bool retVal = binder.BindModel(null, bindingContext);
// Assert
Assert.True(retVal);
Binary binaryModel = Assert.IsType<Binary>(bindingContext.Model);
Assert.Equal(_base64Bytes, binaryModel.ToArray());
}
[Fact]
public void BindModel_NoValue_Fails()
{
// Arrange
ModelBindingContext bindingContext = new ModelBindingContext
{
ModelMetadata = new EmptyModelMetadataProvider().GetMetadataForType(null, typeof(byte[])),
ModelName = "foo",
ValueProvider = new SimpleHttpValueProvider
{
{ "foo.bar", _base64String }
}
};
BinaryDataModelBinderProvider binderProvider = new BinaryDataModelBinderProvider();
// Act
IModelBinder binder = binderProvider.GetBinder(null, bindingContext);
bool retVal = binder.BindModel(null, bindingContext);
// Assert
Assert.False(retVal);
}
[Fact]
public void GetBinder_WrongModelType_ReturnsNull()
{
// Arrange
ModelBindingContext bindingContext = new ModelBindingContext
{
ModelMetadata = new EmptyModelMetadataProvider().GetMetadataForType(null, typeof(object)),
ModelName = "foo",
ValueProvider = new SimpleHttpValueProvider
{
{ "foo", _base64String }
}
};
BinaryDataModelBinderProvider binderProvider = new BinaryDataModelBinderProvider();
// Act
IModelBinder modelBinder = binderProvider.GetBinder(null, bindingContext);
// Assert
Assert.Null(modelBinder);
}
}
}

View File

@@ -0,0 +1,79 @@
// Copyright (c) Microsoft Corporation. All rights reserved. See License.txt in the project root for license information.
using System.Collections.Generic;
using System.Web.Http.Metadata.Providers;
using System.Web.Http.ModelBinding.Binders;
using System.Web.Http.Util;
using Xunit;
namespace System.Web.Http.ModelBinding
{
public class CollectionModelBinderProviderTest
{
[Fact]
public void GetBinder_CorrectModelTypeAndValueProviderEntries_ReturnsBinder()
{
// Arrange
ModelBindingContext bindingContext = new ModelBindingContext
{
ModelMetadata = new EmptyModelMetadataProvider().GetMetadataForType(null, typeof(IEnumerable<int>)),
ModelName = "foo",
ValueProvider = new SimpleHttpValueProvider
{
{ "foo[0]", "42" },
}
};
CollectionModelBinderProvider binderProvider = new CollectionModelBinderProvider();
// Act
IModelBinder binder = binderProvider.GetBinder(null, bindingContext);
// Assert
Assert.IsType<CollectionModelBinder<int>>(binder);
}
[Fact]
public void GetBinder_ModelTypeIsIncorrect_ReturnsNull()
{
// Arrange
ModelBindingContext bindingContext = new ModelBindingContext
{
ModelMetadata = new EmptyModelMetadataProvider().GetMetadataForType(null, typeof(int)),
ModelName = "foo",
ValueProvider = new SimpleHttpValueProvider
{
{ "foo[0]", "42" },
}
};
CollectionModelBinderProvider binderProvider = new CollectionModelBinderProvider();
// Act
IModelBinder binder = binderProvider.GetBinder(null, bindingContext);
// Assert
Assert.Null(binder);
}
[Fact]
public void GetBinder_ValueProviderDoesNotContainPrefix_ReturnsNull()
{
// Arrange
ModelBindingContext bindingContext = new ModelBindingContext
{
ModelMetadata = new EmptyModelMetadataProvider().GetMetadataForType(null, typeof(IEnumerable<int>)),
ModelName = "foo",
ValueProvider = new SimpleHttpValueProvider()
};
CollectionModelBinderProvider binderProvider = new CollectionModelBinderProvider();
// Act
IModelBinder binder = binderProvider.GetBinder(null, bindingContext);
// Assert
Assert.Null(binder);
}
}
}

View File

@@ -0,0 +1,242 @@
// Copyright (c) Microsoft Corporation. All rights reserved. See License.txt in the project root for license information.
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Web.Http.Controllers;
using System.Web.Http.Metadata.Providers;
using System.Web.Http.ModelBinding.Binders;
using System.Web.Http.Util;
using System.Web.Http.Validation;
using Moq;
using Xunit;
namespace System.Web.Http.ModelBinding
{
public class CollectionModelBinderTest
{
[Fact]
public void BindComplexCollectionFromIndexes_FiniteIndexes()
{
// 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[foo]", "42" },
{ "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;
});
// Act
List<int> boundCollection = CollectionModelBinder<int>.BindComplexCollectionFromIndexes(context, bindingContext, new[] { "foo", "bar", "baz" });
// Assert
Assert.Equal(new[] { 42, 0, 200 }, boundCollection.ToArray());
Assert.Equal(new[] { "someName[foo]", "someName[baz]" }, bindingContext.ValidationNode.ChildNodes.Select(o => o.ModelStateKey).ToArray());
}
[Fact]
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());
}
[Fact]
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());
}
[Fact]
public void BindModel_SimpleCollection()
{
// 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", new[] { "42", "100", "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.True(retVal);
Assert.Equal(new[] { 42, 100, 200 }, ((List<int>)bindingContext.Model).ToArray());
}
[Fact]
public void BindSimpleCollection_RawValueIsEmptyCollection_ReturnsEmptyList()
{
// Act
List<int> boundCollection = CollectionModelBinder<int>.BindSimpleCollection(null, null, new object[0], null);
// Assert
Assert.NotNull(boundCollection);
Assert.Empty(boundCollection);
}
[Fact]
public void BindSimpleCollection_RawValueIsNull_ReturnsNull()
{
// Act
List<int> boundCollection = CollectionModelBinder<int>.BindSimpleCollection(null, null, null, null);
// Assert
Assert.Null(boundCollection);
}
[Fact(Skip = "is this test checking a valid invariant?")]
public void BindSimpleCollection_SubBinderDoesNotExist()
{
// Arrange
CultureInfo culture = CultureInfo.GetCultureInfo("fr-FR");
ModelBindingContext bindingContext = new ModelBindingContext
{
ModelMetadata = new EmptyModelMetadataProvider().GetMetadataForType(null, typeof(int)),
ModelName = "someName",
ValueProvider = new SimpleHttpValueProvider()
};
HttpActionContext context = ContextUtil.CreateActionContext();
context.ControllerContext.Configuration.Services.Replace(typeof(ModelBinderProvider), null); // completely remove from resolution?
// Act
List<int> boundCollection = CollectionModelBinder<int>.BindSimpleCollection(context, bindingContext, new int[1], culture);
// Assert
Assert.Equal(new[] { 0 }, boundCollection.ToArray());
Assert.Empty(bindingContext.ValidationNode.ChildNodes);
}
[Fact]
public void BindSimpleCollection_SubBindingSucceeds()
{
// 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()
};
HttpActionContext context = ContextUtil.CreateActionContext();
context.ControllerContext.Configuration.Services.Replace(typeof(ModelBinderProvider), new SimpleModelBinderProvider(typeof(int), mockIntBinder.Object));
ModelValidationNode childValidationNode = null;
mockIntBinder
.Setup(o => o.BindModel(context, It.IsAny<ModelBindingContext>()))
.Returns((HttpActionContext ec, ModelBindingContext mbc) =>
{
Assert.Equal("someName", mbc.ModelName);
childValidationNode = mbc.ValidationNode;
mbc.Model = 42;
return true;
});
// Act
List<int> boundCollection = CollectionModelBinder<int>.BindSimpleCollection(context, bindingContext, new int[1], culture);
// Assert
Assert.Equal(new[] { 42 }, boundCollection.ToArray());
Assert.Equal(new[] { childValidationNode }, bindingContext.ValidationNode.ChildNodes.ToArray());
}
}
}

View File

@@ -0,0 +1,46 @@
// Copyright (c) Microsoft Corporation. All rights reserved. See License.txt in the project root for license information.
using System.Web.Http.Metadata.Providers;
using Xunit;
namespace System.Web.Http.ModelBinding.Binders
{
public class ComplexModelDtoModelBinderProviderTest
{
[Fact]
public void GetBinder_TypeDoesNotMatch_ReturnsNull()
{
// Arrange
ComplexModelDtoModelBinderProvider provider = new ComplexModelDtoModelBinderProvider();
ModelBindingContext bindingContext = GetBindingContext(typeof(object));
// Act
IModelBinder binder = provider.GetBinder(null, bindingContext);
// Assert
Assert.Null(binder);
}
[Fact]
public void GetBinder_TypeMatches_ReturnsBinder()
{
// Arrange
ComplexModelDtoModelBinderProvider provider = new ComplexModelDtoModelBinderProvider();
ModelBindingContext bindingContext = GetBindingContext(typeof(ComplexModelDto));
// Act
IModelBinder binder = provider.GetBinder(null, bindingContext);
// Assert
Assert.IsType<ComplexModelDtoModelBinder>(binder);
}
private static ModelBindingContext GetBindingContext(Type modelType)
{
return new ModelBindingContext
{
ModelMetadata = new EmptyModelMetadataProvider().GetMetadataForType(() => null, modelType)
};
}
}
}

View File

@@ -0,0 +1,95 @@
// Copyright (c) Microsoft Corporation. All rights reserved. See License.txt in the project root for license information.
using System.Linq;
using System.Web.Http.Controllers;
using System.Web.Http.Metadata;
using System.Web.Http.Metadata.Providers;
using System.Web.Http.Validation;
using Moq;
using Xunit;
namespace System.Web.Http.ModelBinding.Binders
{
public class ComplexModelDtoModelBinderTest
{
[Fact]
public void BindModel()
{
// Arrange
MyModel model = new MyModel();
ModelMetadata modelMetadata = new EmptyModelMetadataProvider().GetMetadataForType(() => model, typeof(MyModel));
ComplexModelDto dto = new ComplexModelDto(modelMetadata, modelMetadata.Properties);
Mock<IModelBinder> mockStringBinder = new Mock<IModelBinder>();
Mock<IModelBinder> mockIntBinder = new Mock<IModelBinder>();
Mock<IModelBinder> mockDateTimeBinder = new Mock<IModelBinder>();
HttpActionContext context = ContextUtil.CreateActionContext();
context.ControllerContext.Configuration.Services.ReplaceRange(typeof(ModelBinderProvider),
new ModelBinderProvider[] {
new SimpleModelBinderProvider(typeof(string), mockStringBinder.Object) { SuppressPrefixCheck = true },
new SimpleModelBinderProvider(typeof(int), mockIntBinder.Object) { SuppressPrefixCheck = true },
new SimpleModelBinderProvider(typeof(DateTime), mockDateTimeBinder.Object) { SuppressPrefixCheck = true }
});
mockStringBinder
.Setup(b => b.BindModel(context, It.IsAny<ModelBindingContext>()))
.Returns((HttpActionContext ec, ModelBindingContext mbc) =>
{
Assert.Equal(typeof(string), mbc.ModelType);
Assert.Equal("theModel.StringProperty", mbc.ModelName);
mbc.ValidationNode = new ModelValidationNode(mbc.ModelMetadata, "theModel.StringProperty");
mbc.Model = "someStringValue";
return true;
});
mockIntBinder
.Setup(b => b.BindModel(context, It.IsAny<ModelBindingContext>()))
.Returns((HttpActionContext ec, ModelBindingContext mbc) =>
{
Assert.Equal(typeof(int), mbc.ModelType);
Assert.Equal("theModel.IntProperty", mbc.ModelName);
mbc.ValidationNode = new ModelValidationNode(mbc.ModelMetadata, "theModel.IntProperty");
mbc.Model = 42;
return true;
});
mockDateTimeBinder
.Setup(b => b.BindModel(context, It.IsAny<ModelBindingContext>()))
.Returns((HttpActionContext ec, ModelBindingContext mbc) =>
{
Assert.Equal(typeof(DateTime), mbc.ModelType);
Assert.Equal("theModel.DateTimeProperty", mbc.ModelName);
return false;
});
ModelBindingContext parentBindingContext = new ModelBindingContext
{
ModelMetadata = new EmptyModelMetadataProvider().GetMetadataForType(() => dto, typeof(ComplexModelDto)),
ModelName = "theModel",
};
ComplexModelDtoModelBinder binder = new ComplexModelDtoModelBinder();
// Act
bool retVal = binder.BindModel(context, parentBindingContext);
// Assert
Assert.True(retVal);
Assert.Equal(dto, parentBindingContext.Model);
ComplexModelDtoResult stringDtoResult = dto.Results[dto.PropertyMetadata.Where(m => m.ModelType == typeof(string)).First()];
Assert.Equal("someStringValue", stringDtoResult.Model);
Assert.Equal("theModel.StringProperty", stringDtoResult.ValidationNode.ModelStateKey);
ComplexModelDtoResult intDtoResult = dto.Results[dto.PropertyMetadata.Where(m => m.ModelType == typeof(int)).First()];
Assert.Equal(42, intDtoResult.Model);
Assert.Equal("theModel.IntProperty", intDtoResult.ValidationNode.ModelStateKey);
ComplexModelDtoResult dateTimeDtoResult = dto.Results[dto.PropertyMetadata.Where(m => m.ModelType == typeof(DateTime)).First()];
Assert.Null(dateTimeDtoResult);
}
private sealed class MyModel
{
public string StringProperty { get; set; }
public int IntProperty { get; set; }
public object ObjectProperty { get; set; } // no binding should happen since no registered binder
public DateTime DateTimeProperty { get; set; } // registered binder returns false
}
}
}

View File

@@ -0,0 +1,43 @@
// Copyright (c) Microsoft Corporation. All rights reserved. See License.txt in the project root for license information.
using System.Web.Http.Metadata;
using System.Web.Http.Metadata.Providers;
using System.Web.Http.Validation;
using Xunit;
using Assert = Microsoft.TestCommon.AssertEx;
namespace System.Web.Http.ModelBinding.Binders
{
public class ComplexModelDtoResultTest
{
[Fact]
public void Constructor_ThrowsIfValidationNodeIsNull()
{
// Act & assert
Assert.ThrowsArgumentNull(
() => new ComplexModelDtoResult("some string", null),
"validationNode");
}
[Fact]
public void Constructor_SetsProperties()
{
// Arrange
ModelValidationNode validationNode = GetValidationNode();
// Act
ComplexModelDtoResult result = new ComplexModelDtoResult("some string", validationNode);
// Assert
Assert.Equal("some string", result.Model);
Assert.Equal(validationNode, result.ValidationNode);
}
private static ModelValidationNode GetValidationNode()
{
EmptyModelMetadataProvider provider = new EmptyModelMetadataProvider();
ModelMetadata metadata = provider.GetMetadataForType(null, typeof(object));
return new ModelValidationNode(metadata, "someKey");
}
}
}

View File

@@ -0,0 +1,55 @@
// Copyright (c) Microsoft Corporation. All rights reserved. See License.txt in the project root for license information.
using System.Linq;
using System.Web.Http.Metadata;
using System.Web.Http.Metadata.Providers;
using Xunit;
using Assert = Microsoft.TestCommon.AssertEx;
namespace System.Web.Http.ModelBinding.Binders
{
public class ComplexModelDtoTest
{
[Fact]
public void ConstructorThrowsIfModelMetadataIsNull()
{
// Act & assert
Assert.ThrowsArgumentNull(
() => new ComplexModelDto(null, Enumerable.Empty<ModelMetadata>()),
"modelMetadata");
}
[Fact]
public void ConstructorThrowsIfPropertyMetadataIsNull()
{
// Arrange
ModelMetadata modelMetadata = GetModelMetadata();
// Act & assert
Assert.ThrowsArgumentNull(
() => new ComplexModelDto(modelMetadata, null),
"propertyMetadata");
}
[Fact]
public void ConstructorSetsProperties()
{
// Arrange
ModelMetadata modelMetadata = GetModelMetadata();
ModelMetadata[] propertyMetadata = new ModelMetadata[0];
// Act
ComplexModelDto dto = new ComplexModelDto(modelMetadata, propertyMetadata);
// Assert
Assert.Equal(modelMetadata, dto.ModelMetadata);
Assert.Equal(propertyMetadata, dto.PropertyMetadata.ToArray());
Assert.Empty(dto.Results);
}
private static ModelMetadata GetModelMetadata()
{
return new ModelMetadata(new EmptyModelMetadataProvider(), typeof(object), null, typeof(object), "PropertyName");
}
}
}

View File

@@ -0,0 +1,78 @@
// Copyright (c) Microsoft Corporation. All rights reserved. See License.txt in the project root for license information.
using System.Collections.Generic;
using System.Web.Http.Metadata.Providers;
using System.Web.Http.Util;
using Xunit;
namespace System.Web.Http.ModelBinding.Binders
{
public class DictionaryModelBinderProviderTest
{
[Fact]
public void GetBinder_CorrectModelTypeAndValueProviderEntries_ReturnsBinder()
{
// Arrange
ModelBindingContext bindingContext = new ModelBindingContext
{
ModelMetadata = new EmptyModelMetadataProvider().GetMetadataForType(null, typeof(IDictionary<int, string>)),
ModelName = "foo",
ValueProvider = new SimpleHttpValueProvider
{
{ "foo[0]", "42" },
}
};
DictionaryModelBinderProvider binderProvider = new DictionaryModelBinderProvider();
// Act
IModelBinder binder = binderProvider.GetBinder(null, bindingContext);
// Assert
Assert.IsType<DictionaryModelBinder<int, string>>(binder);
}
[Fact]
public void GetBinder_ModelTypeIsIncorrect_ReturnsNull()
{
// Arrange
ModelBindingContext bindingContext = new ModelBindingContext
{
ModelMetadata = new EmptyModelMetadataProvider().GetMetadataForType(null, typeof(int)),
ModelName = "foo",
ValueProvider = new SimpleHttpValueProvider
{
{ "foo[0]", "42" },
}
};
DictionaryModelBinderProvider binderProvider = new DictionaryModelBinderProvider();
// Act
IModelBinder binder = binderProvider.GetBinder(null, bindingContext);
// Assert
Assert.Null(binder);
}
[Fact]
public void GetBinder_ValueProviderDoesNotContainPrefix_ReturnsNull()
{
// Arrange
ModelBindingContext bindingContext = new ModelBindingContext
{
ModelMetadata = new EmptyModelMetadataProvider().GetMetadataForType(null, typeof(IDictionary<int, string>)),
ModelName = "foo",
ValueProvider = new SimpleHttpValueProvider()
};
DictionaryModelBinderProvider binderProvider = new DictionaryModelBinderProvider();
// Act
IModelBinder binder = binderProvider.GetBinder(null, bindingContext);
// Assert
Assert.Null(binder);
}
}
}

View File

@@ -0,0 +1,53 @@
// Copyright (c) Microsoft Corporation. All rights reserved. See License.txt in the project root for license information.
using System.Collections.Generic;
using System.Web.Http.Controllers;
using System.Web.Http.Metadata.Providers;
using System.Web.Http.Util;
using Moq;
using Xunit;
namespace System.Web.Http.ModelBinding.Binders
{
public class DictionaryModelBinderTest
{
[Fact]
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]);
}
}
}

View File

@@ -0,0 +1,253 @@
// Copyright (c) Microsoft Corporation. All rights reserved. See License.txt in the project root for license information.
using System.Collections.Generic;
using System.Web.Http.Metadata.Providers;
using System.Web.Http.Util;
using Moq;
using Xunit;
using Assert = Microsoft.TestCommon.AssertEx;
namespace System.Web.Http.ModelBinding.Binders
{
public class GenericModelBinderProviderTest
{
[Fact]
public void Constructor_WithFactory_ThrowsIfModelBinderFactoryIsNull()
{
// Act & assert
Assert.ThrowsArgumentNull(
() => new GenericModelBinderProvider(typeof(List<>), (Func<Type[], IModelBinder>)null),
"modelBinderFactory");
}
[Fact]
public void Constructor_WithFactory_ThrowsIfModelTypeIsNotOpenGeneric()
{
// Act & assert
Assert.Throws<ArgumentException>(
() => new GenericModelBinderProvider(typeof(List<int>), _ => null),
@"The type 'System.Collections.Generic.List`1[System.Int32]' is not an open generic type.
Parameter name: modelType");
}
[Fact]
public void Constructor_WithFactory_ThrowsIfModelTypeIsNull()
{
// Act & assert
Assert.ThrowsArgumentNull(
() => new GenericModelBinderProvider(null, _ => null),
"modelType");
}
[Fact]
public void Constructor_WithInstance_ThrowsIfModelBinderIsNull()
{
// Act & assert
Assert.ThrowsArgumentNull(
() => new GenericModelBinderProvider(typeof(List<>), (IModelBinder)null),
"modelBinder");
}
[Fact]
public void Constructor_WithInstance_ThrowsIfModelTypeIsNotOpenGeneric()
{
// Act & assert
Assert.Throws<ArgumentException>(
() => new GenericModelBinderProvider(typeof(List<int>), new MutableObjectModelBinder()),
@"The type 'System.Collections.Generic.List`1[System.Int32]' is not an open generic type.
Parameter name: modelType");
}
[Fact]
public void Constructor_WithInstance_ThrowsIfModelTypeIsNull()
{
// Act & assert
Assert.ThrowsArgumentNull(
() => new GenericModelBinderProvider(null, new MutableObjectModelBinder()),
"modelType");
}
[Fact]
public void Constructor_WithType_ThrowsIfModelBinderTypeIsNotModelBinder()
{
// Act & assert
Assert.Throws<ArgumentException>(
() => new GenericModelBinderProvider(typeof(List<>), typeof(string)),
@"The type 'System.String' does not implement the interface 'System.Web.Http.ModelBinding.IModelBinder'.
Parameter name: modelBinderType");
}
[Fact]
public void Constructor_WithType_ThrowsIfModelBinderTypeIsNull()
{
// Act & assert
Assert.ThrowsArgumentNull(
() => new GenericModelBinderProvider(typeof(List<>), (Type)null),
"modelBinderType");
}
[Fact]
public void Constructor_WithType_ThrowsIfModelBinderTypeTypeArgumentMismatch()
{
// Act & assert
Assert.Throws<ArgumentException>(
() => new GenericModelBinderProvider(typeof(List<>), typeof(DictionaryModelBinder<,>)),
@"The open model type 'System.Collections.Generic.List`1[T]' has 1 generic type argument(s), but the open binder type 'System.Web.Http.ModelBinding.Binders.DictionaryModelBinder`2[TKey,TValue]' has 2 generic type argument(s). The binder type must not be an open generic type or must have the same number of generic arguments as the open model type.
Parameter name: modelBinderType");
}
[Fact]
public void Constructor_WithType_ThrowsIfModelTypeIsNotOpenGeneric()
{
// Act & assert
Assert.Throws<ArgumentException>(
() => new GenericModelBinderProvider(typeof(List<int>), typeof(MutableObjectModelBinder)),
@"The type 'System.Collections.Generic.List`1[System.Int32]' is not an open generic type.
Parameter name: modelType");
}
[Fact]
public void Constructor_WithType_ThrowsIfModelTypeIsNull()
{
// Act & assert
Assert.ThrowsArgumentNull(
() => new GenericModelBinderProvider(null, typeof(MutableObjectModelBinder)),
"modelType");
}
[Fact]
public void GetBinder_TypeDoesNotMatch_ModelTypeIsInterface_ReturnsNull()
{
// Arrange
GenericModelBinderProvider provider = new GenericModelBinderProvider(typeof(IEnumerable<>), typeof(CollectionModelBinder<>))
{
SuppressPrefixCheck = true
};
ModelBindingContext bindingContext = GetBindingContext(typeof(object));
// Act
IModelBinder binder = provider.GetBinder(null, bindingContext);
// Assert
Assert.Null(binder);
}
[Fact]
public void GetBinder_TypeDoesNotMatch_ModelTypeIsNotInterface_ReturnsNull()
{
// Arrange
GenericModelBinderProvider provider = new GenericModelBinderProvider(typeof(List<>), typeof(CollectionModelBinder<>))
{
SuppressPrefixCheck = true
};
ModelBindingContext bindingContext = GetBindingContext(typeof(object));
// Act
IModelBinder binder = provider.GetBinder(null, bindingContext);
// Assert
Assert.Null(binder);
}
[Fact]
public void GetBinder_TypeMatches_PrefixNotFound_ReturnsNull()
{
// Arrange
IModelBinder binderInstance = new Mock<IModelBinder>().Object;
GenericModelBinderProvider provider = new GenericModelBinderProvider(typeof(List<>), binderInstance);
ModelBindingContext bindingContext = GetBindingContext(typeof(List<int>));
bindingContext.ValueProvider = new SimpleHttpValueProvider();
// Act
IModelBinder returnedBinder = provider.GetBinder(null, bindingContext);
// Assert
Assert.Null(returnedBinder);
}
[Fact]
public void GetBinder_TypeMatches_Success_Factory_ReturnsBinder()
{
// Arrange
IModelBinder binderInstance = new Mock<IModelBinder>().Object;
Func<Type[], IModelBinder> binderFactory = typeArguments =>
{
Assert.Equal(new[] { typeof(int) }, typeArguments);
return binderInstance;
};
GenericModelBinderProvider provider = new GenericModelBinderProvider(typeof(IList<>), binderFactory)
{
SuppressPrefixCheck = true
};
ModelBindingContext bindingContext = GetBindingContext(typeof(List<int>));
// Act
IModelBinder returnedBinder = provider.GetBinder(null, bindingContext);
// Assert
Assert.Same(binderInstance, returnedBinder);
}
[Fact]
public void GetBinder_TypeMatches_Success_Instance_ReturnsBinder()
{
// Arrange
IModelBinder binderInstance = new Mock<IModelBinder>().Object;
GenericModelBinderProvider provider = new GenericModelBinderProvider(typeof(List<>), binderInstance)
{
SuppressPrefixCheck = true
};
ModelBindingContext bindingContext = GetBindingContext(typeof(List<int>));
// Act
IModelBinder returnedBinder = provider.GetBinder(null, bindingContext);
// Assert
Assert.Same(binderInstance, returnedBinder);
}
[Fact]
public void GetBinder_TypeMatches_Success_TypeActivation_ReturnsBinder()
{
// Arrange
GenericModelBinderProvider provider = new GenericModelBinderProvider(typeof(List<>), typeof(CollectionModelBinder<>))
{
SuppressPrefixCheck = true
};
ModelBindingContext bindingContext = GetBindingContext(typeof(List<int>));
// Act
IModelBinder returnedBinder = provider.GetBinder(null, bindingContext);
// Assert
Assert.IsType<CollectionModelBinder<int>>(returnedBinder);
}
[Fact]
public void GetBinderThrowsIfBindingContextIsNull()
{
// Arrange
GenericModelBinderProvider provider = new GenericModelBinderProvider(typeof(IEnumerable<>), typeof(CollectionModelBinder<>));
// Act & assert
Assert.ThrowsArgumentNull(
() => provider.GetBinder(null, null),
"bindingContext");
}
private static ModelBindingContext GetBindingContext(Type modelType)
{
return new ModelBindingContext
{
ModelMetadata = new EmptyModelMetadataProvider().GetMetadataForType(() => null, modelType)
};
}
}
}

View File

@@ -0,0 +1,106 @@
// Copyright (c) Microsoft Corporation. All rights reserved. See License.txt in the project root for license information.
using System.Collections.Generic;
using System.Web.Http.Metadata.Providers;
using System.Web.Http.Util;
using Xunit;
namespace System.Web.Http.ModelBinding.Binders
{
public class KeyValuePairModelBinderProviderTest
{
[Fact]
public void GetBinder_CorrectModelTypeAndValueProviderEntries_ReturnsBinder()
{
// Arrange
ModelBindingContext bindingContext = new ModelBindingContext
{
ModelMetadata = new EmptyModelMetadataProvider().GetMetadataForType(null, typeof(KeyValuePair<int, string>)),
ModelName = "foo",
ValueProvider = new SimpleHttpValueProvider
{
{ "foo.key", 42 },
{ "foo.value", "someValue" }
}
};
KeyValuePairModelBinderProvider binderProvider = new KeyValuePairModelBinderProvider();
// Act
IModelBinder binder = binderProvider.GetBinder(null, bindingContext);
// Assert
Assert.IsType<KeyValuePairModelBinder<int, string>>(binder);
}
[Fact]
public void GetBinder_ModelTypeIsIncorrect_ReturnsNull()
{
// Arrange
ModelBindingContext bindingContext = new ModelBindingContext
{
ModelMetadata = new EmptyModelMetadataProvider().GetMetadataForType(null, typeof(List<int>)),
ModelName = "foo",
ValueProvider = new SimpleHttpValueProvider
{
{ "foo.key", 42 },
{ "foo.value", "someValue" }
}
};
KeyValuePairModelBinderProvider binderProvider = new KeyValuePairModelBinderProvider();
// Act
IModelBinder binder = binderProvider.GetBinder(null, bindingContext);
// Assert
Assert.Null(binder);
}
[Fact]
public void GetBinder_ValueProviderDoesNotContainKeyProperty_ReturnsNull()
{
// Arrange
ModelBindingContext bindingContext = new ModelBindingContext
{
ModelMetadata = new EmptyModelMetadataProvider().GetMetadataForType(null, typeof(KeyValuePair<int, string>)),
ModelName = "foo",
ValueProvider = new SimpleHttpValueProvider
{
{ "foo.value", "someValue" }
}
};
KeyValuePairModelBinderProvider binderProvider = new KeyValuePairModelBinderProvider();
// Act
IModelBinder binder = binderProvider.GetBinder(null, bindingContext);
// Assert
Assert.Null(binder);
}
[Fact]
public void GetBinder_ValueProviderDoesNotContainValueProperty_ReturnsNull()
{
// Arrange
ModelBindingContext bindingContext = new ModelBindingContext
{
ModelMetadata = new EmptyModelMetadataProvider().GetMetadataForType(null, typeof(KeyValuePair<int, string>)),
ModelName = "foo",
ValueProvider = new SimpleHttpValueProvider
{
{ "foo.key", 42 }
}
};
KeyValuePairModelBinderProvider binderProvider = new KeyValuePairModelBinderProvider();
// Act
IModelBinder binder = binderProvider.GetBinder(null, bindingContext);
// Assert
Assert.Null(binder);
}
}
}

View File

@@ -0,0 +1,114 @@
// Copyright (c) Microsoft Corporation. All rights reserved. See License.txt in the project root for license information.
using System.Collections.Generic;
using System.Linq;
using System.Web.Http.Controllers;
using System.Web.Http.Metadata.Providers;
using System.Web.Http.Util;
using Moq;
using Xunit;
namespace System.Web.Http.ModelBinding.Binders
{
public class KeyValuePairModelBinderTest
{
[Fact]
public void BindModel_MissingKey_ReturnsFalse()
{
// Arrange
KeyValuePairModelBinder<int, string> binder = new KeyValuePairModelBinder<int, string>();
ModelBindingContext bindingContext = new ModelBindingContext
{
ModelMetadata = new EmptyModelMetadataProvider().GetMetadataForType(null, typeof(KeyValuePair<int, string>)),
ModelName = "someName",
ValueProvider = new SimpleHttpValueProvider()
};
HttpActionContext context = ContextUtil.CreateActionContext();
context.ControllerContext.Configuration.Services.Replace(typeof(ModelBinderProvider), new SimpleModelBinderProvider(typeof(KeyValuePair<int, string>), binder));
// Act
bool retVal = binder.BindModel(context, bindingContext);
// Assert
Assert.False(retVal);
Assert.Null(bindingContext.Model);
Assert.Empty(bindingContext.ValidationNode.ChildNodes);
}
[Fact]
public void BindModel_MissingValue_ReturnsTrue()
{
// Arrange
Mock<IModelBinder> mockIntBinder = new Mock<IModelBinder>();
ModelBindingContext bindingContext = new ModelBindingContext
{
ModelMetadata = new EmptyModelMetadataProvider().GetMetadataForType(null, typeof(KeyValuePair<int, string>)),
ModelName = "someName",
ValueProvider = new SimpleHttpValueProvider()
};
HttpActionContext context = ContextUtil.CreateActionContext();
context.ControllerContext.Configuration.Services.Replace(typeof(ModelBinderProvider), new SimpleModelBinderProvider(typeof(int), mockIntBinder.Object) { SuppressPrefixCheck = true });
mockIntBinder
.Setup(o => o.BindModel(context, It.IsAny<ModelBindingContext>()))
.Returns((HttpActionContext cc, ModelBindingContext mbc) =>
{
mbc.Model = 42;
return true;
});
KeyValuePairModelBinder<int, string> binder = new KeyValuePairModelBinder<int, string>();
// Act
bool retVal = binder.BindModel(context, bindingContext);
// Assert
Assert.True(retVal);
Assert.Null(bindingContext.Model);
Assert.Equal(new[] { "someName.key" }, bindingContext.ValidationNode.ChildNodes.Select(n => n.ModelStateKey).ToArray());
}
[Fact]
public void BindModel_SubBindingSucceeds()
{
// Arrange
Mock<IModelBinder> mockIntBinder = new Mock<IModelBinder>();
Mock<IModelBinder> mockStringBinder = new Mock<IModelBinder>();
ModelBindingContext bindingContext = new ModelBindingContext
{
ModelMetadata = new EmptyModelMetadataProvider().GetMetadataForType(null, typeof(KeyValuePair<int, string>)),
ModelName = "someName",
ValueProvider = new SimpleHttpValueProvider()
};
HttpActionContext context = ContextUtil.CreateActionContext();
context.ControllerContext.Configuration.Services.ReplaceRange(typeof(ModelBinderProvider),
new ModelBinderProvider[] {
new SimpleModelBinderProvider(typeof(int), mockIntBinder.Object) { SuppressPrefixCheck = true },
new SimpleModelBinderProvider(typeof(string), mockStringBinder.Object) { SuppressPrefixCheck = true }
});
mockIntBinder
.Setup(o => o.BindModel(context, It.IsAny<ModelBindingContext>()))
.Returns((HttpActionContext cc, ModelBindingContext mbc) =>
{
mbc.Model = 42;
return true;
});
mockStringBinder
.Setup(o => o.BindModel(context, It.IsAny<ModelBindingContext>()))
.Returns((HttpActionContext cc, ModelBindingContext mbc) =>
{
mbc.Model = "forty-two";
return true;
});
KeyValuePairModelBinder<int, string> binder = new KeyValuePairModelBinder<int, string>();
// Act
bool retVal = binder.BindModel(context, bindingContext);
// Assert
Assert.True(retVal);
Assert.Equal(new KeyValuePair<int, string>(42, "forty-two"), bindingContext.Model);
Assert.Equal(new[] { "someName.key", "someName.value" }, bindingContext.ValidationNode.ChildNodes.Select(n => n.ModelStateKey).ToArray());
}
}
}

View File

@@ -0,0 +1,107 @@
// Copyright (c) Microsoft Corporation. All rights reserved. See License.txt in the project root for license information.
using System.Web.Http.Controllers;
using System.Web.Http.Internal;
using System.Web.Http.Metadata.Providers;
using System.Web.Http.Util;
using Moq;
using Xunit;
namespace System.Web.Http.ModelBinding.Binders
{
public class KeyValuePairModelBinderUtilTest
{
[Fact]
public void TryBindStrongModel_BinderExists_BinderReturnsCorrectlyTypedObject_ReturnsTrue()
{
// Arrange
Mock<IModelBinder> mockIntBinder = new Mock<IModelBinder>();
ModelBindingContext bindingContext = new ModelBindingContext
{
ModelMetadata = new EmptyModelMetadataProvider().GetMetadataForType(null, typeof(int)),
ModelName = "someName",
ModelState = new ModelStateDictionary(),
ValueProvider = new SimpleHttpValueProvider()
};
HttpActionContext context = ContextUtil.CreateActionContext();
context.ControllerContext.Configuration.Services.Replace(typeof(ModelBinderProvider), new SimpleModelBinderProvider(typeof(int), mockIntBinder.Object) { SuppressPrefixCheck = true });
mockIntBinder
.Setup(o => o.BindModel(context, It.IsAny<ModelBindingContext>()))
.Returns((HttpActionContext cc, ModelBindingContext mbc) =>
{
Assert.Equal("someName.key", mbc.ModelName);
mbc.Model = 42;
return true;
});
// Act
int model;
bool retVal = context.TryBindStrongModel(bindingContext, "key", new EmptyModelMetadataProvider(), out model);
// Assert
Assert.True(retVal);
Assert.Equal(42, model);
Assert.Single(bindingContext.ValidationNode.ChildNodes);
Assert.Empty(bindingContext.ModelState);
}
[Fact]
public void TryBindStrongModel_BinderExists_BinderReturnsIncorrectlyTypedObject_ReturnsTrue()
{
// Arrange
Mock<IModelBinder> mockIntBinder = new Mock<IModelBinder>();
ModelBindingContext bindingContext = new ModelBindingContext
{
ModelMetadata = new EmptyModelMetadataProvider().GetMetadataForType(null, typeof(int)),
ModelName = "someName",
ModelState = new ModelStateDictionary(),
ValueProvider = new SimpleHttpValueProvider()
};
HttpActionContext context = ContextUtil.CreateActionContext();
context.ControllerContext.Configuration.Services.Replace(typeof(ModelBinderProvider), new SimpleModelBinderProvider(typeof(int), mockIntBinder.Object) { SuppressPrefixCheck = true });
mockIntBinder
.Setup(o => o.BindModel(context, It.IsAny<ModelBindingContext>()))
.Returns((HttpActionContext cc, ModelBindingContext mbc) =>
{
Assert.Equal("someName.key", mbc.ModelName);
return true;
});
// Act
int model;
bool retVal = context.TryBindStrongModel(bindingContext, "key", new EmptyModelMetadataProvider(), out model);
// Assert
Assert.True(retVal);
Assert.Equal(default(int), model);
Assert.Single(bindingContext.ValidationNode.ChildNodes);
Assert.Empty(bindingContext.ModelState);
}
[Fact]
public void TryBindStrongModel_NoBinder_ReturnsFalse()
{
// Arrange
HttpActionContext context = ContextUtil.CreateActionContext();
ModelBindingContext bindingContext = new ModelBindingContext
{
ModelMetadata = new EmptyModelMetadataProvider().GetMetadataForType(null, typeof(int)),
ModelName = "someName",
ModelState = new ModelStateDictionary(),
ValueProvider = new SimpleHttpValueProvider()
};
// Act
int model;
bool retVal = context.TryBindStrongModel(bindingContext, "key", new EmptyModelMetadataProvider(), out model);
// Assert
Assert.False(retVal);
Assert.Equal(default(int), model);
Assert.Empty(bindingContext.ValidationNode.ChildNodes);
Assert.Empty(bindingContext.ModelState);
}
}
}

View File

@@ -0,0 +1,105 @@
// Copyright (c) Microsoft Corporation. All rights reserved. See License.txt in the project root for license information.
using System.Web.Http.Metadata.Providers;
using System.Web.Http.Util;
using Xunit;
namespace System.Web.Http.ModelBinding.Binders
{
public class MutableObjectModelBinderProviderTest
{
[Fact]
public void GetBinder_NoPrefixInValueProvider_ReturnsNull()
{
// Arrange
ModelBindingContext bindingContext = new ModelBindingContext
{
ModelMetadata = new EmptyModelMetadataProvider().GetMetadataForType(() => 42, typeof(int)),
ModelName = "foo",
ValueProvider = new SimpleHttpValueProvider()
};
MutableObjectModelBinderProvider binderProvider = new MutableObjectModelBinderProvider();
// Act
IModelBinder binder = binderProvider.GetBinder(null, bindingContext);
// Assert
Assert.Null(binder);
}
[Fact]
public void GetBinder_PrefixInValueProvider_ComplexType_ReturnsBinder()
{
// Arrange
ModelBindingContext bindingContext = new ModelBindingContext
{
ModelMetadata = new EmptyModelMetadataProvider().GetMetadataForType(() => new MutableTestType(), typeof(MutableTestType)),
ModelName = "foo",
ValueProvider = new SimpleHttpValueProvider
{
{ "foo.bar", "someValue" }
}
};
MutableObjectModelBinderProvider binderProvider = new MutableObjectModelBinderProvider();
// Act
IModelBinder binder = binderProvider.GetBinder(null, bindingContext);
// Assert
Assert.NotNull(binder);
Assert.IsType<MutableObjectModelBinder>(binder);
}
[Fact]
public void GetBinder_PrefixInValueProvider_SimpleType_ReturnsNull()
{
// Arrange
ModelBindingContext bindingContext = new ModelBindingContext
{
ModelMetadata = new EmptyModelMetadataProvider().GetMetadataForType(() => 42, typeof(int)),
ModelName = "foo",
ValueProvider = new SimpleHttpValueProvider
{
{ "foo.bar", "someValue" }
}
};
MutableObjectModelBinderProvider binderProvider = new MutableObjectModelBinderProvider();
// Act
IModelBinder binder = binderProvider.GetBinder(null, bindingContext);
// Assert
Assert.Null(binder);
}
[Fact]
public void GetBinder_TypeIsComplexModelDto_ReturnsNull()
{
// Arrange
ModelBindingContext bindingContext = new ModelBindingContext
{
ModelMetadata = new EmptyModelMetadataProvider().GetMetadataForType(null, typeof(ComplexModelDto)),
ModelName = "foo",
ValueProvider = new SimpleHttpValueProvider
{
{ "foo.bar", "someValue" }
}
};
MutableObjectModelBinderProvider binderProvider = new MutableObjectModelBinderProvider();
// Act
IModelBinder binder = binderProvider.GetBinder(null, bindingContext);
// Assert
Assert.Null(binder);
}
class MutableTestType
{
}
}
}

View File

@@ -0,0 +1,157 @@
// Copyright (c) Microsoft Corporation. All rights reserved. See License.txt in the project root for license information.
using System.Web.Http.Metadata.Providers;
using System.Web.Http.Util;
using Moq;
using Xunit;
using Assert = Microsoft.TestCommon.AssertEx;
namespace System.Web.Http.ModelBinding.Binders
{
public class SimpleModelBinderProviderTest
{
[Fact]
public void ConstructorWithFactoryThrowsIfModelBinderFactoryIsNull()
{
// Act & assert
Assert.ThrowsArgumentNull(
() => new SimpleModelBinderProvider(typeof(object), (Func<IModelBinder>)null),
"modelBinderFactory");
}
[Fact]
public void ConstructorWithFactoryThrowsIfModelTypeIsNull()
{
// Act & assert
Assert.ThrowsArgumentNull(
() => new SimpleModelBinderProvider(null, () => null),
"modelType");
}
[Fact]
public void ConstructorWithInstanceThrowsIfModelBinderIsNull()
{
// Act & assert
Assert.ThrowsArgumentNull(
() => new SimpleModelBinderProvider(typeof(object), (IModelBinder)null),
"modelBinder");
}
[Fact]
public void ConstructorWithInstanceThrowsIfModelTypeIsNull()
{
// Act & assert
Assert.ThrowsArgumentNull(
() => new SimpleModelBinderProvider(null, new Mock<IModelBinder>().Object),
"modelType");
}
[Fact]
public void GetBinder_TypeDoesNotMatch_ReturnsNull()
{
// Arrange
SimpleModelBinderProvider provider = new SimpleModelBinderProvider(typeof(string), new Mock<IModelBinder>().Object)
{
SuppressPrefixCheck = true
};
ModelBindingContext bindingContext = GetBindingContext(typeof(object));
// Act
IModelBinder binder = provider.GetBinder(null, bindingContext);
// Assert
Assert.Null(binder);
}
[Fact]
public void GetBinder_TypeMatches_PrefixNotFound_ReturnsNull()
{
// Arrange
IModelBinder binderInstance = new Mock<IModelBinder>().Object;
SimpleModelBinderProvider provider = new SimpleModelBinderProvider(typeof(string), binderInstance);
ModelBindingContext bindingContext = GetBindingContext(typeof(string));
bindingContext.ValueProvider = new SimpleHttpValueProvider();
// Act
IModelBinder returnedBinder = provider.GetBinder(null, bindingContext);
// Assert
Assert.Null(returnedBinder);
}
[Fact]
public void GetBinder_TypeMatches_PrefixSuppressed_ReturnsFactoryInstance()
{
// Arrange
int numExecutions = 0;
IModelBinder theBinderInstance = new Mock<IModelBinder>().Object;
Func<IModelBinder> factory = delegate
{
numExecutions++;
return theBinderInstance;
};
SimpleModelBinderProvider provider = new SimpleModelBinderProvider(typeof(string), factory)
{
SuppressPrefixCheck = true
};
ModelBindingContext bindingContext = GetBindingContext(typeof(string));
// Act
IModelBinder returnedBinder = provider.GetBinder(null, bindingContext);
returnedBinder = provider.GetBinder(null, bindingContext);
// Assert
Assert.Equal(2, numExecutions);
Assert.Equal(theBinderInstance, returnedBinder);
}
[Fact]
public void GetBinder_TypeMatches_PrefixSuppressed_ReturnsInstance()
{
// Arrange
IModelBinder theBinderInstance = new Mock<IModelBinder>().Object;
SimpleModelBinderProvider provider = new SimpleModelBinderProvider(typeof(string), theBinderInstance)
{
SuppressPrefixCheck = true
};
ModelBindingContext bindingContext = GetBindingContext(typeof(string));
// Act
IModelBinder returnedBinder = provider.GetBinder(null, bindingContext);
// Assert
Assert.Equal(theBinderInstance, returnedBinder);
}
[Fact]
public void GetBinderThrowsIfBindingContextIsNull()
{
// Arrange
SimpleModelBinderProvider provider = new SimpleModelBinderProvider(typeof(string), new Mock<IModelBinder>().Object);
// Act & assert
Assert.ThrowsArgumentNull(
delegate { provider.GetBinder(null, null); }, "bindingContext");
}
[Fact]
public void ModelTypeProperty()
{
// Arrange
SimpleModelBinderProvider provider = new SimpleModelBinderProvider(typeof(string), new Mock<IModelBinder>().Object);
// Act & assert
Assert.Equal(typeof(string), provider.ModelType);
}
private static ModelBindingContext GetBindingContext(Type modelType)
{
return new ModelBindingContext
{
ModelMetadata = new EmptyModelMetadataProvider().GetMetadataForType(() => null, modelType)
};
}
}
}

View File

@@ -0,0 +1,70 @@
// Copyright (c) Microsoft Corporation. All rights reserved. See License.txt in the project root for license information.
using System.Web.Http.Metadata.Providers;
using System.Web.Http.Util;
using Xunit;
namespace System.Web.Http.ModelBinding.Binders
{
public class TypeConverterModelBinderProviderTest
{
[Fact]
public void GetBinder_NoTypeConverterExistsFromString_ReturnsNull()
{
// Arrange
ModelBindingContext bindingContext = GetBindingContext(typeof(void)); // no TypeConverter exists Void -> String
TypeConverterModelBinderProvider provider = new TypeConverterModelBinderProvider();
// Act
IModelBinder binder = provider.GetBinder(null, bindingContext);
// Assert
Assert.Null(binder);
}
[Fact]
public void GetBinder_NullValueProviderResult_ReturnsNull()
{
// Arrange
ModelBindingContext bindingContext = GetBindingContext(typeof(int));
bindingContext.ValueProvider = new SimpleHttpValueProvider(); // clear the ValueProvider
TypeConverterModelBinderProvider provider = new TypeConverterModelBinderProvider();
// Act
IModelBinder binder = provider.GetBinder(null, bindingContext);
// Assert
Assert.Null(binder);
}
[Fact]
public void GetBinder_TypeConverterExistsFromString_ReturnsNull()
{
// Arrange
ModelBindingContext bindingContext = GetBindingContext(typeof(int)); // TypeConverter exists Int32 -> String
TypeConverterModelBinderProvider provider = new TypeConverterModelBinderProvider();
// Act
IModelBinder binder = provider.GetBinder(null, bindingContext);
// Assert
Assert.IsType<TypeConverterModelBinder>(binder);
}
private static ModelBindingContext GetBindingContext(Type modelType)
{
return new ModelBindingContext
{
ModelMetadata = new EmptyModelMetadataProvider().GetMetadataForType(null, modelType),
ModelName = "theModelName",
ValueProvider = new SimpleHttpValueProvider
{
{ "theModelName", "someValue" }
}
};
}
}
}

View File

@@ -0,0 +1,172 @@
// Copyright (c) Microsoft Corporation. All rights reserved. See License.txt in the project root for license information.
using System.ComponentModel;
using System.Globalization;
using System.Web.Http.Metadata.Providers;
using System.Web.Http.Util;
using Xunit;
namespace System.Web.Http.ModelBinding.Binders
{
public class TypeConverterModelBinderTest
{
[Fact]
public void BindModel_Error_FormatExceptionsTurnedIntoStringsInModelState()
{
// Arrange
ModelBindingContext bindingContext = GetBindingContext(typeof(int));
bindingContext.ValueProvider = new SimpleHttpValueProvider
{
{ "theModelName", "not an integer" }
};
TypeConverterModelBinder binder = new TypeConverterModelBinder();
// Act
bool retVal = binder.BindModel(null, bindingContext);
// Assert
Assert.False(retVal);
Assert.Equal("The value 'not an integer' is not valid for Int32.", bindingContext.ModelState["theModelName"].Errors[0].ErrorMessage);
}
[Fact]
public void BindModel_Error_FormatExceptionsTurnedIntoStringsInModelState_ErrorNotAddedIfCallbackReturnsNull()
{
// Arrange
ModelBindingContext bindingContext = GetBindingContext(typeof(int));
bindingContext.ValueProvider = new SimpleHttpValueProvider
{
{ "theModelName", "not an integer" }
};
TypeConverterModelBinder binder = new TypeConverterModelBinder();
// Act
ModelBinderErrorMessageProvider originalProvider = ModelBinderConfig.TypeConversionErrorMessageProvider;
bool retVal;
try
{
ModelBinderConfig.TypeConversionErrorMessageProvider = delegate { return null; };
retVal = binder.BindModel(null, bindingContext);
}
finally
{
ModelBinderConfig.TypeConversionErrorMessageProvider = originalProvider;
}
// Assert
Assert.False(retVal);
Assert.Null(bindingContext.Model);
Assert.True(bindingContext.ModelState.IsValid);
}
[Fact]
public void BindModel_Error_GeneralExceptionsSavedInModelState()
{
// Arrange
ModelBindingContext bindingContext = GetBindingContext(typeof(Dummy));
bindingContext.ValueProvider = new SimpleHttpValueProvider
{
{ "theModelName", "foo" }
};
TypeConverterModelBinder binder = new TypeConverterModelBinder();
// Act
bool retVal = binder.BindModel(null, bindingContext);
// Assert
Assert.False(retVal);
Assert.Null(bindingContext.Model);
Assert.Equal("The parameter conversion from type 'System.String' to type 'System.Web.Http.ModelBinding.Binders.TypeConverterModelBinderTest+Dummy' failed. See the inner exception for more information.", bindingContext.ModelState["theModelName"].Errors[0].Exception.Message);
Assert.Equal("From DummyTypeConverter: foo", bindingContext.ModelState["theModelName"].Errors[0].Exception.InnerException.Message);
}
[Fact]
public void BindModel_NullValueProviderResult_ReturnsFalse()
{
// Arrange
ModelBindingContext bindingContext = GetBindingContext(typeof(int));
TypeConverterModelBinder binder = new TypeConverterModelBinder();
// Act
bool retVal = binder.BindModel(null, bindingContext);
// Assert
Assert.False(retVal, "BindModel should have returned null.");
Assert.Empty(bindingContext.ModelState);
}
[Fact]
public void BindModel_ValidValueProviderResult_ConvertEmptyStringsToNull()
{
// Arrange
ModelBindingContext bindingContext = GetBindingContext(typeof(string));
bindingContext.ValueProvider = new SimpleHttpValueProvider
{
{ "theModelName", "" }
};
TypeConverterModelBinder binder = new TypeConverterModelBinder();
// Act
bool retVal = binder.BindModel(null, bindingContext);
// Assert
Assert.True(retVal);
Assert.Null(bindingContext.Model);
Assert.True(bindingContext.ModelState.ContainsKey("theModelName"));
}
[Fact]
public void BindModel_ValidValueProviderResult_ReturnsModel()
{
// Arrange
ModelBindingContext bindingContext = GetBindingContext(typeof(int));
bindingContext.ValueProvider = new SimpleHttpValueProvider
{
{ "theModelName", "42" }
};
TypeConverterModelBinder binder = new TypeConverterModelBinder();
// Act
bool retVal = binder.BindModel(null, bindingContext);
// Assert
Assert.True(retVal);
Assert.Equal(42, bindingContext.Model);
Assert.True(bindingContext.ModelState.ContainsKey("theModelName"));
}
private static ModelBindingContext GetBindingContext(Type modelType)
{
return new ModelBindingContext
{
ModelMetadata = new EmptyModelMetadataProvider().GetMetadataForType(null, modelType),
ModelName = "theModelName",
ValueProvider = new SimpleHttpValueProvider() // empty
};
}
[TypeConverter(typeof(DummyTypeConverter))]
private struct Dummy
{
}
private sealed class DummyTypeConverter : TypeConverter
{
public override bool CanConvertFrom(ITypeDescriptorContext context, Type sourceType)
{
return (sourceType == typeof(string)) || base.CanConvertFrom(context, sourceType);
}
public override object ConvertFrom(ITypeDescriptorContext context, CultureInfo culture, object value)
{
throw new InvalidOperationException(String.Format("From DummyTypeConverter: {0}", value));
}
}
}
}

Some files were not shown because too many files have changed in this diff Show More