Moving model binders from DI to MvcOptions
This commit is contained in:
parent
ba506b2976
commit
3c092cb083
|
|
@ -147,6 +147,7 @@
|
|||
<Compile Include="ParameterBindingInfo.cs" />
|
||||
<Compile Include="ParameterBinding\ActionBindingContext.cs" />
|
||||
<Compile Include="ParameterBinding\DefaultActionBindingContextProvider.cs" />
|
||||
<Compile Include="ParameterBinding\DefaultModelBindersProvider.cs" />
|
||||
<Compile Include="ParameterBinding\FromBodyAttribute.cs" />
|
||||
<Compile Include="ParameterBinding\IActionBindingContextProvider.cs" />
|
||||
<Compile Include="ParameterDescriptor.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<IReflectedApplicationModelConvention>();
|
||||
ModelBinders = new List<ModelBinderDescriptor>
|
||||
{
|
||||
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<ModelBinderDescriptor> ModelBinders { get; private set; }
|
||||
|
||||
public List<IReflectedApplicationModelConvention> ApplicationModelConventions { get; private set; }
|
||||
}
|
||||
}
|
||||
|
|
@ -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<IModelBinder> _modelBinders;
|
||||
private readonly ICompositeModelBinder _compositeModelBinder;
|
||||
private readonly IEnumerable<IValueProviderFactory> _valueProviderFactories;
|
||||
private readonly IInputFormatterProvider _inputFormatterProvider;
|
||||
private readonly IEnumerable<IModelValidatorProvider> _validatorProviders;
|
||||
|
||||
private Tuple<ActionContext, ActionBindingContext> _bindingContext;
|
||||
|
||||
public DefaultActionBindingContextProvider(IModelMetadataProvider modelMetadataProvider,
|
||||
IEnumerable<IModelBinder> modelBinders,
|
||||
ICompositeModelBinder compositeModelBinder,
|
||||
IEnumerable<IValueProviderFactory> valueProviderFactories,
|
||||
IInputFormatterProvider inputFormatterProvider,
|
||||
IEnumerable<IModelValidatorProvider> 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);
|
||||
|
|
|
|||
|
|
@ -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
|
||||
{
|
||||
/// <inheritdoc />
|
||||
public class DefaultModelBindersProvider : IModelBindersProvider
|
||||
{
|
||||
private readonly List<ModelBinderDescriptor> _descriptors;
|
||||
private readonly ITypeActivator _typeActivator;
|
||||
private readonly IServiceProvider _serviceProvider;
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the DefaultModelBindersProvider class.
|
||||
/// </summary>
|
||||
/// <param name="options">An accessor to the <see cref="MvcOptions"/> configured for this application.</param>
|
||||
/// <param name="typeActivator">An <see cref="ITypeActivator"/> instance used to instantiate types.</param>
|
||||
/// <param name="serviceProvider">A <see cref="IServiceProvider"/> instance that retrieves services from the
|
||||
/// service collection.</param>
|
||||
public DefaultModelBindersProvider(IOptionsAccessor<MvcOptions> options,
|
||||
ITypeActivator typeActivator,
|
||||
IServiceProvider serviceProvider)
|
||||
{
|
||||
_descriptors = options.Options.ModelBinders;
|
||||
_typeActivator = typeActivator;
|
||||
_serviceProvider = serviceProvider;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public IReadOnlyList<IModelBinder> ModelBinders
|
||||
{
|
||||
get
|
||||
{
|
||||
var binders = new List<IModelBinder>();
|
||||
foreach (var descriptor in _descriptors)
|
||||
{
|
||||
var binder = descriptor.ModelBinder;
|
||||
if (binder == null)
|
||||
{
|
||||
binder = (IModelBinder)_typeActivator.CreateInstance(_serviceProvider,
|
||||
descriptor.ModelBinderType);
|
||||
}
|
||||
|
||||
binders.Add(binder);
|
||||
}
|
||||
return binders;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -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
|
||||
{
|
||||
/// <summary>
|
||||
/// This class is an <see cref="IModelBinder"/> that delegates to one of a collection of
|
||||
/// <see cref="IModelBinder"/> instances.
|
||||
/// Represents an <see cref="IModelBinder"/> that delegates to one of a collection of <see cref="IModelBinder"/>
|
||||
/// instances.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// If no binder is available and the <see cref="ModelBindingContext"/> allows it,
|
||||
/// this class tries to find a binder using an empty prefix.
|
||||
/// </remarks>
|
||||
public class CompositeModelBinder : IModelBinder
|
||||
public class CompositeModelBinder : ICompositeModelBinder
|
||||
{
|
||||
public CompositeModelBinder([NotNull] IEnumerable<IModelBinder> binders)
|
||||
: this(binders.ToArray())
|
||||
private readonly IModelBindersProvider _modelBindersProvider;
|
||||
private IReadOnlyList<IModelBinder> _binders;
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the CompositeModelBinder class.
|
||||
/// </summary>
|
||||
/// <param name="modelBindersProvider">Provides a collection of <see cref="IModelBinder"/> instances.</param>
|
||||
public CompositeModelBinder(IModelBindersProvider modelBindersProvider)
|
||||
{
|
||||
_modelBindersProvider = modelBindersProvider;
|
||||
}
|
||||
|
||||
public CompositeModelBinder(params IModelBinder[] binders)
|
||||
/// <inheritdoc />
|
||||
public IReadOnlyList<IModelBinder> ModelBinders
|
||||
{
|
||||
Binders = binders;
|
||||
get
|
||||
{
|
||||
if (_binders == null)
|
||||
{
|
||||
_binders = _modelBindersProvider.ModelBinders;
|
||||
}
|
||||
return _binders;
|
||||
}
|
||||
}
|
||||
|
||||
private IModelBinder[] Binders { get; set; }
|
||||
|
||||
public virtual async Task<bool> 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))
|
||||
{
|
||||
|
|
|
|||
|
|
@ -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
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents an aggregate of <see cref="IModelBinder"/> that delegates to one of the instances for model binding.
|
||||
/// </summary>
|
||||
public interface ICompositeModelBinder : IModelBinder
|
||||
{
|
||||
}
|
||||
}
|
||||
|
|
@ -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
|
||||
{
|
||||
/// <summary>
|
||||
/// Provides an activated collection of <see cref="IModelBinder"/> instances.
|
||||
/// </summary>
|
||||
public interface IModelBindersProvider
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets a collection of activated ModelBinders instances.
|
||||
/// </summary>
|
||||
IReadOnlyList<IModelBinder> ModelBinders { get; }
|
||||
}
|
||||
}
|
||||
|
|
@ -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
|
||||
{
|
||||
/// <summary>
|
||||
/// Encapsulates information that describes an <see cref="IModelBinder"/>.
|
||||
/// </summary>
|
||||
public class ModelBinderDescriptor
|
||||
{
|
||||
/// <summary>
|
||||
/// Creates a new instance of <see cref="ModelBinderDescriptor"/>.
|
||||
/// </summary>
|
||||
/// <param name="modelBinderType">A <see cref="IModelBinder/> type that the descriptor represents.</param>
|
||||
public ModelBinderDescriptor([NotNull] Type modelBinderType)
|
||||
{
|
||||
var binderType = typeof(IModelBinder);
|
||||
if (!binderType.IsAssignableFrom(modelBinderType))
|
||||
{
|
||||
var message = Resources.FormatTypeMustDeriveFromType(modelBinderType, binderType.FullName);
|
||||
throw new ArgumentException(message, "modelBinderType");
|
||||
}
|
||||
|
||||
ModelBinderType = modelBinderType;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new instance of <see cref="ModelBinderDescriptor"/>.
|
||||
/// </summary>
|
||||
/// <param name="modelBinder">An instance of <see cref="IModelBinder"/> that the descriptor represents.</param>
|
||||
public ModelBinderDescriptor([NotNull] IModelBinder modelBinder)
|
||||
{
|
||||
ModelBinder = modelBinder;
|
||||
ModelBinderType = modelBinder.GetType();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the type of the <see cref="IModelBinder"/>.
|
||||
/// </summary>
|
||||
public Type ModelBinderType
|
||||
{
|
||||
get;
|
||||
private set;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the instance of the <see cref="IModelBinder"/>.
|
||||
/// </summary>
|
||||
public IModelBinder ModelBinder
|
||||
{
|
||||
get;
|
||||
private set;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -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
|
||||
{
|
||||
/// <summary>
|
||||
/// Extension methods for adding model binders to a collection.
|
||||
/// </summary>
|
||||
public static class ModelBinderDescriptorExtensions
|
||||
{
|
||||
/// <summary>
|
||||
/// Adds a type representing a <see cref="IModelBinder"/> to a descriptor collection.
|
||||
/// </summary>
|
||||
/// <param name="descriptors">A list of ModelBinderDescriptors</param>
|
||||
/// <param name="modelBinderType">Type representing an <see cref="IModelBinder"/>.</param>
|
||||
/// <returns>ModelBinderDescriptor representing the added instance.</returns>
|
||||
public static ModelBinderDescriptor Add([NotNull] this IList<ModelBinderDescriptor> descriptors,
|
||||
[NotNull] Type modelBinderType)
|
||||
{
|
||||
var descriptor = new ModelBinderDescriptor(modelBinderType);
|
||||
descriptors.Add(descriptor);
|
||||
return descriptor;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Inserts a type representing a <see cref="IModelBinder"/> to a descriptor collection.
|
||||
/// </summary>
|
||||
/// <param name="descriptors">A list of ModelBinderDescriptors</param>
|
||||
/// <param name="modelBinderType">Type representing an <see cref="IModelBinder"/>.</param>
|
||||
/// <returns>ModelBinderDescriptor representing the inserted instance.</returns>
|
||||
public static ModelBinderDescriptor Insert([NotNull] this IList<ModelBinderDescriptor> 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;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Adds an <see cref="IModelBinder"/> to a descriptor collection.
|
||||
/// </summary>
|
||||
/// <param name="descriptors">A list of ModelBinderDescriptors</param>
|
||||
/// <param name="modelBinder">An <see cref="IModelBinder"/> instance.</param>
|
||||
/// <returns>ModelBinderDescriptor representing the added instance.</returns>
|
||||
public static ModelBinderDescriptor Add([NotNull] this IList<ModelBinderDescriptor> descriptors,
|
||||
[NotNull] IModelBinder modelBinder)
|
||||
{
|
||||
var descriptor = new ModelBinderDescriptor(modelBinder);
|
||||
descriptors.Add(descriptor);
|
||||
return descriptor;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Insert an <see cref="IModelBinder"/> to a descriptor collection.
|
||||
/// </summary>
|
||||
/// <param name="descriptors">A list of ModelBinderDescriptors</param>
|
||||
/// <param name="modelBinder">An <see cref="IModelBinder"/> instance.</param>
|
||||
/// <returns>ModelBinderDescriptor representing the added instance.</returns>
|
||||
public static ModelBinderDescriptor Insert([NotNull] this IList<ModelBinderDescriptor> 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -33,8 +33,12 @@
|
|||
<Compile Include="Binders\CompositeModelBinder.cs" />
|
||||
<Compile Include="Binders\DictionaryModelBinder.cs" />
|
||||
<Compile Include="Binders\GenericModelBinder.cs" />
|
||||
<Compile Include="Binders\ICompositeModelBinder.cs" />
|
||||
<Compile Include="Binders\IModelBinder.cs" />
|
||||
<Compile Include="Binders\IModelBindersProvider.cs" />
|
||||
<Compile Include="Binders\KeyValuePairModelBinder.cs" />
|
||||
<Compile Include="Binders\ModelBinderDescriptor.cs" />
|
||||
<Compile Include="Binders\ModelBinderDescriptorExtensions.cs" />
|
||||
<Compile Include="Binders\MutableObjectModelBinder.cs" />
|
||||
<Compile Include="Binders\TypeConverterModelBinder.cs" />
|
||||
<Compile Include="Binders\TypeMatchModelBinder.cs" />
|
||||
|
|
|
|||
|
|
@ -44,7 +44,7 @@ namespace Microsoft.AspNet.Mvc
|
|||
ReflectedActionDescriptorProvider>();
|
||||
yield return describe.Transient<INestedProvider<ActionInvokerProviderContext>,
|
||||
ReflectedActionInvokerProvider>();
|
||||
yield return describe.Singleton<IActionDescriptorsCollectionProvider,
|
||||
yield return describe.Singleton<IActionDescriptorsCollectionProvider,
|
||||
DefaultActionDescriptorsCollectionProvider>();
|
||||
|
||||
yield return describe.Transient<IModelMetadataProvider, DataAnnotationsModelMetadataProvider>();
|
||||
|
|
@ -54,15 +54,12 @@ namespace Microsoft.AspNet.Mvc
|
|||
yield return describe.Transient<IValueProviderFactory, QueryStringValueProviderFactory>();
|
||||
yield return describe.Transient<IValueProviderFactory, FormValueProviderFactory>();
|
||||
|
||||
yield return describe.Transient<IModelBinder, TypeConverterModelBinder>();
|
||||
yield return describe.Transient<IModelBinder, TypeMatchModelBinder>();
|
||||
yield return describe.Transient<IModelBinder, GenericModelBinder>();
|
||||
yield return describe.Transient<IModelBinder, MutableObjectModelBinder>();
|
||||
yield return describe.Transient<IModelBinder, ComplexModelDtoModelBinder>();
|
||||
|
||||
yield return describe.Transient<IInputFormatter, JsonInputFormatter>();
|
||||
yield return describe.Transient<IInputFormatterProvider, TempInputFormatterProvider>();
|
||||
|
||||
yield return describe.Transient<IModelBindersProvider, DefaultModelBindersProvider>();
|
||||
yield return describe.Transient<ICompositeModelBinder, CompositeModelBinder>();
|
||||
|
||||
yield return describe.Transient<INestedProvider<FilterProviderContext>, DefaultFilterProvider>();
|
||||
|
||||
yield return describe.Transient<IModelValidatorProvider, DataAnnotationsModelValidatorProvider>();
|
||||
|
|
@ -72,15 +69,15 @@ namespace Microsoft.AspNet.Mvc
|
|||
|
||||
yield return describe.Transient<IViewComponentSelector, DefaultViewComponentSelector>();
|
||||
yield return describe.Transient<IViewComponentInvokerFactory, DefaultViewComponentInvokerFactory>();
|
||||
yield return describe.Transient<INestedProvider<ViewComponentInvokerProviderContext>,
|
||||
yield return describe.Transient<INestedProvider<ViewComponentInvokerProviderContext>,
|
||||
DefaultViewComponentInvokerProvider>();
|
||||
yield return describe.Transient<IViewComponentHelper, DefaultViewComponentHelper>();
|
||||
|
||||
yield return describe.Transient<IAuthorizationService, DefaultAuthorizationService>();
|
||||
yield return describe.Singleton<IClaimUidExtractor, DefaultClaimUidExtractor>();
|
||||
yield return describe.Singleton<AntiForgery, AntiForgery>();
|
||||
yield return describe.Singleton<IAntiForgeryAdditionalDataProvider,
|
||||
DefaultAntiForgeryAdditionalDataProvider>();
|
||||
yield return describe.Singleton<IAntiForgeryAdditionalDataProvider,
|
||||
DefaultAntiForgeryAdditionalDataProvider>();
|
||||
|
||||
yield return
|
||||
describe.Describe(
|
||||
|
|
|
|||
|
|
@ -55,6 +55,7 @@
|
|||
<Compile Include="DefaultControllerFactoryTest.cs" />
|
||||
<Compile Include="Filters\ResultFilterAttributeTest.cs" />
|
||||
<Compile Include="JsonResultTest.cs" />
|
||||
<Compile Include="ParameterBinding\DefaultModelBindersProviderTest.cs" />
|
||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||
<Compile Include="PropertyHelperTest.cs" />
|
||||
<Compile Include="ReflectedActionDescriptorProviderTests.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<IOptionsAccessor<MvcOptions>>();
|
||||
optionsAccessor.SetupGet(o => o.Options)
|
||||
.Returns(options);
|
||||
var activator = new Mock<ITypeActivator>();
|
||||
var serviceProvider = Mock.Of<IServiceProvider>();
|
||||
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<GenericModelBinder>(binders[1]);
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
|
@ -38,7 +38,7 @@ namespace Microsoft.AspNet.Mvc.ModelBinding.Test
|
|||
mockIntBinder
|
||||
.Setup(o => o.BindModelAsync(It.IsAny<ModelBindingContext>()))
|
||||
.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<IModelBinder>();
|
||||
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<IModelBindersProvider>();
|
||||
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<IModelBindersProvider>();
|
||||
binderProvider.SetupGet(p => p.ModelBinders)
|
||||
.Returns(new[] { mockIntBinder });
|
||||
|
||||
var shimBinder = new CompositeModelBinder(binderProvider.Object);
|
||||
return shimBinder;
|
||||
}
|
||||
|
||||
private class SimplePropertiesModel
|
||||
{
|
||||
public string FirstName { get; set; }
|
||||
|
|
|
|||
|
|
@ -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<IModelBindersProvider>();
|
||||
binderProviders.SetupGet(b => b.ModelBinders)
|
||||
.Returns(new[] { CreateStringBinder(), CreateIntBinder() });
|
||||
var innerBinder = new CompositeModelBinder(binderProviders.Object);
|
||||
var valueProvider = new SimpleHttpValueProvider();
|
||||
var bindingContext = GetBindingContext(valueProvider, innerBinder);
|
||||
|
||||
|
|
|
|||
|
|
@ -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<ModelBinderDescriptor>
|
||||
{
|
||||
new ModelBinderDescriptor(Mock.Of<IModelBinder>()),
|
||||
new ModelBinderDescriptor(Mock.Of<IModelBinder>())
|
||||
};
|
||||
|
||||
// Act & Assert
|
||||
Assert.Throws<ArgumentOutOfRangeException>("index", () => collection.Insert(index, typeof(IModelBinder)));
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData(-2)]
|
||||
[InlineData(3)]
|
||||
public void Insert_WithInstance_ThrowsIfIndexIsOutOfBounds(int index)
|
||||
{
|
||||
// Arrange
|
||||
var collection = new List<ModelBinderDescriptor>
|
||||
{
|
||||
new ModelBinderDescriptor(Mock.Of<IModelBinder>()),
|
||||
new ModelBinderDescriptor(Mock.Of<IModelBinder>())
|
||||
};
|
||||
var binder = Mock.Of<IModelBinder>();
|
||||
|
||||
// Act & Assert
|
||||
Assert.Throws<ArgumentOutOfRangeException>("index", () => collection.Insert(index, binder));
|
||||
}
|
||||
|
||||
[InlineData]
|
||||
public void ModelBinderDescriptors_AddsTypesAndInstances()
|
||||
{
|
||||
// Arrange
|
||||
var binder1 = Mock.Of<IModelBinder>();
|
||||
var binder2 = Mock.Of<IModelBinder>();
|
||||
var type1 = typeof(TypeMatchModelBinder);
|
||||
var type2 = typeof(TypeConverterModelBinder);
|
||||
var collection = new List<ModelBinderDescriptor>();
|
||||
|
||||
// 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
|
||||
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -29,6 +29,8 @@
|
|||
<Compile Include="Binders\CompositeModelBinderTest.cs" />
|
||||
<Compile Include="Binders\DictionaryModelBinderTest.cs" />
|
||||
<Compile Include="Binders\KeyValuePairModelBinderTest.cs" />
|
||||
<Compile Include="Binders\ModelBinderDescriptorExtensionsTest.cs" />
|
||||
<Compile Include="Binders\ModelBinderDescriptorTest.cs" />
|
||||
<Compile Include="Binders\ModelBindingContextTest.cs" />
|
||||
<Compile Include="Binders\MutableObjectModelBinderTest.cs" />
|
||||
<Compile Include="Binders\TypeConverterModelBinderTest.cs" />
|
||||
|
|
|
|||
Loading…
Reference in New Issue