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="ParameterBindingInfo.cs" />
|
||||||
<Compile Include="ParameterBinding\ActionBindingContext.cs" />
|
<Compile Include="ParameterBinding\ActionBindingContext.cs" />
|
||||||
<Compile Include="ParameterBinding\DefaultActionBindingContextProvider.cs" />
|
<Compile Include="ParameterBinding\DefaultActionBindingContextProvider.cs" />
|
||||||
|
<Compile Include="ParameterBinding\DefaultModelBindersProvider.cs" />
|
||||||
<Compile Include="ParameterBinding\FromBodyAttribute.cs" />
|
<Compile Include="ParameterBinding\FromBodyAttribute.cs" />
|
||||||
<Compile Include="ParameterBinding\IActionBindingContextProvider.cs" />
|
<Compile Include="ParameterBinding\IActionBindingContextProvider.cs" />
|
||||||
<Compile Include="ParameterDescriptor.cs" />
|
<Compile Include="ParameterDescriptor.cs" />
|
||||||
|
|
|
||||||
|
|
@ -4,6 +4,7 @@
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using Microsoft.AspNet.Mvc.Core;
|
using Microsoft.AspNet.Mvc.Core;
|
||||||
|
using Microsoft.AspNet.Mvc.ModelBinding;
|
||||||
using Microsoft.AspNet.Mvc.ReflectedModelBuilder;
|
using Microsoft.AspNet.Mvc.ReflectedModelBuilder;
|
||||||
|
|
||||||
namespace Microsoft.AspNet.Mvc
|
namespace Microsoft.AspNet.Mvc
|
||||||
|
|
@ -15,6 +16,14 @@ namespace Microsoft.AspNet.Mvc
|
||||||
public MvcOptions()
|
public MvcOptions()
|
||||||
{
|
{
|
||||||
ApplicationModelConventions = new List<IReflectedApplicationModelConvention>();
|
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
|
public AntiForgeryOptions AntiForgeryOptions
|
||||||
|
|
@ -28,7 +37,7 @@ namespace Microsoft.AspNet.Mvc
|
||||||
{
|
{
|
||||||
if (value == null)
|
if (value == null)
|
||||||
{
|
{
|
||||||
throw new ArgumentNullException("value",
|
throw new ArgumentNullException("value",
|
||||||
Resources.FormatPropertyOfTypeCannotBeNull("AntiForgeryOptions",
|
Resources.FormatPropertyOfTypeCannotBeNull("AntiForgeryOptions",
|
||||||
typeof(MvcOptions)));
|
typeof(MvcOptions)));
|
||||||
}
|
}
|
||||||
|
|
@ -37,6 +46,8 @@ namespace Microsoft.AspNet.Mvc
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public List<ModelBinderDescriptor> ModelBinders { get; private set; }
|
||||||
|
|
||||||
public List<IReflectedApplicationModelConvention> ApplicationModelConventions { get; private set; }
|
public List<IReflectedApplicationModelConvention> ApplicationModelConventions { get; private set; }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -6,29 +6,26 @@ using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using Microsoft.AspNet.Mvc.ModelBinding;
|
using Microsoft.AspNet.Mvc.ModelBinding;
|
||||||
using Microsoft.AspNet.Routing;
|
|
||||||
|
|
||||||
namespace Microsoft.AspNet.Mvc
|
namespace Microsoft.AspNet.Mvc
|
||||||
{
|
{
|
||||||
public class DefaultActionBindingContextProvider : IActionBindingContextProvider
|
public class DefaultActionBindingContextProvider : IActionBindingContextProvider
|
||||||
{
|
{
|
||||||
private readonly IModelMetadataProvider _modelMetadataProvider;
|
private readonly IModelMetadataProvider _modelMetadataProvider;
|
||||||
private readonly IEnumerable<IModelBinder> _modelBinders;
|
private readonly ICompositeModelBinder _compositeModelBinder;
|
||||||
private readonly IEnumerable<IValueProviderFactory> _valueProviderFactories;
|
private readonly IEnumerable<IValueProviderFactory> _valueProviderFactories;
|
||||||
private readonly IInputFormatterProvider _inputFormatterProvider;
|
private readonly IInputFormatterProvider _inputFormatterProvider;
|
||||||
private readonly IEnumerable<IModelValidatorProvider> _validatorProviders;
|
private readonly IEnumerable<IModelValidatorProvider> _validatorProviders;
|
||||||
|
|
||||||
private Tuple<ActionContext, ActionBindingContext> _bindingContext;
|
private Tuple<ActionContext, ActionBindingContext> _bindingContext;
|
||||||
|
|
||||||
public DefaultActionBindingContextProvider(IModelMetadataProvider modelMetadataProvider,
|
public DefaultActionBindingContextProvider(IModelMetadataProvider modelMetadataProvider,
|
||||||
IEnumerable<IModelBinder> modelBinders,
|
ICompositeModelBinder compositeModelBinder,
|
||||||
IEnumerable<IValueProviderFactory> valueProviderFactories,
|
IEnumerable<IValueProviderFactory> valueProviderFactories,
|
||||||
IInputFormatterProvider inputFormatterProvider,
|
IInputFormatterProvider inputFormatterProvider,
|
||||||
IEnumerable<IModelValidatorProvider> validatorProviders)
|
IEnumerable<IModelValidatorProvider> validatorProviders)
|
||||||
{
|
{
|
||||||
_modelMetadataProvider = modelMetadataProvider;
|
_modelMetadataProvider = modelMetadataProvider;
|
||||||
_modelBinders = modelBinders.OrderBy(
|
_compositeModelBinder = compositeModelBinder;
|
||||||
binder => binder.GetType() == typeof(ComplexModelDtoModelBinder) ? 1 : 0).ToArray();
|
|
||||||
_valueProviderFactories = valueProviderFactories;
|
_valueProviderFactories = valueProviderFactories;
|
||||||
_inputFormatterProvider = inputFormatterProvider;
|
_inputFormatterProvider = inputFormatterProvider;
|
||||||
_validatorProviders = validatorProviders;
|
_validatorProviders = validatorProviders;
|
||||||
|
|
@ -54,7 +51,7 @@ namespace Microsoft.AspNet.Mvc
|
||||||
var context = new ActionBindingContext(
|
var context = new ActionBindingContext(
|
||||||
actionContext,
|
actionContext,
|
||||||
_modelMetadataProvider,
|
_modelMetadataProvider,
|
||||||
new CompositeModelBinder(_modelBinders),
|
_compositeModelBinder,
|
||||||
new CompositeValueProvider(valueProviders),
|
new CompositeValueProvider(valueProviders),
|
||||||
_inputFormatterProvider,
|
_inputFormatterProvider,
|
||||||
_validatorProviders);
|
_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.
|
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||||
|
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
namespace Microsoft.AspNet.Mvc.ModelBinding
|
namespace Microsoft.AspNet.Mvc.ModelBinding
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// This class is an <see cref="IModelBinder"/> that delegates to one of a collection of
|
/// Represents an <see cref="IModelBinder"/> that delegates to one of a collection of <see cref="IModelBinder"/>
|
||||||
/// <see cref="IModelBinder"/> instances.
|
/// instances.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <remarks>
|
/// <remarks>
|
||||||
/// If no binder is available and the <see cref="ModelBindingContext"/> allows it,
|
/// If no binder is available and the <see cref="ModelBindingContext"/> allows it,
|
||||||
/// this class tries to find a binder using an empty prefix.
|
/// this class tries to find a binder using an empty prefix.
|
||||||
/// </remarks>
|
/// </remarks>
|
||||||
public class CompositeModelBinder : IModelBinder
|
public class CompositeModelBinder : ICompositeModelBinder
|
||||||
{
|
{
|
||||||
public CompositeModelBinder([NotNull] IEnumerable<IModelBinder> binders)
|
private readonly IModelBindersProvider _modelBindersProvider;
|
||||||
: this(binders.ToArray())
|
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)
|
public virtual async Task<bool> BindModelAsync([NotNull] ModelBindingContext bindingContext)
|
||||||
{
|
{
|
||||||
var newBindingContext = CreateNewBindingContext(bindingContext,
|
var newBindingContext = CreateNewBindingContext(bindingContext,
|
||||||
|
|
@ -86,7 +98,7 @@ namespace Microsoft.AspNet.Mvc.ModelBinding
|
||||||
// Protects against stack overflow for deeply nested model binding
|
// Protects against stack overflow for deeply nested model binding
|
||||||
// RuntimeHelpers.EnsureSufficientExecutionStack();
|
// RuntimeHelpers.EnsureSufficientExecutionStack();
|
||||||
|
|
||||||
foreach (var binder in Binders)
|
foreach (var binder in ModelBinders)
|
||||||
{
|
{
|
||||||
if (await binder.BindModelAsync(bindingContext))
|
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\CompositeModelBinder.cs" />
|
||||||
<Compile Include="Binders\DictionaryModelBinder.cs" />
|
<Compile Include="Binders\DictionaryModelBinder.cs" />
|
||||||
<Compile Include="Binders\GenericModelBinder.cs" />
|
<Compile Include="Binders\GenericModelBinder.cs" />
|
||||||
|
<Compile Include="Binders\ICompositeModelBinder.cs" />
|
||||||
<Compile Include="Binders\IModelBinder.cs" />
|
<Compile Include="Binders\IModelBinder.cs" />
|
||||||
|
<Compile Include="Binders\IModelBindersProvider.cs" />
|
||||||
<Compile Include="Binders\KeyValuePairModelBinder.cs" />
|
<Compile Include="Binders\KeyValuePairModelBinder.cs" />
|
||||||
|
<Compile Include="Binders\ModelBinderDescriptor.cs" />
|
||||||
|
<Compile Include="Binders\ModelBinderDescriptorExtensions.cs" />
|
||||||
<Compile Include="Binders\MutableObjectModelBinder.cs" />
|
<Compile Include="Binders\MutableObjectModelBinder.cs" />
|
||||||
<Compile Include="Binders\TypeConverterModelBinder.cs" />
|
<Compile Include="Binders\TypeConverterModelBinder.cs" />
|
||||||
<Compile Include="Binders\TypeMatchModelBinder.cs" />
|
<Compile Include="Binders\TypeMatchModelBinder.cs" />
|
||||||
|
|
|
||||||
|
|
@ -44,7 +44,7 @@ namespace Microsoft.AspNet.Mvc
|
||||||
ReflectedActionDescriptorProvider>();
|
ReflectedActionDescriptorProvider>();
|
||||||
yield return describe.Transient<INestedProvider<ActionInvokerProviderContext>,
|
yield return describe.Transient<INestedProvider<ActionInvokerProviderContext>,
|
||||||
ReflectedActionInvokerProvider>();
|
ReflectedActionInvokerProvider>();
|
||||||
yield return describe.Singleton<IActionDescriptorsCollectionProvider,
|
yield return describe.Singleton<IActionDescriptorsCollectionProvider,
|
||||||
DefaultActionDescriptorsCollectionProvider>();
|
DefaultActionDescriptorsCollectionProvider>();
|
||||||
|
|
||||||
yield return describe.Transient<IModelMetadataProvider, DataAnnotationsModelMetadataProvider>();
|
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, QueryStringValueProviderFactory>();
|
||||||
yield return describe.Transient<IValueProviderFactory, FormValueProviderFactory>();
|
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<IInputFormatter, JsonInputFormatter>();
|
||||||
yield return describe.Transient<IInputFormatterProvider, TempInputFormatterProvider>();
|
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<INestedProvider<FilterProviderContext>, DefaultFilterProvider>();
|
||||||
|
|
||||||
yield return describe.Transient<IModelValidatorProvider, DataAnnotationsModelValidatorProvider>();
|
yield return describe.Transient<IModelValidatorProvider, DataAnnotationsModelValidatorProvider>();
|
||||||
|
|
@ -72,15 +69,15 @@ namespace Microsoft.AspNet.Mvc
|
||||||
|
|
||||||
yield return describe.Transient<IViewComponentSelector, DefaultViewComponentSelector>();
|
yield return describe.Transient<IViewComponentSelector, DefaultViewComponentSelector>();
|
||||||
yield return describe.Transient<IViewComponentInvokerFactory, DefaultViewComponentInvokerFactory>();
|
yield return describe.Transient<IViewComponentInvokerFactory, DefaultViewComponentInvokerFactory>();
|
||||||
yield return describe.Transient<INestedProvider<ViewComponentInvokerProviderContext>,
|
yield return describe.Transient<INestedProvider<ViewComponentInvokerProviderContext>,
|
||||||
DefaultViewComponentInvokerProvider>();
|
DefaultViewComponentInvokerProvider>();
|
||||||
yield return describe.Transient<IViewComponentHelper, DefaultViewComponentHelper>();
|
yield return describe.Transient<IViewComponentHelper, DefaultViewComponentHelper>();
|
||||||
|
|
||||||
yield return describe.Transient<IAuthorizationService, DefaultAuthorizationService>();
|
yield return describe.Transient<IAuthorizationService, DefaultAuthorizationService>();
|
||||||
yield return describe.Singleton<IClaimUidExtractor, DefaultClaimUidExtractor>();
|
yield return describe.Singleton<IClaimUidExtractor, DefaultClaimUidExtractor>();
|
||||||
yield return describe.Singleton<AntiForgery, AntiForgery>();
|
yield return describe.Singleton<AntiForgery, AntiForgery>();
|
||||||
yield return describe.Singleton<IAntiForgeryAdditionalDataProvider,
|
yield return describe.Singleton<IAntiForgeryAdditionalDataProvider,
|
||||||
DefaultAntiForgeryAdditionalDataProvider>();
|
DefaultAntiForgeryAdditionalDataProvider>();
|
||||||
|
|
||||||
yield return
|
yield return
|
||||||
describe.Describe(
|
describe.Describe(
|
||||||
|
|
|
||||||
|
|
@ -55,6 +55,7 @@
|
||||||
<Compile Include="DefaultControllerFactoryTest.cs" />
|
<Compile Include="DefaultControllerFactoryTest.cs" />
|
||||||
<Compile Include="Filters\ResultFilterAttributeTest.cs" />
|
<Compile Include="Filters\ResultFilterAttributeTest.cs" />
|
||||||
<Compile Include="JsonResultTest.cs" />
|
<Compile Include="JsonResultTest.cs" />
|
||||||
|
<Compile Include="ParameterBinding\DefaultModelBindersProviderTest.cs" />
|
||||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||||
<Compile Include="PropertyHelperTest.cs" />
|
<Compile Include="PropertyHelperTest.cs" />
|
||||||
<Compile Include="ReflectedActionDescriptorProviderTests.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
|
mockIntBinder
|
||||||
.Setup(o => o.BindModelAsync(It.IsAny<ModelBindingContext>()))
|
.Setup(o => o.BindModelAsync(It.IsAny<ModelBindingContext>()))
|
||||||
.Returns(
|
.Returns(
|
||||||
delegate(ModelBindingContext context)
|
delegate (ModelBindingContext context)
|
||||||
{
|
{
|
||||||
Assert.Same(bindingContext.ModelMetadata, context.ModelMetadata);
|
Assert.Same(bindingContext.ModelMetadata, context.ModelMetadata);
|
||||||
Assert.Equal("someName", context.ModelName);
|
Assert.Equal("someName", context.ModelName);
|
||||||
|
|
@ -48,8 +48,7 @@ namespace Microsoft.AspNet.Mvc.ModelBinding.Test
|
||||||
bindingContext.ValidationNode.Validating += delegate { validationCalled = true; };
|
bindingContext.ValidationNode.Validating += delegate { validationCalled = true; };
|
||||||
return Task.FromResult(true);
|
return Task.FromResult(true);
|
||||||
});
|
});
|
||||||
|
var shimBinder = CreateCompositeBinder(mockIntBinder.Object);
|
||||||
var shimBinder = new CompositeModelBinder(mockIntBinder.Object);
|
|
||||||
|
|
||||||
// Act
|
// Act
|
||||||
var isBound = await shimBinder.BindModelAsync(bindingContext);
|
var isBound = await shimBinder.BindModelAsync(bindingContext);
|
||||||
|
|
@ -59,7 +58,7 @@ namespace Microsoft.AspNet.Mvc.ModelBinding.Test
|
||||||
Assert.Equal(42, bindingContext.Model);
|
Assert.Equal(42, bindingContext.Model);
|
||||||
|
|
||||||
Assert.True(validationCalled);
|
Assert.True(validationCalled);
|
||||||
Assert.Equal(true, bindingContext.ModelState.IsValid);
|
Assert.True(bindingContext.ModelState.IsValid);
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
|
|
@ -102,7 +101,7 @@ namespace Microsoft.AspNet.Mvc.ModelBinding.Test
|
||||||
return Task.FromResult(true);
|
return Task.FromResult(true);
|
||||||
});
|
});
|
||||||
|
|
||||||
IModelBinder shimBinder = new CompositeModelBinder(mockIntBinder.Object);
|
var shimBinder = CreateCompositeBinder(mockIntBinder.Object);
|
||||||
|
|
||||||
// Act
|
// Act
|
||||||
var isBound = await shimBinder.BindModelAsync(bindingContext);
|
var isBound = await shimBinder.BindModelAsync(bindingContext);
|
||||||
|
|
@ -146,7 +145,7 @@ namespace Microsoft.AspNet.Mvc.ModelBinding.Test
|
||||||
{
|
{
|
||||||
// Arrange
|
// Arrange
|
||||||
var innerBinder = Mock.Of<IModelBinder>();
|
var innerBinder = Mock.Of<IModelBinder>();
|
||||||
var shimBinder = new CompositeModelBinder(innerBinder);
|
var shimBinder = CreateCompositeBinder(innerBinder);
|
||||||
|
|
||||||
var bindingContext = new ModelBindingContext
|
var bindingContext = new ModelBindingContext
|
||||||
{
|
{
|
||||||
|
|
@ -300,10 +299,23 @@ namespace Microsoft.AspNet.Mvc.ModelBinding.Test
|
||||||
new TypeConverterModelBinder(),
|
new TypeConverterModelBinder(),
|
||||||
new MutableObjectModelBinder()
|
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;
|
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
|
private class SimplePropertiesModel
|
||||||
{
|
{
|
||||||
public string FirstName { get; set; }
|
public string FirstName { get; set; }
|
||||||
|
|
|
||||||
|
|
@ -50,7 +50,10 @@ namespace Microsoft.AspNet.Mvc.ModelBinding.Test
|
||||||
public async Task BindModel_SubBindingSucceeds()
|
public async Task BindModel_SubBindingSucceeds()
|
||||||
{
|
{
|
||||||
// Arrange
|
// 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 valueProvider = new SimpleHttpValueProvider();
|
||||||
var bindingContext = GetBindingContext(valueProvider, innerBinder);
|
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\CompositeModelBinderTest.cs" />
|
||||||
<Compile Include="Binders\DictionaryModelBinderTest.cs" />
|
<Compile Include="Binders\DictionaryModelBinderTest.cs" />
|
||||||
<Compile Include="Binders\KeyValuePairModelBinderTest.cs" />
|
<Compile Include="Binders\KeyValuePairModelBinderTest.cs" />
|
||||||
|
<Compile Include="Binders\ModelBinderDescriptorExtensionsTest.cs" />
|
||||||
|
<Compile Include="Binders\ModelBinderDescriptorTest.cs" />
|
||||||
<Compile Include="Binders\ModelBindingContextTest.cs" />
|
<Compile Include="Binders\ModelBindingContextTest.cs" />
|
||||||
<Compile Include="Binders\MutableObjectModelBinderTest.cs" />
|
<Compile Include="Binders\MutableObjectModelBinderTest.cs" />
|
||||||
<Compile Include="Binders\TypeConverterModelBinderTest.cs" />
|
<Compile Include="Binders\TypeConverterModelBinderTest.cs" />
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue