diff --git a/src/Microsoft.AspNetCore.Mvc.Abstractions/ModelBinding/ModelBindingContext.cs b/src/Microsoft.AspNetCore.Mvc.Abstractions/ModelBinding/ModelBindingContext.cs
index 0a1a711686..2f6f13d5fd 100644
--- a/src/Microsoft.AspNetCore.Mvc.Abstractions/ModelBinding/ModelBindingContext.cs
+++ b/src/Microsoft.AspNetCore.Mvc.Abstractions/ModelBinding/ModelBindingContext.cs
@@ -2,6 +2,7 @@
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System;
+using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc.ModelBinding.Validation;
namespace Microsoft.AspNetCore.Mvc.ModelBinding
@@ -11,6 +12,14 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding
///
public abstract class ModelBindingContext
{
+ ///
+ /// Represents the associated with this context.
+ ///
+ ///
+ /// The property setter is provided for unit testing purposes only.
+ ///
+ public abstract ActionContext ActionContext { get; set; }
+
///
/// Gets or sets a model name which is explicitly set using an .
///
@@ -27,6 +36,11 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding
///
public abstract string FieldName { get; set; }
+ ///
+ /// Gets the associated with this context.
+ ///
+ public virtual HttpContext HttpContext => ActionContext?.HttpContext;
+
///
/// Gets or sets an indication that the current binder is handling the top-level object.
///
@@ -57,6 +71,9 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding
/// Gets or sets the used to capture values
/// for properties in the object graph of the model when binding.
///
+ ///
+ /// The property setter is provided for unit testing purposes only.
+ ///
public abstract ModelStateDictionary ModelState { get; set; }
///
@@ -65,12 +82,7 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding
///
/// The property must be set to access this property.
///
- public abstract Type ModelType { get; }
-
- ///
- /// Represents the associated with this context.
- ///
- public abstract OperationBindingContext OperationBindingContext { get; set; }
+ public virtual Type ModelType => ModelMetadata.ModelType;
///
/// Gets or sets a predicate which will be evaluated for each property to determine if the property
@@ -82,6 +94,9 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding
/// Gets or sets the . Used for tracking validation state to
/// customize validation behavior for a model object.
///
+ ///
+ /// The property setter is provided for unit testing purposes only.
+ ///
public abstract ValidationStateDictionary ValidationState { get; set; }
///
diff --git a/src/Microsoft.AspNetCore.Mvc.Abstractions/ModelBinding/OperationBindingContext.cs b/src/Microsoft.AspNetCore.Mvc.Abstractions/ModelBinding/OperationBindingContext.cs
deleted file mode 100644
index e5a21af2de..0000000000
--- a/src/Microsoft.AspNetCore.Mvc.Abstractions/ModelBinding/OperationBindingContext.cs
+++ /dev/null
@@ -1,49 +0,0 @@
-// Copyright (c) .NET Foundation. 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;
-using Microsoft.AspNetCore.Http;
-using Microsoft.AspNetCore.Mvc.Formatters;
-using Microsoft.AspNetCore.Mvc.ModelBinding.Validation;
-
-namespace Microsoft.AspNetCore.Mvc.ModelBinding
-{
- ///
- /// A context that contains information specific to the current request and the action whose parameters
- /// are being model bound.
- ///
- public class OperationBindingContext
- {
- ///
- /// Gets or sets the for the current request.
- ///
- public ActionContext ActionContext { get; set; }
-
- ///
- /// Gets the for the current request.
- ///
- public HttpContext HttpContext => ActionContext.HttpContext;
-
- ///
- /// Gets or sets the set of instances associated with this context.
- ///
- public IList InputFormatters { get; set; }
-
- ///
- /// Gets unaltered value provider collection.
- /// Value providers can be filtered by specific model binders.
- ///
- public IValueProvider ValueProvider { get; set; }
-
- ///
- /// Gets or sets the associated with this context.
- ///
- public IModelMetadataProvider MetadataProvider { get; set; }
-
- ///
- /// Gets or sets the instance used for model validation with this
- /// context.
- ///
- public IModelValidatorProvider ValidatorProvider { get; set; }
- }
-}
diff --git a/src/Microsoft.AspNetCore.Mvc.Core/ControllerBase.cs b/src/Microsoft.AspNetCore.Mvc.Core/ControllerBase.cs
index dbb5e939d5..f387c03757 100644
--- a/src/Microsoft.AspNetCore.Mvc.Core/ControllerBase.cs
+++ b/src/Microsoft.AspNetCore.Mvc.Core/ControllerBase.cs
@@ -1121,9 +1121,7 @@ namespace Microsoft.AspNetCore.Mvc
MetadataProvider,
ModelBinderFactory,
valueProvider,
- ControllerContext.InputFormatters,
- ObjectValidator,
- new CompositeModelValidatorProvider(ControllerContext.ValidatorProviders));
+ ObjectValidator);
}
///
@@ -1161,9 +1159,7 @@ namespace Microsoft.AspNetCore.Mvc
MetadataProvider,
ModelBinderFactory,
new CompositeValueProvider(ControllerContext.ValueProviders),
- ControllerContext.InputFormatters,
ObjectValidator,
- new CompositeModelValidatorProvider(ControllerContext.ValidatorProviders),
includeExpressions);
}
@@ -1201,9 +1197,7 @@ namespace Microsoft.AspNetCore.Mvc
MetadataProvider,
ModelBinderFactory,
new CompositeValueProvider(ControllerContext.ValueProviders),
- ControllerContext.InputFormatters,
ObjectValidator,
- new CompositeModelValidatorProvider(ControllerContext.ValidatorProviders),
propertyFilter);
}
@@ -1249,9 +1243,7 @@ namespace Microsoft.AspNetCore.Mvc
MetadataProvider,
ModelBinderFactory,
valueProvider,
- ControllerContext.InputFormatters,
ObjectValidator,
- new CompositeModelValidatorProvider(ControllerContext.ValidatorProviders),
includeExpressions);
}
@@ -1296,9 +1288,7 @@ namespace Microsoft.AspNetCore.Mvc
MetadataProvider,
ModelBinderFactory,
valueProvider,
- ControllerContext.InputFormatters,
ObjectValidator,
- new CompositeModelValidatorProvider(ControllerContext.ValidatorProviders),
propertyFilter);
}
@@ -1335,9 +1325,7 @@ namespace Microsoft.AspNetCore.Mvc
MetadataProvider,
ModelBinderFactory,
new CompositeValueProvider(ControllerContext.ValueProviders),
- ControllerContext.InputFormatters,
- ObjectValidator,
- new CompositeModelValidatorProvider(ControllerContext.ValidatorProviders));
+ ObjectValidator);
}
///
@@ -1387,9 +1375,7 @@ namespace Microsoft.AspNetCore.Mvc
MetadataProvider,
ModelBinderFactory,
valueProvider,
- ControllerContext.InputFormatters,
ObjectValidator,
- new CompositeModelValidatorProvider(ControllerContext.ValidatorProviders),
propertyFilter);
}
@@ -1429,7 +1415,6 @@ namespace Microsoft.AspNetCore.Mvc
ObjectValidator.Validate(
ControllerContext,
- new CompositeModelValidatorProvider(ControllerContext.ValidatorProviders),
validationState: null,
prefix: prefix ?? string.Empty,
model: model);
diff --git a/src/Microsoft.AspNetCore.Mvc.Core/ControllerContext.cs b/src/Microsoft.AspNetCore.Mvc.Core/ControllerContext.cs
index a63c612f63..690a029f67 100644
--- a/src/Microsoft.AspNetCore.Mvc.Core/ControllerContext.cs
+++ b/src/Microsoft.AspNetCore.Mvc.Core/ControllerContext.cs
@@ -5,9 +5,7 @@ using System;
using System.Collections.Generic;
using Microsoft.AspNetCore.Mvc.Controllers;
using Microsoft.AspNetCore.Mvc.Core;
-using Microsoft.AspNetCore.Mvc.Formatters;
using Microsoft.AspNetCore.Mvc.ModelBinding;
-using Microsoft.AspNetCore.Mvc.ModelBinding.Validation;
namespace Microsoft.AspNetCore.Mvc
{
@@ -16,8 +14,6 @@ namespace Microsoft.AspNetCore.Mvc
///
public class ControllerContext : ActionContext
{
- private FormatterCollection _inputFormatters;
- private IList _validatorProviders;
private IList _valueProviders;
///
@@ -55,56 +51,6 @@ namespace Microsoft.AspNetCore.Mvc
set { base.ActionDescriptor = value; }
}
- ///
- /// Gets or sets the list of instances for the current request.
- ///
- public virtual FormatterCollection InputFormatters
- {
- get
- {
- if (_inputFormatters == null)
- {
- _inputFormatters = new FormatterCollection();
- }
-
- return _inputFormatters;
- }
- set
- {
- if (value == null)
- {
- throw new ArgumentNullException(nameof(value));
- }
-
- _inputFormatters = value;
- }
- }
-
- ///
- /// Gets or sets the list of instances for the current request.
- ///
- public virtual IList ValidatorProviders
- {
- get
- {
- if (_validatorProviders == null)
- {
- _validatorProviders = new List();
- }
-
- return _validatorProviders;
- }
- set
- {
- if (value == null)
- {
- throw new ArgumentNullException(nameof(value));
- }
-
- _validatorProviders = value;
- }
- }
-
///
/// Gets or sets the list of instances for the current request.
///
diff --git a/src/Microsoft.AspNetCore.Mvc.Core/DependencyInjection/MvcCoreServiceCollectionExtensions.cs b/src/Microsoft.AspNetCore.Mvc.Core/DependencyInjection/MvcCoreServiceCollectionExtensions.cs
index 17b5c83db8..1d1a4eb3e2 100644
--- a/src/Microsoft.AspNetCore.Mvc.Core/DependencyInjection/MvcCoreServiceCollectionExtensions.cs
+++ b/src/Microsoft.AspNetCore.Mvc.Core/DependencyInjection/MvcCoreServiceCollectionExtensions.cs
@@ -178,18 +178,22 @@ namespace Microsoft.Extensions.DependencyInjection
ServiceDescriptor.Singleton());
//
- // ModelBinding, Validation and Formatting
+ // ModelBinding, Validation
//
// The DefaultModelMetadataProvider does significant caching and should be a singleton.
services.TryAddSingleton();
- services.TryAdd(ServiceDescriptor.Transient(serviceProvider =>
+ services.TryAdd(ServiceDescriptor.Transient(s =>
{
- var options = serviceProvider.GetRequiredService>().Value;
+ var options = s.GetRequiredService>().Value;
return new DefaultCompositeMetadataDetailsProvider(options.ModelMetadataDetailsProviders);
}));
services.TryAddSingleton();
- services.TryAddSingleton();
- services.TryAddSingleton();
+ services.TryAddSingleton(s =>
+ {
+ var options = s.GetRequiredService>().Value;
+ var metadataProvider = s.GetRequiredService();
+ return new DefaultObjectValidator(metadataProvider, options.ModelValidatorProviders);
+ });
services.TryAddSingleton();
//
diff --git a/src/Microsoft.AspNetCore.Mvc.Core/Internal/ControllerActionInvoker.cs b/src/Microsoft.AspNetCore.Mvc.Core/Internal/ControllerActionInvoker.cs
index 21367a6e52..522194bbc6 100644
--- a/src/Microsoft.AspNetCore.Mvc.Core/Internal/ControllerActionInvoker.cs
+++ b/src/Microsoft.AspNetCore.Mvc.Core/Internal/ControllerActionInvoker.cs
@@ -13,7 +13,6 @@ using Microsoft.AspNetCore.Mvc.Core;
using Microsoft.AspNetCore.Mvc.Filters;
using Microsoft.AspNetCore.Mvc.Formatters;
using Microsoft.AspNetCore.Mvc.ModelBinding;
-using Microsoft.AspNetCore.Mvc.ModelBinding.Validation;
using Microsoft.Extensions.Internal;
using Microsoft.Extensions.Logging;
@@ -32,7 +31,6 @@ namespace Microsoft.AspNetCore.Mvc.Internal
ControllerActionDescriptor descriptor,
IReadOnlyList inputFormatters,
IControllerActionArgumentBinder argumentBinder,
- IReadOnlyList modelValidatorProviders,
IReadOnlyList valueProviderFactories,
ILogger logger,
DiagnosticSource diagnosticSource,
@@ -41,7 +39,6 @@ namespace Microsoft.AspNetCore.Mvc.Internal
actionContext,
controllerActionInvokerCache,
inputFormatters,
- modelValidatorProviders,
valueProviderFactories,
logger,
diagnosticSource,
diff --git a/src/Microsoft.AspNetCore.Mvc.Core/Internal/ControllerActionInvokerProvider.cs b/src/Microsoft.AspNetCore.Mvc.Core/Internal/ControllerActionInvokerProvider.cs
index adab7bde3f..c1dfed330b 100644
--- a/src/Microsoft.AspNetCore.Mvc.Core/Internal/ControllerActionInvokerProvider.cs
+++ b/src/Microsoft.AspNetCore.Mvc.Core/Internal/ControllerActionInvokerProvider.cs
@@ -21,7 +21,6 @@ namespace Microsoft.AspNetCore.Mvc.Internal
private readonly IControllerFactory _controllerFactory;
private readonly ControllerActionInvokerCache _controllerActionInvokerCache;
private readonly IReadOnlyList _inputFormatters;
- private readonly IReadOnlyList _modelValidatorProviders;
private readonly IReadOnlyList _valueProviderFactories;
private readonly int _maxModelValidationErrors;
private readonly ILogger _logger;
@@ -39,7 +38,6 @@ namespace Microsoft.AspNetCore.Mvc.Internal
_controllerActionInvokerCache = controllerActionInvokerCache;
_argumentBinder = argumentBinder;
_inputFormatters = optionsAccessor.Value.InputFormatters.ToArray();
- _modelValidatorProviders = optionsAccessor.Value.ModelValidatorProviders.ToArray();
_valueProviderFactories = optionsAccessor.Value.ValueProviderFactories.ToArray();
_maxModelValidationErrors = optionsAccessor.Value.MaxModelValidationErrors;
_logger = loggerFactory.CreateLogger();
@@ -70,7 +68,6 @@ namespace Microsoft.AspNetCore.Mvc.Internal
actionDescriptor,
_inputFormatters,
_argumentBinder,
- _modelValidatorProviders,
_valueProviderFactories,
_logger,
_diagnosticSource,
diff --git a/src/Microsoft.AspNetCore.Mvc.Core/Internal/ControllerArgumentBinder.cs b/src/Microsoft.AspNetCore.Mvc.Core/Internal/ControllerArgumentBinder.cs
index dba8f14fb8..72341226ff 100644
--- a/src/Microsoft.AspNetCore.Mvc.Core/Internal/ControllerArgumentBinder.cs
+++ b/src/Microsoft.AspNetCore.Mvc.Core/Internal/ControllerArgumentBinder.cs
@@ -39,12 +39,12 @@ namespace Microsoft.AspNetCore.Mvc.Internal
}
public Task> BindActionArgumentsAsync(
- ControllerContext context,
+ ControllerContext controllerContext,
object controller)
{
- if (context == null)
+ if (controllerContext == null)
{
- throw new ArgumentNullException(nameof(context));
+ throw new ArgumentNullException(nameof(controllerContext));
}
if (controller == null)
@@ -52,7 +52,7 @@ namespace Microsoft.AspNetCore.Mvc.Internal
throw new ArgumentNullException(nameof(controller));
}
- if (context.ActionDescriptor == null)
+ if (controllerContext.ActionDescriptor == null)
{
throw new ArgumentException(Resources.FormatPropertyOfTypeCannotBeNull(
nameof(ControllerContext.ActionDescriptor),
@@ -61,7 +61,7 @@ namespace Microsoft.AspNetCore.Mvc.Internal
// Perf: Avoid allocating async state machines where possible. We only need the state
// machine if you need to bind properties.
- var actionDescriptor = context.ActionDescriptor;
+ var actionDescriptor = controllerContext.ActionDescriptor;
if (actionDescriptor.BoundProperties.Count == 0 &&
actionDescriptor.Parameters.Count == 0)
{
@@ -70,53 +70,51 @@ namespace Microsoft.AspNetCore.Mvc.Internal
}
else if (actionDescriptor.BoundProperties.Count == 0)
{
- var operationBindingContext = GetOperationBindingContext(context);
- return PopulateArgumentsAsync(operationBindingContext, actionDescriptor.Parameters);
+ return PopulateArgumentsAsync(controllerContext, actionDescriptor.Parameters);
}
else
{
return BindActionArgumentsAndPropertiesCoreAsync(
- context,
+ controllerContext,
controller,
actionDescriptor);
}
}
private async Task> BindActionArgumentsAndPropertiesCoreAsync(
- ControllerContext context,
+ ControllerContext controllerContext,
object controller,
ControllerActionDescriptor actionDescriptor)
{
- var operationBindingContext = GetOperationBindingContext(context);
-
var controllerProperties = await PopulateArgumentsAsync(
- operationBindingContext,
+ controllerContext,
actionDescriptor.BoundProperties);
ActivateProperties(actionDescriptor, controller, controllerProperties);
var actionArguments = await PopulateArgumentsAsync(
- operationBindingContext,
+ controllerContext,
actionDescriptor.Parameters);
return actionArguments;
}
public async Task BindModelAsync(
ParameterDescriptor parameter,
- OperationBindingContext operationContext)
+ ControllerContext controllerContext)
{
if (parameter == null)
{
throw new ArgumentNullException(nameof(parameter));
}
- if (operationContext == null)
+ if (controllerContext == null)
{
- throw new ArgumentNullException(nameof(operationContext));
+ throw new ArgumentNullException(nameof(controllerContext));
}
var metadata = _modelMetadataProvider.GetMetadataForType(parameter.ParameterType);
var modelBindingContext = DefaultModelBindingContext.CreateBindingContext(
- operationContext,
+ controllerContext,
+ new CompositeValueProvider(controllerContext.ValueProviders),
metadata,
parameter.BindingInfo,
parameter.Name);
@@ -150,8 +148,7 @@ namespace Microsoft.AspNetCore.Mvc.Internal
if (modelBindingResult != null && modelBindingResult.Value.IsModelSet)
{
_validator.Validate(
- operationContext.ActionContext,
- operationContext.ValidatorProvider,
+ controllerContext,
modelBindingContext.ValidationState,
modelBindingResult.Value.Key,
modelBindingResult.Value.Model);
@@ -243,16 +240,16 @@ namespace Microsoft.AspNetCore.Mvc.Internal
}
private async Task> PopulateArgumentsAsync(
- OperationBindingContext operationContext,
- IList parameterMetadata)
+ ControllerContext controllerContext,
+ IList parameters)
{
var arguments = new Dictionary(StringComparer.Ordinal);
// Perf: Avoid allocations
- for (var i = 0; i < parameterMetadata.Count; i++)
+ for (var i = 0; i < parameters.Count; i++)
{
- var parameter = parameterMetadata[i];
- var modelBindingResult = await BindModelAsync(parameter, operationContext);
+ var parameter = parameters[i];
+ var modelBindingResult = await BindModelAsync(parameter, controllerContext);
if (modelBindingResult != null && modelBindingResult.Value.IsModelSet)
{
arguments[parameter.Name] = modelBindingResult.Value.Model;
@@ -261,17 +258,5 @@ namespace Microsoft.AspNetCore.Mvc.Internal
return arguments;
}
-
- private OperationBindingContext GetOperationBindingContext(ControllerContext context)
- {
- return new OperationBindingContext
- {
- ActionContext = context,
- InputFormatters = context.InputFormatters,
- ValidatorProvider = new CompositeModelValidatorProvider(context.ValidatorProviders),
- MetadataProvider = _modelMetadataProvider,
- ValueProvider = new CompositeValueProvider(context.ValueProviders),
- };
- }
}
}
diff --git a/src/Microsoft.AspNetCore.Mvc.Core/Internal/DefaultModelBindingContext.cs b/src/Microsoft.AspNetCore.Mvc.Core/Internal/DefaultModelBindingContext.cs
index a0e3025fe9..b6ee8319d9 100644
--- a/src/Microsoft.AspNetCore.Mvc.Core/Internal/DefaultModelBindingContext.cs
+++ b/src/Microsoft.AspNetCore.Mvc.Core/Internal/DefaultModelBindingContext.cs
@@ -12,7 +12,10 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding
///
public class DefaultModelBindingContext : ModelBindingContext
{
- private OperationBindingContext _operationBindingContext;
+ private IValueProvider _originalValueProvider;
+ private ActionContext _actionContext;
+ private ModelStateDictionary _modelState;
+ private ValidationStateDictionary _validationState;
private State _state;
private readonly Stack _stack = new Stack();
@@ -24,138 +27,17 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding
{
}
- ///
- /// Creates a new for top-level model binding operation.
- ///
- ///
- /// The associated with the binding operation.
- ///
- /// associated with the model.
- /// associated with the model.
- /// The name of the property or parameter being bound.
- /// A new instance of .
- public static ModelBindingContext CreateBindingContext(
- OperationBindingContext operationBindingContext,
- ModelMetadata metadata,
- BindingInfo bindingInfo,
- string modelName)
- {
- if (operationBindingContext == null)
- {
- throw new ArgumentNullException(nameof(operationBindingContext));
- }
-
- if (metadata == null)
- {
- throw new ArgumentNullException(nameof(metadata));
- }
-
- if (modelName == null)
- {
- throw new ArgumentNullException(nameof(modelName));
- }
-
- var binderModelName = bindingInfo?.BinderModelName ?? metadata.BinderModelName;
- var propertyFilterProvider = bindingInfo?.PropertyFilterProvider ?? metadata.PropertyFilterProvider;
-
- var valueProvider = operationBindingContext.ValueProvider;
- var bindingSource = bindingInfo?.BindingSource ?? metadata.BindingSource;
- if (bindingSource != null && !bindingSource.IsGreedy)
- {
- valueProvider = FilterValueProvider(operationBindingContext.ValueProvider, bindingSource);
- }
-
- return new DefaultModelBindingContext()
- {
- BinderModelName = binderModelName,
- BindingSource = bindingSource,
- PropertyFilter = propertyFilterProvider?.PropertyFilter,
-
- // Because this is the top-level context, FieldName and ModelName should be the same.
- FieldName = binderModelName ?? modelName,
- ModelName = binderModelName ?? modelName,
-
- IsTopLevelObject = true,
- ModelMetadata = metadata,
- ModelState = operationBindingContext.ActionContext.ModelState,
- OperationBindingContext = operationBindingContext,
- ValueProvider = valueProvider,
-
- ValidationState = new ValidationStateDictionary(),
- };
- }
-
///
- public override NestedScope EnterNestedScope(
- ModelMetadata modelMetadata,
- string fieldName,
- string modelName,
- object model)
+ public override ActionContext ActionContext
{
- if (modelMetadata == null)
- {
- throw new ArgumentNullException(nameof(modelMetadata));
- }
-
- if (fieldName == null)
- {
- throw new ArgumentNullException(nameof(fieldName));
- }
-
- if (modelName == null)
- {
- throw new ArgumentNullException(nameof(modelName));
- }
-
- var scope = EnterNestedScope();
-
- // Only filter if the new BindingSource affects the value providers. Otherwise we want
- // to preserve the currrent state.
- if (modelMetadata.BindingSource != null && !modelMetadata.BindingSource.IsGreedy)
- {
- ValueProvider = FilterValueProvider(_operationBindingContext.ValueProvider, modelMetadata.BindingSource);
- }
-
- Model = model;
- ModelMetadata = modelMetadata;
- ModelName = modelName;
- FieldName = fieldName;
- BinderModelName = modelMetadata.BinderModelName;
- BindingSource = modelMetadata.BindingSource;
- PropertyFilter = modelMetadata.PropertyFilterProvider?.PropertyFilter;
-
- IsTopLevelObject = false;
-
- return scope;
- }
-
- ///
- public override NestedScope EnterNestedScope()
- {
- _stack.Push(_state);
-
- Result = null;
-
- return new NestedScope(this);
- }
-
- ///
- protected override void ExitNestedScope()
- {
- _state = _stack.Pop();
- }
-
- ///
- public override OperationBindingContext OperationBindingContext
- {
- get { return _operationBindingContext; }
+ get { return _actionContext; }
set
{
if (value == null)
{
throw new ArgumentNullException(nameof(value));
}
- _operationBindingContext = value;
+ _actionContext = value;
}
}
@@ -211,20 +93,17 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding
///
public override ModelStateDictionary ModelState
{
- get { return _state.ModelState; }
+ get { return _modelState; }
set
{
if (value == null)
{
throw new ArgumentNullException(nameof(value));
}
- _state.ModelState = value;
+ _modelState = value;
}
}
- ///
- public override Type ModelType => ModelMetadata?.ModelType;
-
///
public override string BinderModelName
{
@@ -246,6 +125,22 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding
set { _state.IsTopLevelObject = value; }
}
+ ///
+ /// Gets or sets the original value provider to be used when value providers are not filtered.
+ ///
+ public IValueProvider OriginalValueProvider
+ {
+ get { return _originalValueProvider; }
+ set
+ {
+ if (value == null)
+ {
+ throw new ArgumentNullException(nameof(value));
+ }
+ _originalValueProvider = value;
+ }
+ }
+
///
public override IValueProvider ValueProvider
{
@@ -270,8 +165,15 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding
///
public override ValidationStateDictionary ValidationState
{
- get { return _state.ValidationState; }
- set { _state.ValidationState = value; }
+ get { return _validationState; }
+ set
+ {
+ if (value == null)
+ {
+ throw new ArgumentNullException(nameof(value));
+ }
+ _validationState = value;
+ }
}
///
@@ -292,6 +194,131 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding
}
}
+ ///
+ /// Creates a new for top-level model binding operation.
+ ///
+ ///
+ /// The associated with the binding operation.
+ ///
+ /// The to use for binding.
+ /// associated with the model.
+ /// associated with the model.
+ /// The name of the property or parameter being bound.
+ /// A new instance of .
+ public static ModelBindingContext CreateBindingContext(
+ ActionContext actionContext,
+ IValueProvider valueProvider,
+ ModelMetadata metadata,
+ BindingInfo bindingInfo,
+ string modelName)
+ {
+ if (actionContext == null)
+ {
+ throw new ArgumentNullException(nameof(actionContext));
+ }
+
+ if (valueProvider == null)
+ {
+ throw new ArgumentNullException(nameof(valueProvider));
+ }
+
+ if (metadata == null)
+ {
+ throw new ArgumentNullException(nameof(metadata));
+ }
+
+ if (modelName == null)
+ {
+ throw new ArgumentNullException(nameof(modelName));
+ }
+
+ var binderModelName = bindingInfo?.BinderModelName ?? metadata.BinderModelName;
+ var propertyFilterProvider = bindingInfo?.PropertyFilterProvider ?? metadata.PropertyFilterProvider;
+
+ var bindingSource = bindingInfo?.BindingSource ?? metadata.BindingSource;
+
+ return new DefaultModelBindingContext()
+ {
+ ActionContext = actionContext,
+ BinderModelName = binderModelName,
+ BindingSource = bindingSource,
+ PropertyFilter = propertyFilterProvider?.PropertyFilter,
+
+ // Because this is the top-level context, FieldName and ModelName should be the same.
+ FieldName = binderModelName ?? modelName,
+ ModelName = binderModelName ?? modelName,
+
+ IsTopLevelObject = true,
+ ModelMetadata = metadata,
+ ModelState = actionContext.ModelState,
+
+ OriginalValueProvider = valueProvider,
+ ValueProvider = FilterValueProvider(valueProvider, bindingSource),
+
+ ValidationState = new ValidationStateDictionary(),
+ };
+ }
+
+ ///
+ public override NestedScope EnterNestedScope(
+ ModelMetadata modelMetadata,
+ string fieldName,
+ string modelName,
+ object model)
+ {
+ if (modelMetadata == null)
+ {
+ throw new ArgumentNullException(nameof(modelMetadata));
+ }
+
+ if (fieldName == null)
+ {
+ throw new ArgumentNullException(nameof(fieldName));
+ }
+
+ if (modelName == null)
+ {
+ throw new ArgumentNullException(nameof(modelName));
+ }
+
+ var scope = EnterNestedScope();
+
+ // Only filter if the new BindingSource affects the value providers. Otherwise we want
+ // to preserve the currrent state.
+ if (modelMetadata.BindingSource != null && !modelMetadata.BindingSource.IsGreedy)
+ {
+ ValueProvider = FilterValueProvider(OriginalValueProvider, modelMetadata.BindingSource);
+ }
+
+ Model = model;
+ ModelMetadata = modelMetadata;
+ ModelName = modelName;
+ FieldName = fieldName;
+ BinderModelName = modelMetadata.BinderModelName;
+ BindingSource = modelMetadata.BindingSource;
+ PropertyFilter = modelMetadata.PropertyFilterProvider?.PropertyFilter;
+
+ IsTopLevelObject = false;
+
+ return scope;
+ }
+
+ ///
+ public override NestedScope EnterNestedScope()
+ {
+ _stack.Push(_state);
+
+ Result = null;
+
+ return new NestedScope(this);
+ }
+
+ ///
+ protected override void ExitNestedScope()
+ {
+ _state = _stack.Pop();
+ }
+
private static IValueProvider FilterValueProvider(IValueProvider valueProvider, BindingSource bindingSource)
{
if (bindingSource == null || bindingSource.IsGreedy)
@@ -317,8 +344,6 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding
public IValueProvider ValueProvider;
public Func PropertyFilter;
- public ValidationStateDictionary ValidationState;
- public ModelStateDictionary ModelState;
public string BinderModelName;
public BindingSource BindingSource;
diff --git a/src/Microsoft.AspNetCore.Mvc.Core/Internal/DefaultObjectValidator.cs b/src/Microsoft.AspNetCore.Mvc.Core/Internal/DefaultObjectValidator.cs
index dbdceb5f85..695b7d6aaf 100644
--- a/src/Microsoft.AspNetCore.Mvc.Core/Internal/DefaultObjectValidator.cs
+++ b/src/Microsoft.AspNetCore.Mvc.Core/Internal/DefaultObjectValidator.cs
@@ -2,6 +2,7 @@
// 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 Microsoft.AspNetCore.Mvc.ModelBinding;
using Microsoft.AspNetCore.Mvc.ModelBinding.Validation;
@@ -14,34 +15,36 @@ namespace Microsoft.AspNetCore.Mvc.Internal
{
private readonly IModelMetadataProvider _modelMetadataProvider;
private readonly ValidatorCache _validatorCache;
+ private readonly IModelValidatorProvider _validatorProvider;
///
/// Initializes a new instance of .
///
/// The .
- /// The .
+ /// The list of .
public DefaultObjectValidator(
IModelMetadataProvider modelMetadataProvider,
- ValidatorCache validatorCache)
+ IList validatorProviders)
{
if (modelMetadataProvider == null)
{
throw new ArgumentNullException(nameof(modelMetadataProvider));
}
- if (validatorCache == null)
+ if (validatorProviders == null)
{
- throw new ArgumentNullException(nameof(validatorCache));
+ throw new ArgumentNullException(nameof(validatorProviders));
}
_modelMetadataProvider = modelMetadataProvider;
- _validatorCache = validatorCache;
+ _validatorCache = new ValidatorCache();
+
+ _validatorProvider = new CompositeModelValidatorProvider(validatorProviders);
}
///
public void Validate(
ActionContext actionContext,
- IModelValidatorProvider validatorProvider,
ValidationStateDictionary validationState,
string prefix,
object model)
@@ -51,14 +54,9 @@ namespace Microsoft.AspNetCore.Mvc.Internal
throw new ArgumentNullException(nameof(actionContext));
}
- if (validatorProvider == null)
- {
- throw new ArgumentNullException(nameof(validatorProvider));
- }
-
var visitor = new ValidationVisitor(
actionContext,
- validatorProvider,
+ _validatorProvider,
_validatorCache,
_modelMetadataProvider,
validationState);
diff --git a/src/Microsoft.AspNetCore.Mvc.Core/Internal/FilterActionInvoker.cs b/src/Microsoft.AspNetCore.Mvc.Core/Internal/FilterActionInvoker.cs
index 49ec7321ba..4861c03d56 100644
--- a/src/Microsoft.AspNetCore.Mvc.Core/Internal/FilterActionInvoker.cs
+++ b/src/Microsoft.AspNetCore.Mvc.Core/Internal/FilterActionInvoker.cs
@@ -20,7 +20,6 @@ namespace Microsoft.AspNetCore.Mvc.Internal
{
private readonly ControllerActionInvokerCache _controllerActionInvokerCache;
private readonly IReadOnlyList _inputFormatters;
- private readonly IReadOnlyList _modelValidatorProviders;
private readonly IReadOnlyList _valueProviderFactories;
private readonly DiagnosticSource _diagnosticSource;
private readonly int _maxModelValidationErrors;
@@ -46,7 +45,6 @@ namespace Microsoft.AspNetCore.Mvc.Internal
ActionContext actionContext,
ControllerActionInvokerCache controllerActionInvokerCache,
IReadOnlyList inputFormatters,
- IReadOnlyList modelValidatorProviders,
IReadOnlyList valueProviderFactories,
ILogger logger,
DiagnosticSource diagnosticSource,
@@ -67,11 +65,6 @@ namespace Microsoft.AspNetCore.Mvc.Internal
throw new ArgumentNullException(nameof(inputFormatters));
}
- if (modelValidatorProviders == null)
- {
- throw new ArgumentNullException(nameof(modelValidatorProviders));
- }
-
if (valueProviderFactories == null)
{
throw new ArgumentNullException(nameof(valueProviderFactories));
@@ -91,7 +84,6 @@ namespace Microsoft.AspNetCore.Mvc.Internal
_controllerActionInvokerCache = controllerActionInvokerCache;
_inputFormatters = inputFormatters;
- _modelValidatorProviders = modelValidatorProviders;
_valueProviderFactories = valueProviderFactories;
Logger = logger;
_diagnosticSource = diagnosticSource;
@@ -346,10 +338,6 @@ namespace Microsoft.AspNetCore.Mvc.Internal
{
// We've reached the end of resource filters, so move to setting up state to invoke model
// binding.
- Context.InputFormatters = new FormatterCollection(
- new CopyOnWriteList(_inputFormatters));
- Context.ValidatorProviders = new CopyOnWriteList(_modelValidatorProviders);
-
var valueProviders = new List();
var factoryContext = new ValueProviderFactoryContext(Context);
diff --git a/src/Microsoft.AspNetCore.Mvc.Core/Internal/MvcCoreMvcOptionsSetup.cs b/src/Microsoft.AspNetCore.Mvc.Core/Internal/MvcCoreMvcOptionsSetup.cs
index 713a1278c8..b71ab8554f 100644
--- a/src/Microsoft.AspNetCore.Mvc.Core/Internal/MvcCoreMvcOptionsSetup.cs
+++ b/src/Microsoft.AspNetCore.Mvc.Core/Internal/MvcCoreMvcOptionsSetup.cs
@@ -46,7 +46,7 @@ namespace Microsoft.AspNetCore.Mvc.Internal
// Set up ModelBinding
options.ModelBinderProviders.Add(new BinderTypeModelBinderProvider());
options.ModelBinderProviders.Add(new ServicesModelBinderProvider());
- options.ModelBinderProviders.Add(new BodyModelBinderProvider(_readerFactory));
+ options.ModelBinderProviders.Add(new BodyModelBinderProvider(options.InputFormatters, _readerFactory));
options.ModelBinderProviders.Add(new HeaderModelBinderProvider());
options.ModelBinderProviders.Add(new SimpleTypeModelBinderProvider());
options.ModelBinderProviders.Add(new CancellationTokenModelBinderProvider());
diff --git a/src/Microsoft.AspNetCore.Mvc.Core/ModelBinding/Binders/BinderTypeModelBinder.cs b/src/Microsoft.AspNetCore.Mvc.Core/ModelBinding/Binders/BinderTypeModelBinder.cs
index 4de5f164f4..3aa7b7b5ac 100644
--- a/src/Microsoft.AspNetCore.Mvc.Core/ModelBinding/Binders/BinderTypeModelBinder.cs
+++ b/src/Microsoft.AspNetCore.Mvc.Core/ModelBinding/Binders/BinderTypeModelBinder.cs
@@ -48,7 +48,7 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding.Binders
throw new ArgumentNullException(nameof(bindingContext));
}
- var requestServices = bindingContext.OperationBindingContext.HttpContext.RequestServices;
+ var requestServices = bindingContext.HttpContext.RequestServices;
var binder = (IModelBinder)_factory(requestServices, arguments: null);
await binder.BindModelAsync(bindingContext);
diff --git a/src/Microsoft.AspNetCore.Mvc.Core/ModelBinding/Binders/BodyModelBinder.cs b/src/Microsoft.AspNetCore.Mvc.Core/ModelBinding/Binders/BodyModelBinder.cs
index b5cd8a422f..36de8bb856 100644
--- a/src/Microsoft.AspNetCore.Mvc.Core/ModelBinding/Binders/BodyModelBinder.cs
+++ b/src/Microsoft.AspNetCore.Mvc.Core/ModelBinding/Binders/BodyModelBinder.cs
@@ -2,8 +2,8 @@
// 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.IO;
-using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc.Core;
@@ -18,17 +18,30 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding.Binders
///
public class BodyModelBinder : IModelBinder
{
+ private readonly IList _formatters;
private readonly Func _readerFactory;
///
/// Creates a new .
///
+ /// The list of .
///
/// The , used to create
/// instances for reading the request body.
///
- public BodyModelBinder(IHttpRequestStreamReaderFactory readerFactory)
+ public BodyModelBinder(IList formatters, IHttpRequestStreamReaderFactory readerFactory)
{
+ if (formatters == null)
+ {
+ throw new ArgumentNullException(nameof(formatters));
+ }
+
+ if (readerFactory == null)
+ {
+ throw new ArgumentNullException(nameof(readerFactory));
+ }
+
+ _formatters = formatters;
_readerFactory = readerFactory.CreateReader;
}
@@ -53,7 +66,7 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding.Binders
modelBindingKey = bindingContext.ModelName;
}
- var httpContext = bindingContext.OperationBindingContext.HttpContext;
+ var httpContext = bindingContext.HttpContext;
var formatterContext = new InputFormatterContext(
httpContext,
@@ -62,13 +75,19 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding.Binders
bindingContext.ModelMetadata,
_readerFactory);
- var formatters = bindingContext.OperationBindingContext.InputFormatters;
- var formatter = formatters.FirstOrDefault(f => f.CanRead(formatterContext));
+ var formatter = (IInputFormatter)null;
+ for (var i = 0; i < _formatters.Count; i++)
+ {
+ if (_formatters[i].CanRead(formatterContext))
+ {
+ formatter = _formatters[i];
+ break;
+ }
+ }
if (formatter == null)
{
- var message = Resources.FormatUnsupportedContentType(
- bindingContext.OperationBindingContext.HttpContext.Request.ContentType);
+ var message = Resources.FormatUnsupportedContentType(httpContext.Request.ContentType);
var exception = new UnsupportedContentTypeException(message);
bindingContext.ModelState.AddModelError(modelBindingKey, exception, bindingContext.ModelMetadata);
diff --git a/src/Microsoft.AspNetCore.Mvc.Core/ModelBinding/Binders/BodyModelBinderProvider.cs b/src/Microsoft.AspNetCore.Mvc.Core/ModelBinding/Binders/BodyModelBinderProvider.cs
index 07b933b4bd..ac2818c33f 100644
--- a/src/Microsoft.AspNetCore.Mvc.Core/ModelBinding/Binders/BodyModelBinderProvider.cs
+++ b/src/Microsoft.AspNetCore.Mvc.Core/ModelBinding/Binders/BodyModelBinderProvider.cs
@@ -2,6 +2,8 @@
// 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 Microsoft.AspNetCore.Mvc.Formatters;
using Microsoft.AspNetCore.Mvc.Internal;
namespace Microsoft.AspNetCore.Mvc.ModelBinding.Binders
@@ -11,19 +13,27 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding.Binders
///
public class BodyModelBinderProvider : IModelBinderProvider
{
+ private readonly IList _formatters;
private readonly IHttpRequestStreamReaderFactory _readerFactory;
///
/// Creates a new .
///
+ /// The list of .
/// The .
- public BodyModelBinderProvider(IHttpRequestStreamReaderFactory readerFactory)
+ public BodyModelBinderProvider(IList formatters, IHttpRequestStreamReaderFactory readerFactory)
{
+ if (formatters == null)
+ {
+ throw new ArgumentNullException(nameof(formatters));
+ }
+
if (readerFactory == null)
{
throw new ArgumentNullException(nameof(readerFactory));
}
+ _formatters = formatters;
_readerFactory = readerFactory;
}
@@ -38,7 +48,7 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding.Binders
if (context.BindingInfo?.BindingSource != null &&
context.BindingInfo.BindingSource.CanAcceptDataFrom(BindingSource.Body))
{
- return new BodyModelBinder(_readerFactory);
+ return new BodyModelBinder(_formatters, _readerFactory);
}
return null;
diff --git a/src/Microsoft.AspNetCore.Mvc.Core/ModelBinding/Binders/CancellationTokenModelBinder.cs b/src/Microsoft.AspNetCore.Mvc.Core/ModelBinding/Binders/CancellationTokenModelBinder.cs
index 5ee4975da0..c76ce816cd 100644
--- a/src/Microsoft.AspNetCore.Mvc.Core/ModelBinding/Binders/CancellationTokenModelBinder.cs
+++ b/src/Microsoft.AspNetCore.Mvc.Core/ModelBinding/Binders/CancellationTokenModelBinder.cs
@@ -26,7 +26,7 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding.Binders
// in both the ValidationState and ModelBindingResult.
//
// DO NOT simplify this code by removing the cast.
- var model = (object)bindingContext.OperationBindingContext.HttpContext.RequestAborted;
+ var model = (object)bindingContext.HttpContext.RequestAborted;
bindingContext.ValidationState.Add(model, new ValidationStateEntry() { SuppressValidation = true });
bindingContext.Result = ModelBindingResult.Success(bindingContext.ModelName, model);
diff --git a/src/Microsoft.AspNetCore.Mvc.Core/ModelBinding/Binders/CollectionModelBinder.cs b/src/Microsoft.AspNetCore.Mvc.Core/ModelBinding/Binders/CollectionModelBinder.cs
index 23fc5e83d7..47d3405726 100644
--- a/src/Microsoft.AspNetCore.Mvc.Core/ModelBinding/Binders/CollectionModelBinder.cs
+++ b/src/Microsoft.AspNetCore.Mvc.Core/ModelBinding/Binders/CollectionModelBinder.cs
@@ -158,10 +158,8 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding.Binders
ValueProviderResult values)
{
var boundCollection = new List();
-
- var metadataProvider = bindingContext.OperationBindingContext.MetadataProvider;
- var elementMetadata = metadataProvider.GetMetadataForType(typeof(TElement));
-
+
+ var elementMetadata = bindingContext.ModelMetadata.ElementMetadata;
foreach (var value in values)
{
@@ -223,8 +221,7 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding.Binders
.Select(i => i.ToString(CultureInfo.InvariantCulture));
}
- var metadataProvider = bindingContext.OperationBindingContext.MetadataProvider;
- var elementMetadata = metadataProvider.GetMetadataForType(typeof(TElement));
+ var elementMetadata = bindingContext.ModelMetadata.ElementMetadata;
var boundCollection = new List();
diff --git a/src/Microsoft.AspNetCore.Mvc.Core/ModelBinding/Binders/ComplexTypeModelBinder.cs b/src/Microsoft.AspNetCore.Mvc.Core/ModelBinding/Binders/ComplexTypeModelBinder.cs
index 0100f8aa81..71a3154822 100644
--- a/src/Microsoft.AspNetCore.Mvc.Core/ModelBinding/Binders/ComplexTypeModelBinder.cs
+++ b/src/Microsoft.AspNetCore.Mvc.Core/ModelBinding/Binders/ComplexTypeModelBinder.cs
@@ -252,8 +252,8 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding.Binders
modelName: modelName,
model: null))
{
- // If any property can return a true value.
- if (CanBindValue(bindingContext))
+ // If any property can be bound from a value provider then continue.
+ if (bindingContext.ValueProvider.ContainsPrefix(bindingContext.ModelName))
{
return true;
}
@@ -271,33 +271,6 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding.Binders
return false;
}
- private bool CanBindValue(ModelBindingContext bindingContext)
- {
- var valueProvider = bindingContext.ValueProvider;
-
- var bindingSource = bindingContext.BindingSource;
- if (bindingSource != null && !bindingSource.IsGreedy)
- {
- var rootValueProvider = bindingContext.OperationBindingContext.ValueProvider as IBindingSourceValueProvider;
- if (rootValueProvider != null)
- {
- valueProvider = rootValueProvider.Filter(bindingSource);
- if (valueProvider == null)
- {
- // Unable to find a value provider for this binding source. Binding will fail.
- return false;
- }
- }
- }
-
- if (valueProvider.ContainsPrefix(bindingContext.ModelName))
- {
- return true;
- }
-
- return false;
- }
-
// Internal for tests
internal static bool CanUpdatePropertyInternal(ModelMetadata propertyMetadata)
{
diff --git a/src/Microsoft.AspNetCore.Mvc.Core/ModelBinding/Binders/DictionaryModelBinder.cs b/src/Microsoft.AspNetCore.Mvc.Core/ModelBinding/Binders/DictionaryModelBinder.cs
index 931b364ee2..39d2d82ea4 100644
--- a/src/Microsoft.AspNetCore.Mvc.Core/ModelBinding/Binders/DictionaryModelBinder.cs
+++ b/src/Microsoft.AspNetCore.Mvc.Core/ModelBinding/Binders/DictionaryModelBinder.cs
@@ -81,8 +81,8 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding.Binders
}
// Update the existing successful but empty ModelBindingResult.
- var metadataProvider = bindingContext.OperationBindingContext.MetadataProvider;
- var valueMetadata = metadataProvider.GetMetadataForType(typeof(TValue));
+ var elementMetadata = bindingContext.ModelMetadata.ElementMetadata;
+ var valueMetadata = elementMetadata.Properties[nameof(KeyValuePair.Value)];
var keyMappings = new Dictionary(StringComparer.Ordinal);
foreach (var kvp in keys)
diff --git a/src/Microsoft.AspNetCore.Mvc.Core/ModelBinding/Binders/FormCollectionModelBinder.cs b/src/Microsoft.AspNetCore.Mvc.Core/ModelBinding/Binders/FormCollectionModelBinder.cs
index e3c10f2e67..2d93d5dadd 100644
--- a/src/Microsoft.AspNetCore.Mvc.Core/ModelBinding/Binders/FormCollectionModelBinder.cs
+++ b/src/Microsoft.AspNetCore.Mvc.Core/ModelBinding/Binders/FormCollectionModelBinder.cs
@@ -26,7 +26,7 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding.Binders
}
object model;
- var request = bindingContext.OperationBindingContext.HttpContext.Request;
+ var request = bindingContext.HttpContext.Request;
if (request.HasFormContentType)
{
var form = await request.ReadFormAsync();
diff --git a/src/Microsoft.AspNetCore.Mvc.Core/ModelBinding/Binders/FormFileModelBinder.cs b/src/Microsoft.AspNetCore.Mvc.Core/ModelBinding/Binders/FormFileModelBinder.cs
index a9eb164714..7e86c74f55 100644
--- a/src/Microsoft.AspNetCore.Mvc.Core/ModelBinding/Binders/FormFileModelBinder.cs
+++ b/src/Microsoft.AspNetCore.Mvc.Core/ModelBinding/Binders/FormFileModelBinder.cs
@@ -118,7 +118,7 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding.Binders
ModelBindingContext bindingContext,
ICollection postedFiles)
{
- var request = bindingContext.OperationBindingContext.HttpContext.Request;
+ var request = bindingContext.HttpContext.Request;
if (request.HasFormContentType)
{
var form = await request.ReadFormAsync();
diff --git a/src/Microsoft.AspNetCore.Mvc.Core/ModelBinding/Binders/HeaderModelBinder.cs b/src/Microsoft.AspNetCore.Mvc.Core/ModelBinding/Binders/HeaderModelBinder.cs
index 8aa1e2d42c..8b4de798b1 100644
--- a/src/Microsoft.AspNetCore.Mvc.Core/ModelBinding/Binders/HeaderModelBinder.cs
+++ b/src/Microsoft.AspNetCore.Mvc.Core/ModelBinding/Binders/HeaderModelBinder.cs
@@ -25,7 +25,7 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding.Binders
throw new ArgumentNullException(nameof(bindingContext));
}
- var request = bindingContext.OperationBindingContext.HttpContext.Request;
+ var request = bindingContext.HttpContext.Request;
// Property name can be null if the model metadata represents a type (rather than a property or parameter).
var headerName = bindingContext.FieldName;
diff --git a/src/Microsoft.AspNetCore.Mvc.Core/ModelBinding/Binders/KeyValuePairModelBinder.cs b/src/Microsoft.AspNetCore.Mvc.Core/ModelBinding/Binders/KeyValuePairModelBinder.cs
index 4732fd9dd8..247c205dfc 100644
--- a/src/Microsoft.AspNetCore.Mvc.Core/ModelBinding/Binders/KeyValuePairModelBinder.cs
+++ b/src/Microsoft.AspNetCore.Mvc.Core/ModelBinding/Binders/KeyValuePairModelBinder.cs
@@ -97,10 +97,8 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding.Binders
IModelBinder binder,
string propertyName)
{
- var propertyModelMetadata =
- bindingContext.OperationBindingContext.MetadataProvider.GetMetadataForType(typeof(TModel));
- var propertyModelName =
- ModelNames.CreatePropertyModelName(bindingContext.ModelName, propertyName);
+ var propertyModelMetadata = bindingContext.ModelMetadata.Properties[propertyName];
+ var propertyModelName = ModelNames.CreatePropertyModelName(bindingContext.ModelName, propertyName);
using (bindingContext.EnterNestedScope(
modelMetadata: propertyModelMetadata,
diff --git a/src/Microsoft.AspNetCore.Mvc.Core/ModelBinding/Binders/ServicesModelBinder.cs b/src/Microsoft.AspNetCore.Mvc.Core/ModelBinding/Binders/ServicesModelBinder.cs
index 5ccc928917..a909d378c8 100644
--- a/src/Microsoft.AspNetCore.Mvc.Core/ModelBinding/Binders/ServicesModelBinder.cs
+++ b/src/Microsoft.AspNetCore.Mvc.Core/ModelBinding/Binders/ServicesModelBinder.cs
@@ -23,7 +23,7 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding.Binders
throw new ArgumentNullException(nameof(bindingContext));
}
- var requestServices = bindingContext.OperationBindingContext.HttpContext.RequestServices;
+ var requestServices = bindingContext.HttpContext.RequestServices;
var model = requestServices.GetRequiredService(bindingContext.ModelType);
bindingContext.ValidationState.Add(model, new ValidationStateEntry() { SuppressValidation = true });
diff --git a/src/Microsoft.AspNetCore.Mvc.Core/ModelBinding/ModelBindingHelper.cs b/src/Microsoft.AspNetCore.Mvc.Core/ModelBinding/ModelBindingHelper.cs
index 26a8c5aca5..ba7029496b 100644
--- a/src/Microsoft.AspNetCore.Mvc.Core/ModelBinding/ModelBindingHelper.cs
+++ b/src/Microsoft.AspNetCore.Mvc.Core/ModelBinding/ModelBindingHelper.cs
@@ -12,7 +12,6 @@ using System.Reflection;
using System.Runtime.ExceptionServices;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc.Core;
-using Microsoft.AspNetCore.Mvc.Formatters;
using Microsoft.AspNetCore.Mvc.ModelBinding.Validation;
namespace Microsoft.AspNetCore.Mvc.ModelBinding
@@ -22,7 +21,7 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding
///
/// Updates the specified instance using the specified
/// and the specified and executes
- /// validation using the specified .
+ /// validation using the specified .
///
/// The type of the model object.
/// The model instance to update and validate.
@@ -32,13 +31,8 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding
/// The provider used for reading metadata for the model type.
/// The used for binding.
/// The used for looking up values.
- ///
- /// The set of instances for deserializing the body.
- ///
/// The used for validating the
/// bound values.
- /// The used for executing validation
- /// on the model instance.
/// A that on completion returns true if the update is successful
public static Task TryUpdateModelAsync(
TModel model,
@@ -47,9 +41,7 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding
IModelMetadataProvider metadataProvider,
IModelBinderFactory modelBinderFactory,
IValueProvider valueProvider,
- IList inputFormatters,
- IObjectModelValidator objectModelValidator,
- IModelValidatorProvider validatorProvider)
+ IObjectModelValidator objectModelValidator)
where TModel : class
{
if (model == null)
@@ -82,21 +74,11 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding
throw new ArgumentNullException(nameof(valueProvider));
}
- if (inputFormatters == null)
- {
- throw new ArgumentNullException(nameof(inputFormatters));
- }
-
if (objectModelValidator == null)
{
throw new ArgumentNullException(nameof(objectModelValidator));
}
- if (validatorProvider == null)
- {
- throw new ArgumentNullException(nameof(validatorProvider));
- }
-
// Includes everything by default.
return TryUpdateModelAsync(
model,
@@ -105,16 +87,14 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding
metadataProvider,
modelBinderFactory,
valueProvider,
- inputFormatters,
objectModelValidator,
- validatorProvider,
propertyFilter: (m) => true);
}
///
/// Updates the specified instance using the specified
/// and the specified and executes validation using the specified
- /// .
+ /// .
///
/// The type of the model object.
/// The model instance to update and validate.
@@ -124,14 +104,8 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding
/// The provider used for reading metadata for the model type.
/// The used for binding.
/// The used for looking up values.
- ///
- /// The set of instances for deserializing the body.
- ///
/// The used for validating the
/// bound values.
- /// The used for executing validation
- /// on the model
- /// instance.
/// Expression(s) which represent top level properties
/// which need to be included for the current model.
/// A that on completion returns true if the update is successful
@@ -142,9 +116,7 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding
IModelMetadataProvider metadataProvider,
IModelBinderFactory modelBinderFactory,
IValueProvider valueProvider,
- IList inputFormatters,
IObjectModelValidator objectModelValidator,
- IModelValidatorProvider validatorProvider,
params Expression>[] includeExpressions)
where TModel : class
{
@@ -178,21 +150,11 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding
throw new ArgumentNullException(nameof(valueProvider));
}
- if (inputFormatters == null)
- {
- throw new ArgumentNullException(nameof(inputFormatters));
- }
-
if (objectModelValidator == null)
{
throw new ArgumentNullException(nameof(objectModelValidator));
}
- if (validatorProvider == null)
- {
- throw new ArgumentNullException(nameof(validatorProvider));
- }
-
if (includeExpressions == null)
{
throw new ArgumentNullException(nameof(includeExpressions));
@@ -208,16 +170,14 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding
metadataProvider,
modelBinderFactory,
valueProvider,
- inputFormatters,
objectModelValidator,
- validatorProvider,
- propertyFilter: propertyFilter);
+ propertyFilter);
}
///
/// Updates the specified instance using the specified
/// and the specified and executes validation using the specified
- /// .
+ /// .
///
/// The type of the model object.
/// The model instance to update and validate.
@@ -227,13 +187,8 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding
/// The provider used for reading metadata for the model type.
/// The used for binding.
/// The used for looking up values.
- ///
- /// The set of instances for deserializing the body.
- ///
/// The used for validating the
/// bound values.
- /// The used for executing validation
- /// on the model instance.
///
/// A predicate which can be used to filter properties(for inclusion/exclusion) at runtime.
///
@@ -245,9 +200,7 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding
IModelMetadataProvider metadataProvider,
IModelBinderFactory modelBinderFactory,
IValueProvider valueProvider,
- IList inputFormatters,
IObjectModelValidator objectModelValidator,
- IModelValidatorProvider validatorProvider,
Func propertyFilter)
where TModel : class
{
@@ -281,21 +234,11 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding
throw new ArgumentNullException(nameof(valueProvider));
}
- if (inputFormatters == null)
- {
- throw new ArgumentNullException(nameof(inputFormatters));
- }
-
if (objectModelValidator == null)
{
throw new ArgumentNullException(nameof(objectModelValidator));
}
- if (validatorProvider == null)
- {
- throw new ArgumentNullException(nameof(validatorProvider));
- }
-
if (propertyFilter == null)
{
throw new ArgumentNullException(nameof(propertyFilter));
@@ -309,16 +252,14 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding
metadataProvider,
modelBinderFactory,
valueProvider,
- inputFormatters,
objectModelValidator,
- validatorProvider,
- propertyFilter: propertyFilter);
+ propertyFilter);
}
///
/// Updates the specified instance using the specified
/// and the specified and executes validation using the specified
- /// .
+ /// .
///
/// The model instance to update and validate.
/// The type of model instance to update and validate.
@@ -328,25 +269,18 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding
/// The provider used for reading metadata for the model type.
/// The used for binding.
/// The used for looking up values.
- ///
- /// The set of instances for deserializing the body.
- ///
/// The used for validating the
/// bound values.
- /// The used for executing validation
- /// on the model instance.
/// A that on completion returns true if the update is successful
public static Task TryUpdateModelAsync(
- object model,
- Type modelType,
- string prefix,
- ActionContext actionContext,
- IModelMetadataProvider metadataProvider,
- IModelBinderFactory modelBinderFactory,
- IValueProvider valueProvider,
- IList inputFormatters,
- IObjectModelValidator objectModelValidator,
- IModelValidatorProvider validatorProvider)
+ object model,
+ Type modelType,
+ string prefix,
+ ActionContext actionContext,
+ IModelMetadataProvider metadataProvider,
+ IModelBinderFactory modelBinderFactory,
+ IValueProvider valueProvider,
+ IObjectModelValidator objectModelValidator)
{
if (model == null)
{
@@ -383,21 +317,11 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding
throw new ArgumentNullException(nameof(valueProvider));
}
- if (inputFormatters == null)
- {
- throw new ArgumentNullException(nameof(inputFormatters));
- }
-
if (objectModelValidator == null)
{
throw new ArgumentNullException(nameof(objectModelValidator));
}
- if (validatorProvider == null)
- {
- throw new ArgumentNullException(nameof(validatorProvider));
- }
-
// Includes everything by default.
return TryUpdateModelAsync(
model,
@@ -407,16 +331,14 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding
metadataProvider,
modelBinderFactory,
valueProvider,
- inputFormatters,
objectModelValidator,
- validatorProvider,
propertyFilter: (m) => true);
}
///
/// Updates the specified instance using the specified
/// and the specified and executes validation using the specified
- /// .
+ /// .
///
/// The model instance to update and validate.
/// The type of model instance to update and validate.
@@ -426,13 +348,8 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding
/// The provider used for reading metadata for the model type.
/// The used for binding.
/// The used for looking up values.
- ///
- /// The set of instances for deserializing the body.
- ///
/// The used for validating the
/// bound values.
- /// The used for executing validation
- /// on the model instance.
/// A predicate which can be used to
/// filter properties(for inclusion/exclusion) at runtime.
/// A that on completion returns true if the update is successful
@@ -444,9 +361,7 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding
IModelMetadataProvider metadataProvider,
IModelBinderFactory modelBinderFactory,
IValueProvider valueProvider,
- IList inputFormatters,
IObjectModelValidator objectModelValidator,
- IModelValidatorProvider validatorProvider,
Func propertyFilter)
{
if (model == null)
@@ -484,21 +399,11 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding
throw new ArgumentNullException(nameof(valueProvider));
}
- if (inputFormatters == null)
- {
- throw new ArgumentNullException(nameof(inputFormatters));
- }
-
if (objectModelValidator == null)
{
throw new ArgumentNullException(nameof(objectModelValidator));
}
- if (validatorProvider == null)
- {
- throw new ArgumentNullException(nameof(validatorProvider));
- }
-
if (propertyFilter == null)
{
throw new ArgumentNullException(nameof(propertyFilter));
@@ -515,20 +420,13 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding
var modelMetadata = metadataProvider.GetMetadataForType(modelType);
var modelState = actionContext.ModelState;
- var operationBindingContext = new OperationBindingContext
- {
- InputFormatters = inputFormatters,
- ValidatorProvider = validatorProvider,
- MetadataProvider = metadataProvider,
- ActionContext = actionContext,
- ValueProvider = valueProvider,
- };
-
var modelBindingContext = DefaultModelBindingContext.CreateBindingContext(
- operationBindingContext,
+ actionContext,
+ valueProvider,
modelMetadata,
bindingInfo: null,
modelName: prefix ?? string.Empty);
+
modelBindingContext.Model = model;
modelBindingContext.PropertyFilter = propertyFilter;
@@ -555,8 +453,7 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding
if (modelBindingResult != null && modelBindingResult.Value.IsModelSet)
{
objectModelValidator.Validate(
- operationBindingContext.ActionContext,
- operationBindingContext.ValidatorProvider,
+ actionContext,
modelBindingContext.ValidationState,
modelBindingResult.Value.Key,
modelBindingResult.Value.Model);
diff --git a/src/Microsoft.AspNetCore.Mvc.Core/ModelBinding/Validation/IObjectModelValidator.cs b/src/Microsoft.AspNetCore.Mvc.Core/ModelBinding/Validation/IObjectModelValidator.cs
index d0ffa99264..1a0ca7659d 100644
--- a/src/Microsoft.AspNetCore.Mvc.Core/ModelBinding/Validation/IObjectModelValidator.cs
+++ b/src/Microsoft.AspNetCore.Mvc.Core/ModelBinding/Validation/IObjectModelValidator.cs
@@ -12,7 +12,6 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding.Validation
/// Validates the provided object.
///
/// The associated with the current request.
- /// The .
/// The . May be null.
///
/// The model prefix. Used to map the model object to entries in .
@@ -20,7 +19,6 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding.Validation
/// The model object.
void Validate(
ActionContext actionContext,
- IModelValidatorProvider validatorProvider,
ValidationStateDictionary validationState,
string prefix,
object model);
diff --git a/src/Microsoft.AspNetCore.Mvc.WebApiCompatShim/ApiController.cs b/src/Microsoft.AspNetCore.Mvc.WebApiCompatShim/ApiController.cs
index f89692de8f..d11f22bef9 100644
--- a/src/Microsoft.AspNetCore.Mvc.WebApiCompatShim/ApiController.cs
+++ b/src/Microsoft.AspNetCore.Mvc.WebApiCompatShim/ApiController.cs
@@ -567,13 +567,11 @@ namespace System.Web.Http
///
public void Validate(TEntity entity, string keyPrefix)
{
- var validatidationState = new ValidationStateDictionary();
ObjectValidator.Validate(
ControllerContext,
- new CompositeModelValidatorProvider(ControllerContext.ValidatorProviders),
- validatidationState,
- keyPrefix,
- entity);
+ validationState: null,
+ prefix: keyPrefix,
+ model: entity);
}
protected virtual void Dispose(bool disposing)
diff --git a/src/Microsoft.AspNetCore.Mvc.WebApiCompatShim/HttpRequestMessage/HttpRequestMessageModelBinder.cs b/src/Microsoft.AspNetCore.Mvc.WebApiCompatShim/HttpRequestMessage/HttpRequestMessageModelBinder.cs
index 2cc20278ff..b7da750ae7 100644
--- a/src/Microsoft.AspNetCore.Mvc.WebApiCompatShim/HttpRequestMessage/HttpRequestMessageModelBinder.cs
+++ b/src/Microsoft.AspNetCore.Mvc.WebApiCompatShim/HttpRequestMessage/HttpRequestMessageModelBinder.cs
@@ -17,7 +17,7 @@ namespace Microsoft.AspNetCore.Mvc.WebApiCompatShim
///
public Task BindModelAsync(ModelBindingContext bindingContext)
{
- var model = bindingContext.OperationBindingContext.HttpContext.GetHttpRequestMessage();
+ var model = bindingContext.HttpContext.GetHttpRequestMessage();
bindingContext.ValidationState.Add(model, new ValidationStateEntry() { SuppressValidation = true });
bindingContext.Result = ModelBindingResult.Success(bindingContext.ModelName, model);
diff --git a/test/Microsoft.AspNetCore.Mvc.Core.Test/ControllerBaseTest.cs b/test/Microsoft.AspNetCore.Mvc.Core.Test/ControllerBaseTest.cs
index 649dd42431..750a4dd109 100644
--- a/test/Microsoft.AspNetCore.Mvc.Core.Test/ControllerBaseTest.cs
+++ b/test/Microsoft.AspNetCore.Mvc.Core.Test/ControllerBaseTest.cs
@@ -1373,10 +1373,9 @@ namespace Microsoft.AspNetCore.Mvc.Core.Test
// Arrange
var binder = new StubModelBinder();
var controller = GetController(binder, valueProvider: null);
- controller.ControllerContext.ValidatorProviders = new List()
- {
- Mock.Of(),
- };
+ controller.ObjectValidator = new DefaultObjectValidator(
+ controller.MetadataProvider,
+ new[] { Mock.Of() });
var model = new TryValidateModelModel();
@@ -1410,10 +1409,9 @@ namespace Microsoft.AspNetCore.Mvc.Core.Test
var binder = new StubModelBinder();
var controller = GetController(binder, valueProvider: null);
- controller.ControllerContext.ValidatorProviders = new List()
- {
- provider.Object,
- };
+ controller.ObjectValidator = new DefaultObjectValidator(
+ controller.MetadataProvider,
+ new[] { provider.Object });
// Act
var result = controller.TryValidateModel(model, "Prefix");
@@ -1447,10 +1445,9 @@ namespace Microsoft.AspNetCore.Mvc.Core.Test
var binder = new StubModelBinder();
var controller = GetController(binder, valueProvider: null);
- controller.ControllerContext.ValidatorProviders = new List()
- {
- provider.Object,
- };
+ controller.ObjectValidator = new DefaultObjectValidator(
+ controller.MetadataProvider,
+ new[] { provider.Object });
// Act
var result = controller.TryValidateModel(model);
@@ -1483,17 +1480,18 @@ namespace Microsoft.AspNetCore.Mvc.Core.Test
var metadataProvider = TestModelMetadataProvider.CreateDefaultProvider();
var httpContext = new DefaultHttpContext();
+ var validatorProviders = new[]
+ {
+ new DataAnnotationsModelValidatorProvider(
+ new ValidationAttributeAdapterProvider(),
+ new TestOptionsManager(),
+ stringLocalizerFactory: null),
+ };
+
var controllerContext = new ControllerContext()
{
HttpContext = httpContext,
ValueProviders = new[] { valueProvider, },
- ValidatorProviders = new[]
- {
- new DataAnnotationsModelValidatorProvider(
- new ValidationAttributeAdapterProvider(),
- new TestOptionsManager(),
- stringLocalizerFactory: null),
- },
};
var binderFactory = new Mock();
@@ -1506,7 +1504,7 @@ namespace Microsoft.AspNetCore.Mvc.Core.Test
ControllerContext = controllerContext,
MetadataProvider = metadataProvider,
ModelBinderFactory = binderFactory.Object,
- ObjectValidator = new DefaultObjectValidator(metadataProvider, new ValidatorCache()),
+ ObjectValidator = new DefaultObjectValidator(metadataProvider, validatorProviders),
};
return controller;
diff --git a/test/Microsoft.AspNetCore.Mvc.Core.Test/Controllers/DefaultControllerActivatorTest.cs b/test/Microsoft.AspNetCore.Mvc.Core.Test/Controllers/DefaultControllerActivatorTest.cs
index 0838bfc7df..be1cd682f9 100644
--- a/test/Microsoft.AspNetCore.Mvc.Core.Test/Controllers/DefaultControllerActivatorTest.cs
+++ b/test/Microsoft.AspNetCore.Mvc.Core.Test/Controllers/DefaultControllerActivatorTest.cs
@@ -2,6 +2,7 @@
// 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.Reflection;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc.Internal;
@@ -126,12 +127,15 @@ namespace Microsoft.AspNetCore.Mvc.Controllers
{
var metadataProvider = new EmptyModelMetadataProvider();
var services = new Mock();
- services.Setup(s => s.GetService(typeof(IUrlHelper)))
+ services
+ .Setup(s => s.GetService(typeof(IUrlHelper)))
.Returns(Mock.Of());
- services.Setup(s => s.GetService(typeof(IModelMetadataProvider)))
+ services
+ .Setup(s => s.GetService(typeof(IModelMetadataProvider)))
.Returns(metadataProvider);
- services.Setup(s => s.GetService(typeof(IObjectModelValidator)))
- .Returns(new DefaultObjectValidator(metadataProvider, new ValidatorCache()));
+ services
+ .Setup(s => s.GetService(typeof(IObjectModelValidator)))
+ .Returns(new DefaultObjectValidator(metadataProvider, new List()));
return services.Object;
}
diff --git a/test/Microsoft.AspNetCore.Mvc.Core.Test/Controllers/DefaultControllerFactoryTest.cs b/test/Microsoft.AspNetCore.Mvc.Core.Test/Controllers/DefaultControllerFactoryTest.cs
index 54aea74ad1..436693bbb9 100644
--- a/test/Microsoft.AspNetCore.Mvc.Core.Test/Controllers/DefaultControllerFactoryTest.cs
+++ b/test/Microsoft.AspNetCore.Mvc.Core.Test/Controllers/DefaultControllerFactoryTest.cs
@@ -205,12 +205,17 @@ namespace Microsoft.AspNetCore.Mvc.Controllers
{
var metadataProvider = new EmptyModelMetadataProvider();
var services = new Mock();
- services.Setup(s => s.GetService(typeof(IUrlHelper)))
- .Returns(Mock.Of());
- services.Setup(s => s.GetService(typeof(IModelMetadataProvider)))
- .Returns(metadataProvider);
- services.Setup(s => s.GetService(typeof(IObjectModelValidator)))
- .Returns(new DefaultObjectValidator(metadataProvider, new ValidatorCache()));
+ services
+ .Setup(s => s.GetService(typeof(IUrlHelper)))
+ .Returns(Mock.Of());
+ services
+ .Setup(s => s.GetService(typeof(IModelMetadataProvider)))
+ .Returns(metadataProvider);
+ services
+ .Setup(s => s.GetService(typeof(IObjectModelValidator)))
+ .Returns(new DefaultObjectValidator(
+ metadataProvider,
+ TestModelValidatorProvider.CreateDefaultProvider().ValidatorProviders));
return services.Object;
}
diff --git a/test/Microsoft.AspNetCore.Mvc.Core.Test/Internal/ControllerActionInvokerTest.cs b/test/Microsoft.AspNetCore.Mvc.Core.Test/Internal/ControllerActionInvokerTest.cs
index 8dd2528159..c294271053 100644
--- a/test/Microsoft.AspNetCore.Mvc.Core.Test/Internal/ControllerActionInvokerTest.cs
+++ b/test/Microsoft.AspNetCore.Mvc.Core.Test/Internal/ControllerActionInvokerTest.cs
@@ -2053,7 +2053,6 @@ namespace Microsoft.AspNetCore.Mvc.Internal
actionDescriptor,
new IInputFormatter[0],
actionArgumentsBinder.Object,
- new IModelValidatorProvider[0],
new IValueProviderFactory[0],
new NullLoggerFactory().CreateLogger(),
new DiagnosticListener("Microsoft.AspNetCore"),
@@ -2108,8 +2107,7 @@ namespace Microsoft.AspNetCore.Mvc.Internal
new ControllerArgumentBinder(
metadataProvider,
TestModelBinderFactory.CreateDefault(metadataProvider),
- new DefaultObjectValidator(metadataProvider, new ValidatorCache())),
- new IModelValidatorProvider[0],
+ new DefaultObjectValidator(metadataProvider, new IModelValidatorProvider[0])),
new IValueProviderFactory[0],
new NullLoggerFactory().CreateLogger(),
new DiagnosticListener("Microsoft.AspNetCore"),
@@ -2233,7 +2231,6 @@ namespace Microsoft.AspNetCore.Mvc.Internal
ControllerActionDescriptor descriptor,
IReadOnlyList inputFormatters,
IControllerActionArgumentBinder controllerActionArgumentBinder,
- IReadOnlyList modelValidatorProviders,
IReadOnlyList valueProviderFactories,
ILogger logger,
DiagnosticSource diagnosticSource,
@@ -2245,7 +2242,6 @@ namespace Microsoft.AspNetCore.Mvc.Internal
descriptor,
inputFormatters,
controllerActionArgumentBinder,
- modelValidatorProviders,
valueProviderFactories,
logger,
diagnosticSource,
diff --git a/test/Microsoft.AspNetCore.Mvc.Core.Test/Internal/ControllerArgumentBinderTests.cs b/test/Microsoft.AspNetCore.Mvc.Core.Test/Internal/ControllerArgumentBinderTests.cs
index 99401503a9..3e45954f4f 100644
--- a/test/Microsoft.AspNetCore.Mvc.Core.Test/Internal/ControllerArgumentBinderTests.cs
+++ b/test/Microsoft.AspNetCore.Mvc.Core.Test/Internal/ControllerArgumentBinderTests.cs
@@ -135,7 +135,6 @@ namespace Microsoft.AspNetCore.Mvc.Internal
mockValidator
.Setup(o => o.Validate(
It.IsAny(),
- It.IsAny(),
It.IsAny(),
It.IsAny(),
It.IsAny