diff --git a/src/Microsoft.AspNet.Mvc.Core/Microsoft.AspNet.Mvc.Core.kproj b/src/Microsoft.AspNet.Mvc.Core/Microsoft.AspNet.Mvc.Core.kproj
index 16c25e8b50..0291a37558 100644
--- a/src/Microsoft.AspNet.Mvc.Core/Microsoft.AspNet.Mvc.Core.kproj
+++ b/src/Microsoft.AspNet.Mvc.Core/Microsoft.AspNet.Mvc.Core.kproj
@@ -147,6 +147,7 @@
+
diff --git a/src/Microsoft.AspNet.Mvc.Core/MvcOptions.cs b/src/Microsoft.AspNet.Mvc.Core/MvcOptions.cs
index 5e2fa586b9..0604ae95aa 100644
--- a/src/Microsoft.AspNet.Mvc.Core/MvcOptions.cs
+++ b/src/Microsoft.AspNet.Mvc.Core/MvcOptions.cs
@@ -4,6 +4,7 @@
using System;
using System.Collections.Generic;
using Microsoft.AspNet.Mvc.Core;
+using Microsoft.AspNet.Mvc.ModelBinding;
using Microsoft.AspNet.Mvc.ReflectedModelBuilder;
namespace Microsoft.AspNet.Mvc
@@ -15,6 +16,14 @@ namespace Microsoft.AspNet.Mvc
public MvcOptions()
{
ApplicationModelConventions = new List();
+ ModelBinders = new List
+ {
+ new ModelBinderDescriptor(new TypeConverterModelBinder()),
+ new ModelBinderDescriptor(new TypeMatchModelBinder()),
+ new ModelBinderDescriptor(typeof(GenericModelBinder)),
+ new ModelBinderDescriptor(new MutableObjectModelBinder()),
+ new ModelBinderDescriptor(new ComplexModelDtoModelBinder()),
+ };
}
public AntiForgeryOptions AntiForgeryOptions
@@ -28,7 +37,7 @@ namespace Microsoft.AspNet.Mvc
{
if (value == null)
{
- throw new ArgumentNullException("value",
+ throw new ArgumentNullException("value",
Resources.FormatPropertyOfTypeCannotBeNull("AntiForgeryOptions",
typeof(MvcOptions)));
}
@@ -37,6 +46,8 @@ namespace Microsoft.AspNet.Mvc
}
}
+ public List ModelBinders { get; private set; }
+
public List ApplicationModelConventions { get; private set; }
}
}
\ No newline at end of file
diff --git a/src/Microsoft.AspNet.Mvc.Core/ParameterBinding/DefaultActionBindingContextProvider.cs b/src/Microsoft.AspNet.Mvc.Core/ParameterBinding/DefaultActionBindingContextProvider.cs
index d0ec65d500..cfea960128 100644
--- a/src/Microsoft.AspNet.Mvc.Core/ParameterBinding/DefaultActionBindingContextProvider.cs
+++ b/src/Microsoft.AspNet.Mvc.Core/ParameterBinding/DefaultActionBindingContextProvider.cs
@@ -6,29 +6,26 @@ using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNet.Mvc.ModelBinding;
-using Microsoft.AspNet.Routing;
namespace Microsoft.AspNet.Mvc
{
public class DefaultActionBindingContextProvider : IActionBindingContextProvider
{
private readonly IModelMetadataProvider _modelMetadataProvider;
- private readonly IEnumerable _modelBinders;
+ private readonly ICompositeModelBinder _compositeModelBinder;
private readonly IEnumerable _valueProviderFactories;
private readonly IInputFormatterProvider _inputFormatterProvider;
private readonly IEnumerable _validatorProviders;
-
private Tuple _bindingContext;
public DefaultActionBindingContextProvider(IModelMetadataProvider modelMetadataProvider,
- IEnumerable modelBinders,
+ ICompositeModelBinder compositeModelBinder,
IEnumerable valueProviderFactories,
IInputFormatterProvider inputFormatterProvider,
IEnumerable validatorProviders)
{
_modelMetadataProvider = modelMetadataProvider;
- _modelBinders = modelBinders.OrderBy(
- binder => binder.GetType() == typeof(ComplexModelDtoModelBinder) ? 1 : 0).ToArray();
+ _compositeModelBinder = compositeModelBinder;
_valueProviderFactories = valueProviderFactories;
_inputFormatterProvider = inputFormatterProvider;
_validatorProviders = validatorProviders;
@@ -54,7 +51,7 @@ namespace Microsoft.AspNet.Mvc
var context = new ActionBindingContext(
actionContext,
_modelMetadataProvider,
- new CompositeModelBinder(_modelBinders),
+ _compositeModelBinder,
new CompositeValueProvider(valueProviders),
_inputFormatterProvider,
_validatorProviders);
diff --git a/src/Microsoft.AspNet.Mvc.Core/ParameterBinding/DefaultModelBindersProvider.cs b/src/Microsoft.AspNet.Mvc.Core/ParameterBinding/DefaultModelBindersProvider.cs
new file mode 100644
index 0000000000..d5bb068a60
--- /dev/null
+++ b/src/Microsoft.AspNet.Mvc.Core/ParameterBinding/DefaultModelBindersProvider.cs
@@ -0,0 +1,57 @@
+// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved.
+// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using Microsoft.AspNet.Mvc.ModelBinding;
+using Microsoft.Framework.DependencyInjection;
+using Microsoft.Framework.OptionsModel;
+
+namespace Microsoft.AspNet.Mvc
+{
+ ///
+ public class DefaultModelBindersProvider : IModelBindersProvider
+ {
+ private readonly List _descriptors;
+ private readonly ITypeActivator _typeActivator;
+ private readonly IServiceProvider _serviceProvider;
+
+ ///
+ /// Initializes a new instance of the DefaultModelBindersProvider class.
+ ///
+ /// An accessor to the configured for this application.
+ /// An instance used to instantiate types.
+ /// A instance that retrieves services from the
+ /// service collection.
+ public DefaultModelBindersProvider(IOptionsAccessor options,
+ ITypeActivator typeActivator,
+ IServiceProvider serviceProvider)
+ {
+ _descriptors = options.Options.ModelBinders;
+ _typeActivator = typeActivator;
+ _serviceProvider = serviceProvider;
+ }
+
+ ///
+ public IReadOnlyList ModelBinders
+ {
+ get
+ {
+ var binders = new List();
+ foreach (var descriptor in _descriptors)
+ {
+ var binder = descriptor.ModelBinder;
+ if (binder == null)
+ {
+ binder = (IModelBinder)_typeActivator.CreateInstance(_serviceProvider,
+ descriptor.ModelBinderType);
+ }
+
+ binders.Add(binder);
+ }
+ return binders;
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/Microsoft.AspNet.Mvc.ModelBinding/Binders/CompositeModelBinder.cs b/src/Microsoft.AspNet.Mvc.ModelBinding/Binders/CompositeModelBinder.cs
index 5c5bd02180..206e5f6ae2 100644
--- a/src/Microsoft.AspNet.Mvc.ModelBinding/Binders/CompositeModelBinder.cs
+++ b/src/Microsoft.AspNet.Mvc.ModelBinding/Binders/CompositeModelBinder.cs
@@ -2,33 +2,45 @@
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System.Collections.Generic;
-using System.Linq;
using System.Threading.Tasks;
namespace Microsoft.AspNet.Mvc.ModelBinding
{
///
- /// This class is an that delegates to one of a collection of
- /// instances.
+ /// Represents an that delegates to one of a collection of
+ /// instances.
///
///
/// If no binder is available and the allows it,
/// this class tries to find a binder using an empty prefix.
///
- public class CompositeModelBinder : IModelBinder
+ public class CompositeModelBinder : ICompositeModelBinder
{
- public CompositeModelBinder([NotNull] IEnumerable binders)
- : this(binders.ToArray())
+ private readonly IModelBindersProvider _modelBindersProvider;
+ private IReadOnlyList _binders;
+
+ ///
+ /// Initializes a new instance of the CompositeModelBinder class.
+ ///
+ /// Provides a collection of instances.
+ public CompositeModelBinder(IModelBindersProvider modelBindersProvider)
{
+ _modelBindersProvider = modelBindersProvider;
}
- public CompositeModelBinder(params IModelBinder[] binders)
+ ///
+ public IReadOnlyList ModelBinders
{
- Binders = binders;
+ get
+ {
+ if (_binders == null)
+ {
+ _binders = _modelBindersProvider.ModelBinders;
+ }
+ return _binders;
+ }
}
- private IModelBinder[] Binders { get; set; }
-
public virtual async Task BindModelAsync([NotNull] ModelBindingContext bindingContext)
{
var newBindingContext = CreateNewBindingContext(bindingContext,
@@ -86,7 +98,7 @@ namespace Microsoft.AspNet.Mvc.ModelBinding
// Protects against stack overflow for deeply nested model binding
// RuntimeHelpers.EnsureSufficientExecutionStack();
- foreach (var binder in Binders)
+ foreach (var binder in ModelBinders)
{
if (await binder.BindModelAsync(bindingContext))
{
diff --git a/src/Microsoft.AspNet.Mvc.ModelBinding/Binders/ICompositeModelBinder.cs b/src/Microsoft.AspNet.Mvc.ModelBinding/Binders/ICompositeModelBinder.cs
new file mode 100644
index 0000000000..8e7498a282
--- /dev/null
+++ b/src/Microsoft.AspNet.Mvc.ModelBinding/Binders/ICompositeModelBinder.cs
@@ -0,0 +1,14 @@
+// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved.
+// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
+
+using System.Collections.Generic;
+
+namespace Microsoft.AspNet.Mvc.ModelBinding
+{
+ ///
+ /// Represents an aggregate of that delegates to one of the instances for model binding.
+ ///
+ public interface ICompositeModelBinder : IModelBinder
+ {
+ }
+}
diff --git a/src/Microsoft.AspNet.Mvc.ModelBinding/Binders/IModelBindersProvider.cs b/src/Microsoft.AspNet.Mvc.ModelBinding/Binders/IModelBindersProvider.cs
new file mode 100644
index 0000000000..d9d4faf172
--- /dev/null
+++ b/src/Microsoft.AspNet.Mvc.ModelBinding/Binders/IModelBindersProvider.cs
@@ -0,0 +1,18 @@
+// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved.
+// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
+
+using System.Collections.Generic;
+
+namespace Microsoft.AspNet.Mvc.ModelBinding
+{
+ ///
+ /// Provides an activated collection of instances.
+ ///
+ public interface IModelBindersProvider
+ {
+ ///
+ /// Gets a collection of activated ModelBinders instances.
+ ///
+ IReadOnlyList ModelBinders { get; }
+ }
+}
\ No newline at end of file
diff --git a/src/Microsoft.AspNet.Mvc.ModelBinding/Binders/ModelBinderDescriptor.cs b/src/Microsoft.AspNet.Mvc.ModelBinding/Binders/ModelBinderDescriptor.cs
new file mode 100644
index 0000000000..e6b75cab8a
--- /dev/null
+++ b/src/Microsoft.AspNet.Mvc.ModelBinding/Binders/ModelBinderDescriptor.cs
@@ -0,0 +1,57 @@
+// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved.
+// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
+
+using System;
+
+namespace Microsoft.AspNet.Mvc.ModelBinding
+{
+ ///
+ /// Encapsulates information that describes an .
+ ///
+ public class ModelBinderDescriptor
+ {
+ ///
+ /// Creates a new instance of .
+ ///
+ /// A
+ /// Creates a new instance of .
+ ///
+ /// An instance of that the descriptor represents.
+ public ModelBinderDescriptor([NotNull] IModelBinder modelBinder)
+ {
+ ModelBinder = modelBinder;
+ ModelBinderType = modelBinder.GetType();
+ }
+
+ ///
+ /// Gets the type of the .
+ ///
+ public Type ModelBinderType
+ {
+ get;
+ private set;
+ }
+
+ ///
+ /// Gets the instance of the .
+ ///
+ public IModelBinder ModelBinder
+ {
+ get;
+ private set;
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/Microsoft.AspNet.Mvc.ModelBinding/Binders/ModelBinderDescriptorExtensions.cs b/src/Microsoft.AspNet.Mvc.ModelBinding/Binders/ModelBinderDescriptorExtensions.cs
new file mode 100644
index 0000000000..8fe9a02883
--- /dev/null
+++ b/src/Microsoft.AspNet.Mvc.ModelBinding/Binders/ModelBinderDescriptorExtensions.cs
@@ -0,0 +1,82 @@
+// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved.
+// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
+
+using System;
+using System.Collections.Generic;
+
+namespace Microsoft.AspNet.Mvc.ModelBinding
+{
+ ///
+ /// Extension methods for adding model binders to a collection.
+ ///
+ public static class ModelBinderDescriptorExtensions
+ {
+ ///
+ /// Adds a type representing a to a descriptor collection.
+ ///
+ /// A list of ModelBinderDescriptors
+ /// Type representing an .
+ /// ModelBinderDescriptor representing the added instance.
+ public static ModelBinderDescriptor Add([NotNull] this IList descriptors,
+ [NotNull] Type modelBinderType)
+ {
+ var descriptor = new ModelBinderDescriptor(modelBinderType);
+ descriptors.Add(descriptor);
+ return descriptor;
+ }
+
+ ///
+ /// Inserts a type representing a to a descriptor collection.
+ ///
+ /// A list of ModelBinderDescriptors
+ /// Type representing an .
+ /// ModelBinderDescriptor representing the inserted instance.
+ public static ModelBinderDescriptor Insert([NotNull] this IList descriptors,
+ int index,
+ [NotNull] Type modelBinderType)
+ {
+ if (index < 0 || index > descriptors.Count)
+ {
+ throw new ArgumentOutOfRangeException("index");
+ }
+
+ var descriptor = new ModelBinderDescriptor(modelBinderType);
+ descriptors.Insert(index, descriptor);
+ return descriptor;
+ }
+
+ ///
+ /// Adds an to a descriptor collection.
+ ///
+ /// A list of ModelBinderDescriptors
+ /// An instance.
+ /// ModelBinderDescriptor representing the added instance.
+ public static ModelBinderDescriptor Add([NotNull] this IList descriptors,
+ [NotNull] IModelBinder modelBinder)
+ {
+ var descriptor = new ModelBinderDescriptor(modelBinder);
+ descriptors.Add(descriptor);
+ return descriptor;
+ }
+
+ ///
+ /// Insert an to a descriptor collection.
+ ///
+ /// A list of ModelBinderDescriptors
+ /// An instance.
+ /// ModelBinderDescriptor representing the added instance.
+ public static ModelBinderDescriptor Insert([NotNull] this IList descriptors,
+ int index,
+ [NotNull] IModelBinder modelBinder)
+ {
+ if (index < 0 || index > descriptors.Count)
+ {
+ throw new ArgumentOutOfRangeException("index");
+ }
+
+ var descriptor = new ModelBinderDescriptor(modelBinder);
+ descriptors.Insert(index, descriptor);
+ return descriptor;
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/Microsoft.AspNet.Mvc.ModelBinding/Microsoft.AspNet.Mvc.ModelBinding.kproj b/src/Microsoft.AspNet.Mvc.ModelBinding/Microsoft.AspNet.Mvc.ModelBinding.kproj
index c2dc72ddf5..b029128842 100644
--- a/src/Microsoft.AspNet.Mvc.ModelBinding/Microsoft.AspNet.Mvc.ModelBinding.kproj
+++ b/src/Microsoft.AspNet.Mvc.ModelBinding/Microsoft.AspNet.Mvc.ModelBinding.kproj
@@ -33,8 +33,12 @@
+
+
+
+
diff --git a/src/Microsoft.AspNet.Mvc/MvcServices.cs b/src/Microsoft.AspNet.Mvc/MvcServices.cs
index 4c54d12bd5..e7e937e9a7 100644
--- a/src/Microsoft.AspNet.Mvc/MvcServices.cs
+++ b/src/Microsoft.AspNet.Mvc/MvcServices.cs
@@ -44,7 +44,7 @@ namespace Microsoft.AspNet.Mvc
ReflectedActionDescriptorProvider>();
yield return describe.Transient,
ReflectedActionInvokerProvider>();
- yield return describe.Singleton();
yield return describe.Transient();
@@ -54,15 +54,12 @@ namespace Microsoft.AspNet.Mvc
yield return describe.Transient();
yield return describe.Transient();
- yield return describe.Transient();
- yield return describe.Transient();
- yield return describe.Transient();
- yield return describe.Transient();
- yield return describe.Transient();
-
yield return describe.Transient();
yield return describe.Transient();
+ yield return describe.Transient();
+ yield return describe.Transient();
+
yield return describe.Transient, DefaultFilterProvider>();
yield return describe.Transient();
@@ -72,15 +69,15 @@ namespace Microsoft.AspNet.Mvc
yield return describe.Transient();
yield return describe.Transient();
- yield return describe.Transient,
+ yield return describe.Transient,
DefaultViewComponentInvokerProvider>();
yield return describe.Transient();
yield return describe.Transient();
yield return describe.Singleton();
yield return describe.Singleton();
- yield return describe.Singleton();
+ yield return describe.Singleton();
yield return
describe.Describe(
diff --git a/test/Microsoft.AspNet.Mvc.Core.Test/Microsoft.AspNet.Mvc.Core.Test.kproj b/test/Microsoft.AspNet.Mvc.Core.Test/Microsoft.AspNet.Mvc.Core.Test.kproj
index 705ded6643..ace2c4d398 100644
--- a/test/Microsoft.AspNet.Mvc.Core.Test/Microsoft.AspNet.Mvc.Core.Test.kproj
+++ b/test/Microsoft.AspNet.Mvc.Core.Test/Microsoft.AspNet.Mvc.Core.Test.kproj
@@ -55,6 +55,7 @@
+
diff --git a/test/Microsoft.AspNet.Mvc.Core.Test/ParameterBinding/DefaultModelBindersProviderTest.cs b/test/Microsoft.AspNet.Mvc.Core.Test/ParameterBinding/DefaultModelBindersProviderTest.cs
new file mode 100644
index 0000000000..e514c8e9b9
--- /dev/null
+++ b/test/Microsoft.AspNet.Mvc.Core.Test/ParameterBinding/DefaultModelBindersProviderTest.cs
@@ -0,0 +1,46 @@
+// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved.
+// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
+
+#if NET45
+using System;
+using Microsoft.AspNet.Mvc.ModelBinding;
+using Microsoft.Framework.DependencyInjection;
+using Microsoft.Framework.OptionsModel;
+using Moq;
+using Xunit;
+
+namespace Microsoft.AspNet.Mvc.Core
+{
+ public class DefaultModelBindersProviderTest
+ {
+ [Fact]
+ public void DefaultModelBindersProvider_ProvidesInstancesOfModelBinders()
+ {
+ // Arrange
+ var binder = new TypeMatchModelBinder();
+ var options = new MvcOptions();
+ options.ModelBinders.Clear();
+ options.ModelBinders.Add(binder);
+ options.ModelBinders.Add(typeof(GenericModelBinder));
+ var optionsAccessor = new Mock>();
+ optionsAccessor.SetupGet(o => o.Options)
+ .Returns(options);
+ var activator = new Mock();
+ var serviceProvider = Mock.Of();
+ activator.Setup(a => a.CreateInstance(serviceProvider, typeof(GenericModelBinder)))
+ .Returns(new GenericModelBinder(serviceProvider, activator.Object))
+ .Verifiable();
+
+ var provider = new DefaultModelBindersProvider(optionsAccessor.Object, activator.Object, serviceProvider);
+
+ // Act
+ var binders = provider.ModelBinders;
+
+ // Assert
+ Assert.Equal(2, binders.Count);
+ Assert.Same(binder, binders[0]);
+ Assert.IsType(binders[1]);
+ }
+ }
+}
+#endif
\ No newline at end of file
diff --git a/test/Microsoft.AspNet.Mvc.ModelBinding.Test/Binders/CompositeModelBinderTest.cs b/test/Microsoft.AspNet.Mvc.ModelBinding.Test/Binders/CompositeModelBinderTest.cs
index cf72d1a2d5..3afa72fdae 100644
--- a/test/Microsoft.AspNet.Mvc.ModelBinding.Test/Binders/CompositeModelBinderTest.cs
+++ b/test/Microsoft.AspNet.Mvc.ModelBinding.Test/Binders/CompositeModelBinderTest.cs
@@ -38,7 +38,7 @@ namespace Microsoft.AspNet.Mvc.ModelBinding.Test
mockIntBinder
.Setup(o => o.BindModelAsync(It.IsAny()))
.Returns(
- delegate(ModelBindingContext context)
+ delegate (ModelBindingContext context)
{
Assert.Same(bindingContext.ModelMetadata, context.ModelMetadata);
Assert.Equal("someName", context.ModelName);
@@ -48,8 +48,7 @@ namespace Microsoft.AspNet.Mvc.ModelBinding.Test
bindingContext.ValidationNode.Validating += delegate { validationCalled = true; };
return Task.FromResult(true);
});
-
- var shimBinder = new CompositeModelBinder(mockIntBinder.Object);
+ var shimBinder = CreateCompositeBinder(mockIntBinder.Object);
// Act
var isBound = await shimBinder.BindModelAsync(bindingContext);
@@ -59,7 +58,7 @@ namespace Microsoft.AspNet.Mvc.ModelBinding.Test
Assert.Equal(42, bindingContext.Model);
Assert.True(validationCalled);
- Assert.Equal(true, bindingContext.ModelState.IsValid);
+ Assert.True(bindingContext.ModelState.IsValid);
}
[Fact]
@@ -102,7 +101,7 @@ namespace Microsoft.AspNet.Mvc.ModelBinding.Test
return Task.FromResult(true);
});
- IModelBinder shimBinder = new CompositeModelBinder(mockIntBinder.Object);
+ var shimBinder = CreateCompositeBinder(mockIntBinder.Object);
// Act
var isBound = await shimBinder.BindModelAsync(bindingContext);
@@ -146,7 +145,7 @@ namespace Microsoft.AspNet.Mvc.ModelBinding.Test
{
// Arrange
var innerBinder = Mock.Of();
- var shimBinder = new CompositeModelBinder(innerBinder);
+ var shimBinder = CreateCompositeBinder(innerBinder);
var bindingContext = new ModelBindingContext
{
@@ -300,10 +299,23 @@ namespace Microsoft.AspNet.Mvc.ModelBinding.Test
new TypeConverterModelBinder(),
new MutableObjectModelBinder()
};
- var binder = new CompositeModelBinder(binders);
+ var binderProviders = new Mock();
+ binderProviders.SetupGet(p => p.ModelBinders)
+ .Returns(binders);
+ var binder = new CompositeModelBinder(binderProviders.Object);
return binder;
}
+ private static CompositeModelBinder CreateCompositeBinder(IModelBinder mockIntBinder)
+ {
+ var binderProvider = new Mock();
+ binderProvider.SetupGet(p => p.ModelBinders)
+ .Returns(new[] { mockIntBinder });
+
+ var shimBinder = new CompositeModelBinder(binderProvider.Object);
+ return shimBinder;
+ }
+
private class SimplePropertiesModel
{
public string FirstName { get; set; }
diff --git a/test/Microsoft.AspNet.Mvc.ModelBinding.Test/Binders/KeyValuePairModelBinderTest.cs b/test/Microsoft.AspNet.Mvc.ModelBinding.Test/Binders/KeyValuePairModelBinderTest.cs
index 111001da07..c3f8f9087b 100644
--- a/test/Microsoft.AspNet.Mvc.ModelBinding.Test/Binders/KeyValuePairModelBinderTest.cs
+++ b/test/Microsoft.AspNet.Mvc.ModelBinding.Test/Binders/KeyValuePairModelBinderTest.cs
@@ -50,7 +50,10 @@ namespace Microsoft.AspNet.Mvc.ModelBinding.Test
public async Task BindModel_SubBindingSucceeds()
{
// Arrange
- var innerBinder = new CompositeModelBinder(CreateStringBinder(), CreateIntBinder());
+ var binderProviders = new Mock();
+ binderProviders.SetupGet(b => b.ModelBinders)
+ .Returns(new[] { CreateStringBinder(), CreateIntBinder() });
+ var innerBinder = new CompositeModelBinder(binderProviders.Object);
var valueProvider = new SimpleHttpValueProvider();
var bindingContext = GetBindingContext(valueProvider, innerBinder);
diff --git a/test/Microsoft.AspNet.Mvc.ModelBinding.Test/Binders/ModelBinderDescriptorExtensionsTest.cs b/test/Microsoft.AspNet.Mvc.ModelBinding.Test/Binders/ModelBinderDescriptorExtensionsTest.cs
new file mode 100644
index 0000000000..6b59a94831
--- /dev/null
+++ b/test/Microsoft.AspNet.Mvc.ModelBinding.Test/Binders/ModelBinderDescriptorExtensionsTest.cs
@@ -0,0 +1,72 @@
+// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved.
+// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
+
+#if NET45
+using System;
+using System.Collections.Generic;
+using Moq;
+using Xunit;
+
+namespace Microsoft.AspNet.Mvc.ModelBinding
+{
+ public class ModelBinderDescriptorExtensionTest
+ {
+ [Theory]
+ [InlineData(-1)]
+ [InlineData(5)]
+ public void Insert_WithType_ThrowsIfIndexIsOutOfBounds(int index)
+ {
+ // Arrange
+ var collection = new List
+ {
+ new ModelBinderDescriptor(Mock.Of()),
+ new ModelBinderDescriptor(Mock.Of())
+ };
+
+ // Act & Assert
+ Assert.Throws("index", () => collection.Insert(index, typeof(IModelBinder)));
+ }
+
+ [Theory]
+ [InlineData(-2)]
+ [InlineData(3)]
+ public void Insert_WithInstance_ThrowsIfIndexIsOutOfBounds(int index)
+ {
+ // Arrange
+ var collection = new List
+ {
+ new ModelBinderDescriptor(Mock.Of()),
+ new ModelBinderDescriptor(Mock.Of())
+ };
+ var binder = Mock.Of();
+
+ // Act & Assert
+ Assert.Throws("index", () => collection.Insert(index, binder));
+ }
+
+ [InlineData]
+ public void ModelBinderDescriptors_AddsTypesAndInstances()
+ {
+ // Arrange
+ var binder1 = Mock.Of();
+ var binder2 = Mock.Of();
+ var type1 = typeof(TypeMatchModelBinder);
+ var type2 = typeof(TypeConverterModelBinder);
+ var collection = new List();
+
+ // Act
+ collection.Add(binder1);
+ collection.Insert(1, binder2);
+ collection.Add(type1);
+ collection.Insert(2, type2);
+
+ // Assert
+ Assert.Equal(4, collection.Count);
+ Assert.Equal(binder1, collection[0].ModelBinder);
+ Assert.Equal(binder2, collection[1].ModelBinder);
+ Assert.Equal(type2, collection[2].ModelBinderType);
+ Assert.Equal(type1, collection[3].ModelBinderType);
+ }
+ }
+}
+#endif
\ No newline at end of file
diff --git a/test/Microsoft.AspNet.Mvc.ModelBinding.Test/Binders/ModelBinderDescriptorTest.cs b/test/Microsoft.AspNet.Mvc.ModelBinding.Test/Binders/ModelBinderDescriptorTest.cs
new file mode 100644
index 0000000000..e3e5f3ce25
--- /dev/null
+++ b/test/Microsoft.AspNet.Mvc.ModelBinding.Test/Binders/ModelBinderDescriptorTest.cs
@@ -0,0 +1,24 @@
+// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved.
+// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
+
+using System;
+using Microsoft.AspNet.Testing;
+using Xunit;
+
+namespace Microsoft.AspNet.Mvc.ModelBinding
+{
+ public class ModelBinderDescriptorTest
+ {
+ [Fact]
+ public void ConstructorThrows_IfTypeIsNotIModelBinder()
+ {
+ // Arrange
+ var expected = "The type 'System.String' must derive from " +
+ "'Microsoft.AspNet.Mvc.ModelBinding.IModelBinder'.";
+ var type = typeof(string);
+
+ // Act & Assert
+ ExceptionAssert.ThrowsArgument(() => new ModelBinderDescriptor(type), "modelBinderType", expected);
+ }
+ }
+}
\ No newline at end of file
diff --git a/test/Microsoft.AspNet.Mvc.ModelBinding.Test/Microsoft.AspNet.Mvc.ModelBinding.Test.kproj b/test/Microsoft.AspNet.Mvc.ModelBinding.Test/Microsoft.AspNet.Mvc.ModelBinding.Test.kproj
index c40daad21f..2851854fe0 100644
--- a/test/Microsoft.AspNet.Mvc.ModelBinding.Test/Microsoft.AspNet.Mvc.ModelBinding.Test.kproj
+++ b/test/Microsoft.AspNet.Mvc.ModelBinding.Test/Microsoft.AspNet.Mvc.ModelBinding.Test.kproj
@@ -29,6 +29,8 @@
+
+