[Fixes #7412] AspNetCore 2.1 breaks integration with 3rd party validation libraries
This commit is contained in:
parent
a952313f1c
commit
a0b1b15101
|
|
@ -232,15 +232,7 @@ namespace Microsoft.Extensions.DependencyInjection
|
|||
return new DefaultObjectValidator(metadataProvider, options.ModelValidatorProviders);
|
||||
});
|
||||
services.TryAddSingleton<ClientValidatorCache>();
|
||||
services.TryAddSingleton<ParameterBinder>(s =>
|
||||
{
|
||||
var options = s.GetRequiredService<IOptions<MvcOptions>>().Value;
|
||||
var loggerFactory = s.GetRequiredService<ILoggerFactory>();
|
||||
var metadataProvider = s.GetRequiredService<IModelMetadataProvider>();
|
||||
var modelBinderFactory = s.GetRequiredService<IModelBinderFactory>();
|
||||
var modelValidatorProvider = new CompositeModelValidatorProvider(options.ModelValidatorProviders);
|
||||
return new ParameterBinder(metadataProvider, modelBinderFactory, modelValidatorProvider, loggerFactory);
|
||||
});
|
||||
services.TryAddSingleton<ParameterBinder>();
|
||||
|
||||
//
|
||||
// Random Infrastructure
|
||||
|
|
|
|||
|
|
@ -1,7 +1,6 @@
|
|||
// 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;
|
||||
using System.Collections.Generic;
|
||||
using Microsoft.AspNetCore.Mvc.ModelBinding;
|
||||
using Microsoft.AspNetCore.Mvc.ModelBinding.Validation;
|
||||
|
|
@ -11,12 +10,8 @@ namespace Microsoft.AspNetCore.Mvc.Internal
|
|||
/// <summary>
|
||||
/// The default implementation of <see cref="IObjectModelValidator"/>.
|
||||
/// </summary>
|
||||
public class DefaultObjectValidator : IObjectModelValidator
|
||||
public class DefaultObjectValidator : ObjectModelValidator
|
||||
{
|
||||
private readonly IModelMetadataProvider _modelMetadataProvider;
|
||||
private readonly ValidatorCache _validatorCache;
|
||||
private readonly IModelValidatorProvider _validatorProvider;
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of <see cref="DefaultObjectValidator"/>.
|
||||
/// </summary>
|
||||
|
|
@ -25,44 +20,23 @@ namespace Microsoft.AspNetCore.Mvc.Internal
|
|||
public DefaultObjectValidator(
|
||||
IModelMetadataProvider modelMetadataProvider,
|
||||
IList<IModelValidatorProvider> validatorProviders)
|
||||
: base(modelMetadataProvider, validatorProviders)
|
||||
{
|
||||
if (modelMetadataProvider == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(modelMetadataProvider));
|
||||
}
|
||||
|
||||
if (validatorProviders == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(validatorProviders));
|
||||
}
|
||||
|
||||
_modelMetadataProvider = modelMetadataProvider;
|
||||
_validatorCache = new ValidatorCache();
|
||||
|
||||
_validatorProvider = new CompositeModelValidatorProvider(validatorProviders);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public void Validate(
|
||||
public override ValidationVisitor GetValidationVisitor(
|
||||
ActionContext actionContext,
|
||||
ValidationStateDictionary validationState,
|
||||
string prefix,
|
||||
object model)
|
||||
IModelValidatorProvider validatorProvider,
|
||||
ValidatorCache validatorCache,
|
||||
IModelMetadataProvider metadataProvider,
|
||||
ValidationStateDictionary validationState)
|
||||
{
|
||||
if (actionContext == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(actionContext));
|
||||
}
|
||||
|
||||
var visitor = new ValidationVisitor(
|
||||
return new ValidationVisitor(
|
||||
actionContext,
|
||||
_validatorProvider,
|
||||
_validatorCache,
|
||||
_modelMetadataProvider,
|
||||
validatorProvider,
|
||||
validatorCache,
|
||||
metadataProvider,
|
||||
validationState);
|
||||
|
||||
var metadata = model == null ? null : _modelMetadataProvider.GetMetadataForType(model.GetType());
|
||||
visitor.Validate(metadata, prefix, model);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,108 @@
|
|||
// 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;
|
||||
using System.Collections.Generic;
|
||||
using Microsoft.AspNetCore.Mvc.Internal;
|
||||
using Microsoft.AspNetCore.Mvc.ModelBinding.Validation;
|
||||
|
||||
namespace Microsoft.AspNetCore.Mvc.ModelBinding
|
||||
{
|
||||
/// <summary>
|
||||
/// Provides a base <see cref="IObjectModelValidator"/> implementation for validating an object graph.
|
||||
/// </summary>
|
||||
public abstract class ObjectModelValidator : IObjectModelValidator
|
||||
{
|
||||
private readonly IModelMetadataProvider _modelMetadataProvider;
|
||||
private readonly ValidatorCache _validatorCache;
|
||||
private readonly CompositeModelValidatorProvider _validatorProvider;
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of <see cref="ObjectModelValidator"/>.
|
||||
/// </summary>
|
||||
/// <param name="modelMetadataProvider">The <see cref="ModelMetadataProvider"/>.</param>
|
||||
/// <param name="validatorProviders">The list of <see cref="IModelValidatorProvider"/>.</param>
|
||||
public ObjectModelValidator(
|
||||
IModelMetadataProvider modelMetadataProvider,
|
||||
IList<IModelValidatorProvider> validatorProviders)
|
||||
{
|
||||
if (modelMetadataProvider == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(modelMetadataProvider));
|
||||
}
|
||||
|
||||
if (validatorProviders == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(validatorProviders));
|
||||
}
|
||||
|
||||
_modelMetadataProvider = modelMetadataProvider;
|
||||
_validatorCache = new ValidatorCache();
|
||||
|
||||
_validatorProvider = new CompositeModelValidatorProvider(validatorProviders);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public virtual void Validate(
|
||||
ActionContext actionContext,
|
||||
ValidationStateDictionary validationState,
|
||||
string prefix,
|
||||
object model)
|
||||
{
|
||||
var visitor = GetValidationVisitor(
|
||||
actionContext,
|
||||
_validatorProvider,
|
||||
_validatorCache,
|
||||
_modelMetadataProvider,
|
||||
validationState);
|
||||
|
||||
var metadata = model == null ? null : _modelMetadataProvider.GetMetadataForType(model.GetType());
|
||||
visitor.Validate(metadata, prefix, model, alwaysValidateAtTopLevel: false);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Validates the provided object model.
|
||||
/// If <paramref name="model"/> is <see langword="null"/> and the <paramref name="metadata"/>'s
|
||||
/// <see cref="ModelMetadata.IsRequired"/> is <see langword="true"/>, will add one or more
|
||||
/// model state errors that <see cref="Validate(ActionContext, ValidationStateDictionary, string, object)"/>
|
||||
/// would not.
|
||||
/// </summary>
|
||||
/// <param name="actionContext">The <see cref="ActionContext"/>.</param>
|
||||
/// <param name="validationState">The <see cref="ValidationStateDictionary"/>.</param>
|
||||
/// <param name="prefix">The model prefix key.</param>
|
||||
/// <param name="model">The model object.</param>
|
||||
/// <param name="metadata">The <see cref="ModelMetadata"/>.</param>
|
||||
public virtual void Validate(
|
||||
ActionContext actionContext,
|
||||
ValidationStateDictionary validationState,
|
||||
string prefix,
|
||||
object model,
|
||||
ModelMetadata metadata)
|
||||
{
|
||||
var visitor = GetValidationVisitor(
|
||||
actionContext,
|
||||
_validatorProvider,
|
||||
_validatorCache,
|
||||
_modelMetadataProvider,
|
||||
validationState);
|
||||
|
||||
visitor.Validate(metadata, prefix, model, alwaysValidateAtTopLevel: metadata.IsRequired);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets a <see cref="ValidationVisitor"/> that traverses the object model graph and performs validation.
|
||||
/// </summary>
|
||||
/// <param name="actionContext">The <see cref="ActionContext"/>.</param>
|
||||
/// <param name="validatorProvider">The <see cref="IModelValidatorProvider"/>.</param>
|
||||
/// <param name="validatorCache">The <see cref="ValidatorCache"/>.</param>
|
||||
/// <param name="metadataProvider">The <see cref="IModelMetadataProvider"/>.</param>
|
||||
/// <param name="validationState">The <see cref="ValidationStateDictionary"/>.</param>
|
||||
/// <returns>A <see cref="ValidationVisitor"/> which traverses the object model graph.</returns>
|
||||
public abstract ValidationVisitor GetValidationVisitor(
|
||||
ActionContext actionContext,
|
||||
IModelValidatorProvider validatorProvider,
|
||||
ValidatorCache validatorCache,
|
||||
IModelMetadataProvider metadataProvider,
|
||||
ValidationStateDictionary validationState);
|
||||
}
|
||||
}
|
||||
|
|
@ -18,9 +18,7 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding
|
|||
{
|
||||
private readonly IModelMetadataProvider _modelMetadataProvider;
|
||||
private readonly IModelBinderFactory _modelBinderFactory;
|
||||
private readonly IObjectModelValidator _validatorForBackCompatOnly;
|
||||
private readonly IModelValidatorProvider _validatorProvider;
|
||||
private readonly ValidatorCache _validatorCache;
|
||||
private readonly IObjectModelValidator _objectModelValidator;
|
||||
|
||||
/// <summary>
|
||||
/// <para>This constructor is obsolete and will be removed in a future version. The recommended alternative
|
||||
|
|
@ -29,19 +27,14 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding
|
|||
/// </summary>
|
||||
/// <param name="modelMetadataProvider">The <see cref="IModelMetadataProvider"/>.</param>
|
||||
/// <param name="modelBinderFactory">The <see cref="IModelBinderFactory"/>.</param>
|
||||
/// <param name="validatorProvider">The <see cref="IModelValidatorProvider"/>.</param>
|
||||
/// <param name="validator">The <see cref="IObjectModelValidator"/>.</param>
|
||||
[Obsolete("This constructor is obsolete and will be removed in a future version. The recommended alternative"
|
||||
+ " is the overload that also takes an " + nameof(ILoggerFactory) + ".")]
|
||||
public ParameterBinder(
|
||||
IModelMetadataProvider modelMetadataProvider,
|
||||
IModelBinderFactory modelBinderFactory,
|
||||
IModelValidatorProvider validatorProvider)
|
||||
: this(
|
||||
modelMetadataProvider,
|
||||
modelBinderFactory,
|
||||
validatorProvider,
|
||||
validatorForBackCompatOnly: null,
|
||||
loggerFactory: NullLoggerFactory.Instance)
|
||||
IObjectModelValidator validator)
|
||||
: this(modelMetadataProvider, modelBinderFactory, validator, NullLoggerFactory.Instance)
|
||||
{
|
||||
}
|
||||
|
||||
|
|
@ -50,63 +43,12 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding
|
|||
/// </summary>
|
||||
/// <param name="modelMetadataProvider">The <see cref="IModelMetadataProvider"/>.</param>
|
||||
/// <param name="modelBinderFactory">The <see cref="IModelBinderFactory"/>.</param>
|
||||
/// <param name="validatorProvider">The <see cref="IModelValidatorProvider"/>.</param>
|
||||
/// <param name="validator">The <see cref="IObjectModelValidator"/>.</param>
|
||||
/// <param name="loggerFactory">The <see cref="ILoggerFactory"/>.</param>
|
||||
public ParameterBinder(
|
||||
IModelMetadataProvider modelMetadataProvider,
|
||||
IModelBinderFactory modelBinderFactory,
|
||||
IModelValidatorProvider validatorProvider,
|
||||
ILoggerFactory loggerFactory)
|
||||
: this(
|
||||
modelMetadataProvider,
|
||||
modelBinderFactory,
|
||||
validatorProvider,
|
||||
validatorForBackCompatOnly: null,
|
||||
loggerFactory: loggerFactory)
|
||||
{
|
||||
if (validatorProvider == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(validatorProvider));
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// <para>This constructor is obsolete and will be removed in a future version. The recommended alternative
|
||||
/// is the overload that also takes an <see cref="IModelValidatorProvider"/> and <see cref="ILoggerFactory"/>
|
||||
/// instead of an <see cref="IObjectModelValidator"/>.</para>
|
||||
/// <para>Initializes a new instance of <see cref="ParameterBinder"/>.</para>
|
||||
/// </summary>
|
||||
/// <param name="modelMetadataProvider">The <see cref="IModelMetadataProvider"/>.</param>
|
||||
/// <param name="modelBinderFactory">The <see cref="IModelBinderFactory"/>.</param>
|
||||
/// <param name="validator">The <see cref="IObjectModelValidator"/>.</param>
|
||||
[Obsolete("This constructor is obsolete and will be removed in a future version. The recommended alternative"
|
||||
+ " is the overload that takes an " + nameof(IModelValidatorProvider) + " and " + nameof(ILoggerFactory)
|
||||
+ " instead of an " + nameof(IObjectModelValidator) + ".")]
|
||||
public ParameterBinder(
|
||||
IModelMetadataProvider modelMetadataProvider,
|
||||
IModelBinderFactory modelBinderFactory,
|
||||
IObjectModelValidator validator)
|
||||
: this(
|
||||
modelMetadataProvider,
|
||||
modelBinderFactory,
|
||||
validatorProvider: null,
|
||||
validatorForBackCompatOnly: validator,
|
||||
loggerFactory: NullLoggerFactory.Instance)
|
||||
{
|
||||
// Note: When this obsolete constructor overload is removed, also remember
|
||||
// to remove the validatorForBackCompatOnly field.
|
||||
|
||||
if (validator == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(validator));
|
||||
}
|
||||
}
|
||||
|
||||
private ParameterBinder(
|
||||
IModelMetadataProvider modelMetadataProvider,
|
||||
IModelBinderFactory modelBinderFactory,
|
||||
IModelValidatorProvider validatorProvider,
|
||||
IObjectModelValidator validatorForBackCompatOnly,
|
||||
IObjectModelValidator validator,
|
||||
ILoggerFactory loggerFactory)
|
||||
{
|
||||
if (modelMetadataProvider == null)
|
||||
|
|
@ -119,6 +61,11 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding
|
|||
throw new ArgumentNullException(nameof(modelBinderFactory));
|
||||
}
|
||||
|
||||
if (validator == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(validator));
|
||||
}
|
||||
|
||||
if (loggerFactory == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(loggerFactory));
|
||||
|
|
@ -126,9 +73,7 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding
|
|||
|
||||
_modelMetadataProvider = modelMetadataProvider;
|
||||
_modelBinderFactory = modelBinderFactory;
|
||||
_validatorProvider = validatorProvider;
|
||||
_validatorForBackCompatOnly = validatorForBackCompatOnly;
|
||||
_validatorCache = new ValidatorCache();
|
||||
_objectModelValidator = validator;
|
||||
Logger = loggerFactory.CreateLogger(GetType());
|
||||
}
|
||||
|
||||
|
|
@ -279,14 +224,15 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding
|
|||
|
||||
var modelBindingResult = modelBindingContext.Result;
|
||||
|
||||
if (_validatorForBackCompatOnly != null)
|
||||
var baseObjectValidator = _objectModelValidator as ObjectModelValidator;
|
||||
if (baseObjectValidator == null)
|
||||
{
|
||||
// Since we don't have access to an IModelValidatorProvider, fall back
|
||||
// on back-compatibility logic. In this scenario, top-level validation
|
||||
// attributes will be ignored like they were historically.
|
||||
// For legacy implementations (which directly implemented IObjectModelValidator), fall back to the
|
||||
// back-compatibility logic. In this scenario, top-level validation attributes will be ignored like
|
||||
// they were historically.
|
||||
if (modelBindingResult.IsModelSet)
|
||||
{
|
||||
_validatorForBackCompatOnly.Validate(
|
||||
_objectModelValidator.Validate(
|
||||
actionContext,
|
||||
modelBindingContext.ValidationState,
|
||||
modelBindingContext.ModelName,
|
||||
|
|
@ -298,6 +244,7 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding
|
|||
Logger.AttemptingToValidateParameterOrProperty(parameter, modelBindingContext);
|
||||
|
||||
EnforceBindRequiredAndValidate(
|
||||
baseObjectValidator,
|
||||
actionContext,
|
||||
metadata,
|
||||
modelBindingContext,
|
||||
|
|
@ -309,7 +256,12 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding
|
|||
return modelBindingResult;
|
||||
}
|
||||
|
||||
private void EnforceBindRequiredAndValidate(ActionContext actionContext, ModelMetadata metadata, ModelBindingContext modelBindingContext, ModelBindingResult modelBindingResult)
|
||||
private void EnforceBindRequiredAndValidate(
|
||||
ObjectModelValidator baseObjectValidator,
|
||||
ActionContext actionContext,
|
||||
ModelMetadata metadata,
|
||||
ModelBindingContext modelBindingContext,
|
||||
ModelBindingResult modelBindingResult)
|
||||
{
|
||||
if (!modelBindingResult.IsModelSet && metadata.IsBindingRequired)
|
||||
{
|
||||
|
|
@ -321,18 +273,12 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding
|
|||
else if (modelBindingResult.IsModelSet || metadata.IsRequired)
|
||||
{
|
||||
// Enforce any other validation rules
|
||||
var visitor = new ValidationVisitor(
|
||||
baseObjectValidator.Validate(
|
||||
actionContext,
|
||||
_validatorProvider,
|
||||
_validatorCache,
|
||||
_modelMetadataProvider,
|
||||
modelBindingContext.ValidationState);
|
||||
|
||||
visitor.Validate(
|
||||
metadata,
|
||||
modelBindingContext.ValidationState,
|
||||
modelBindingContext.ModelName,
|
||||
modelBindingResult.Model,
|
||||
alwaysValidateAtTopLevel: metadata.IsRequired);
|
||||
metadata);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -109,7 +109,7 @@ namespace Microsoft.AspNetCore.Mvc.Internal
|
|||
new ParameterBinder(
|
||||
modelMetadataProvider,
|
||||
modelBinderFactory,
|
||||
Mock.Of<IModelValidatorProvider>(),
|
||||
Mock.Of<IObjectModelValidator>(),
|
||||
NullLoggerFactory.Instance),
|
||||
modelBinderFactory,
|
||||
modelMetadataProvider,
|
||||
|
|
|
|||
|
|
@ -49,10 +49,19 @@ namespace Microsoft.AspNetCore.Mvc.Internal
|
|||
.Setup(b => b.BindModelAsync(It.IsAny<DefaultModelBindingContext>()))
|
||||
.Verifiable();
|
||||
|
||||
var mockValidator = CreateMockValidator();
|
||||
var mockValidator = new Mock<IModelValidator>(MockBehavior.Strict);
|
||||
mockValidator.Setup(o => o.Validate(It.IsAny<ModelValidationContext>()));
|
||||
|
||||
var factory = GetModelBinderFactory(binder.Object);
|
||||
var modelMetadataProvider = TestModelMetadataProvider.CreateDefaultProvider();
|
||||
var controller = new TestController();
|
||||
var parameterBinder = GetParameterBinder(factory);
|
||||
var parameterBinder = new ParameterBinder(
|
||||
modelMetadataProvider,
|
||||
factory,
|
||||
new DefaultObjectValidator(
|
||||
modelMetadataProvider,
|
||||
new[] { GetModelValidatorProvider(mockValidator.Object) }),
|
||||
NullLoggerFactory.Instance);
|
||||
|
||||
// Act
|
||||
var binderDelegate = ControllerBinderDelegateProvider.CreateBinderDelegate(
|
||||
|
|
@ -95,10 +104,18 @@ namespace Microsoft.AspNetCore.Mvc.Internal
|
|||
.Setup(b => b.BindModelAsync(It.IsAny<DefaultModelBindingContext>()))
|
||||
.Verifiable();
|
||||
|
||||
var mockValidator = CreateMockValidator();
|
||||
var mockValidator = new Mock<IModelValidator>(MockBehavior.Strict);
|
||||
mockValidator.Setup(o => o.Validate(It.IsAny<ModelValidationContext>()));
|
||||
var factory = GetModelBinderFactory(binder.Object);
|
||||
var modelMetadataProvider = TestModelMetadataProvider.CreateDefaultProvider();
|
||||
var controller = new TestController();
|
||||
var parameterBinder = GetParameterBinder(factory);
|
||||
var parameterBinder = new ParameterBinder(
|
||||
modelMetadataProvider,
|
||||
factory,
|
||||
new DefaultObjectValidator(
|
||||
modelMetadataProvider,
|
||||
new[] { GetModelValidatorProvider(mockValidator.Object) }),
|
||||
NullLoggerFactory.Instance);
|
||||
|
||||
// Act
|
||||
var binderDelegate = ControllerBinderDelegateProvider.CreateBinderDelegate(
|
||||
|
|
@ -139,7 +156,14 @@ namespace Microsoft.AspNetCore.Mvc.Internal
|
|||
.Setup(b => b.BindModelAsync(It.IsAny<DefaultModelBindingContext>()))
|
||||
.Returns(Task.CompletedTask);
|
||||
var factory = GetModelBinderFactory(binder.Object);
|
||||
var parameterBinder = GetParameterBinder(factory);
|
||||
var modelMetadataProvider = TestModelMetadataProvider.CreateDefaultProvider();
|
||||
var parameterBinder = new ParameterBinder(
|
||||
modelMetadataProvider,
|
||||
factory,
|
||||
new DefaultObjectValidator(
|
||||
modelMetadataProvider,
|
||||
new IModelValidatorProvider[] { }),
|
||||
NullLoggerFactory.Instance);
|
||||
|
||||
var controllerContext = GetControllerContext(actionDescriptor);
|
||||
var controller = new TestController();
|
||||
|
|
@ -149,7 +173,7 @@ namespace Microsoft.AspNetCore.Mvc.Internal
|
|||
var binderDelegate = ControllerBinderDelegateProvider.CreateBinderDelegate(
|
||||
parameterBinder,
|
||||
factory,
|
||||
TestModelMetadataProvider.CreateDefaultProvider(),
|
||||
modelMetadataProvider,
|
||||
actionDescriptor);
|
||||
|
||||
await binderDelegate(controllerContext, controller, arguments);
|
||||
|
|
@ -176,7 +200,14 @@ namespace Microsoft.AspNetCore.Mvc.Internal
|
|||
.Setup(b => b.BindModelAsync(It.IsAny<DefaultModelBindingContext>()))
|
||||
.Returns(Task.CompletedTask);
|
||||
var factory = GetModelBinderFactory(binder.Object);
|
||||
var parameterBinder = GetParameterBinder(factory);
|
||||
var modelMetadataProvider = TestModelMetadataProvider.CreateDefaultProvider();
|
||||
var parameterBinder = new ParameterBinder(
|
||||
modelMetadataProvider,
|
||||
factory,
|
||||
new DefaultObjectValidator(
|
||||
modelMetadataProvider,
|
||||
new IModelValidatorProvider[] { }),
|
||||
NullLoggerFactory.Instance);
|
||||
|
||||
var controllerContext = GetControllerContext(actionDescriptor);
|
||||
var controller = new TestController();
|
||||
|
|
@ -186,7 +217,7 @@ namespace Microsoft.AspNetCore.Mvc.Internal
|
|||
var binderDelegate = ControllerBinderDelegateProvider.CreateBinderDelegate(
|
||||
parameterBinder,
|
||||
factory,
|
||||
TestModelMetadataProvider.CreateDefaultProvider(),
|
||||
modelMetadataProvider,
|
||||
actionDescriptor);
|
||||
|
||||
await binderDelegate(controllerContext, controller, arguments);
|
||||
|
|
@ -221,7 +252,14 @@ namespace Microsoft.AspNetCore.Mvc.Internal
|
|||
})
|
||||
.Returns(Task.CompletedTask);
|
||||
var factory = GetModelBinderFactory(binder.Object);
|
||||
var parameterBinder = GetParameterBinder(factory);
|
||||
var modelMetadataProvider = TestModelMetadataProvider.CreateDefaultProvider();
|
||||
var parameterBinder = new ParameterBinder(
|
||||
modelMetadataProvider,
|
||||
factory,
|
||||
new DefaultObjectValidator(
|
||||
modelMetadataProvider,
|
||||
new IModelValidatorProvider[] { }),
|
||||
NullLoggerFactory.Instance);
|
||||
|
||||
var controllerContext = GetControllerContext(actionDescriptor);
|
||||
var controller = new TestController();
|
||||
|
|
@ -231,7 +269,7 @@ namespace Microsoft.AspNetCore.Mvc.Internal
|
|||
var binderDelegate = ControllerBinderDelegateProvider.CreateBinderDelegate(
|
||||
parameterBinder,
|
||||
factory,
|
||||
TestModelMetadataProvider.CreateDefaultProvider(),
|
||||
modelMetadataProvider,
|
||||
actionDescriptor);
|
||||
|
||||
await binderDelegate(controllerContext, controller, arguments);
|
||||
|
|
@ -259,7 +297,6 @@ namespace Microsoft.AspNetCore.Mvc.Internal
|
|||
var mockBinder = new Mock<IModelBinder>();
|
||||
var factory = GetModelBinderFactory(mockBinder.Object);
|
||||
|
||||
var parameterBinder = GetParameterBinder(factory, CreateMockValidator().Object);
|
||||
var controller = new TestController();
|
||||
var arguments = new Dictionary<string, object>(StringComparer.Ordinal);
|
||||
|
||||
|
|
@ -270,6 +307,13 @@ namespace Microsoft.AspNetCore.Mvc.Internal
|
|||
mockMetadataProvider
|
||||
.Setup(p => p.GetMetadataForParameter(ParameterInfos.NoAttributesParameterInfo))
|
||||
.Returns(modelMetadata.Object);
|
||||
var parameterBinder = new ParameterBinder(
|
||||
mockMetadataProvider.Object,
|
||||
factory,
|
||||
new DefaultObjectValidator(
|
||||
mockMetadataProvider.Object,
|
||||
new IModelValidatorProvider[] { }),
|
||||
NullLoggerFactory.Instance);
|
||||
|
||||
// Act
|
||||
var binderDelegate = ControllerBinderDelegateProvider.CreateBinderDelegate(
|
||||
|
|
@ -304,7 +348,6 @@ namespace Microsoft.AspNetCore.Mvc.Internal
|
|||
var mockBinder = new Mock<IModelBinder>();
|
||||
var factory = GetModelBinderFactory(mockBinder.Object);
|
||||
|
||||
var parameterBinder = GetParameterBinder(factory, CreateMockValidator().Object);
|
||||
var controller = new TestController();
|
||||
var arguments = new Dictionary<string, object>(StringComparer.Ordinal);
|
||||
|
||||
|
|
@ -314,6 +357,13 @@ namespace Microsoft.AspNetCore.Mvc.Internal
|
|||
mockMetadataProvider
|
||||
.Setup(p => p.GetMetadataForType(typeof(Person)))
|
||||
.Returns(modelMetadata.Object);
|
||||
var parameterBinder = new ParameterBinder(
|
||||
mockMetadataProvider.Object,
|
||||
factory,
|
||||
new DefaultObjectValidator(
|
||||
mockMetadataProvider.Object,
|
||||
new IModelValidatorProvider[] { }),
|
||||
NullLoggerFactory.Instance);
|
||||
|
||||
// Act
|
||||
var binderDelegate = ControllerBinderDelegateProvider.CreateBinderDelegate(
|
||||
|
|
@ -348,13 +398,19 @@ namespace Microsoft.AspNetCore.Mvc.Internal
|
|||
|
||||
var factory = GetModelBinderFactory("Hello");
|
||||
|
||||
var mockValidator = CreateMockValidator();
|
||||
var mockValidator = new Mock<IModelValidator>();
|
||||
mockValidator
|
||||
.Setup(o => o.Validate(It.IsAny<ModelValidationContext>()))
|
||||
.Returns(new[] { new ModelValidationResult("memberName", "some message") });
|
||||
|
||||
var modelMetadataProvider = TestModelMetadataProvider.CreateDefaultProvider();
|
||||
var parameterBinder = GetParameterBinder(factory, mockValidator.Object, modelMetadataProvider);
|
||||
var parameterBinder = new ParameterBinder(
|
||||
modelMetadataProvider,
|
||||
factory,
|
||||
new DefaultObjectValidator(
|
||||
modelMetadataProvider,
|
||||
new[] { GetModelValidatorProvider(mockValidator.Object) }),
|
||||
NullLoggerFactory.Instance);
|
||||
var controller = new TestController();
|
||||
var arguments = new Dictionary<string, object>(StringComparer.Ordinal);
|
||||
|
||||
|
|
@ -400,16 +456,24 @@ namespace Microsoft.AspNetCore.Mvc.Internal
|
|||
.Setup(b => b.BindModelAsync(It.IsAny<DefaultModelBindingContext>()))
|
||||
.Returns(Task.CompletedTask);
|
||||
|
||||
var mockValidator = CreateMockValidator();
|
||||
var mockValidator = new Mock<IModelValidator>(MockBehavior.Strict);
|
||||
mockValidator.Setup(o => o.Validate(It.IsAny<ModelValidationContext>()));
|
||||
var factory = GetModelBinderFactory(binder.Object);
|
||||
var controller = new TestController();
|
||||
var parameterBinder = GetParameterBinder(factory, mockValidator.Object);
|
||||
var modelMetadataProvider = TestModelMetadataProvider.CreateDefaultProvider();
|
||||
var parameterBinder = new ParameterBinder(
|
||||
modelMetadataProvider,
|
||||
factory,
|
||||
new DefaultObjectValidator(
|
||||
modelMetadataProvider,
|
||||
new IModelValidatorProvider[] { }),
|
||||
NullLoggerFactory.Instance);
|
||||
|
||||
// Act
|
||||
var binderDelegate = ControllerBinderDelegateProvider.CreateBinderDelegate(
|
||||
parameterBinder,
|
||||
factory,
|
||||
TestModelMetadataProvider.CreateDefaultProvider(),
|
||||
modelMetadataProvider,
|
||||
actionDescriptor);
|
||||
|
||||
await binderDelegate(controllerContext, controller, arguments);
|
||||
|
|
@ -437,14 +501,21 @@ namespace Microsoft.AspNetCore.Mvc.Internal
|
|||
var controller = new TestController();
|
||||
var arguments = new Dictionary<string, object>(StringComparer.Ordinal);
|
||||
|
||||
var mockValidator = CreateMockValidator();
|
||||
var mockValidator = new Mock<IModelValidator>(MockBehavior.Strict);
|
||||
mockValidator
|
||||
.Setup(o => o.Validate(It.IsAny<ModelValidationContext>()))
|
||||
.Returns(new[] { new ModelValidationResult("memberName", "some message") });
|
||||
|
||||
var factory = GetModelBinderFactory("Hello");
|
||||
var modelMetadataProvider = TestModelMetadataProvider.CreateDefaultProvider();
|
||||
var parameterBinder = GetParameterBinder(factory, mockValidator.Object, modelMetadataProvider);
|
||||
|
||||
var parameterBinder = new ParameterBinder(
|
||||
modelMetadataProvider,
|
||||
factory,
|
||||
new DefaultObjectValidator(
|
||||
modelMetadataProvider,
|
||||
new[] { GetModelValidatorProvider(mockValidator.Object) }),
|
||||
NullLoggerFactory.Instance);
|
||||
|
||||
// Act
|
||||
var binderDelegate = ControllerBinderDelegateProvider.CreateBinderDelegate(
|
||||
|
|
@ -466,6 +537,51 @@ namespace Microsoft.AspNetCore.Mvc.Internal
|
|||
controllerContext.ModelState["memberName"].Errors.Single().ErrorMessage);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task DoesNotValidate_ForControllerProperties_IfObjectValidatorDoesNotInheritFromBase()
|
||||
{
|
||||
// Arrange
|
||||
var actionDescriptor = GetActionDescriptor();
|
||||
actionDescriptor.BoundProperties.Add(
|
||||
new ParameterDescriptor
|
||||
{
|
||||
Name = nameof(TestController.ValidatedProperty),
|
||||
ParameterType = typeof(string),
|
||||
});
|
||||
|
||||
var controllerContext = GetControllerContext(actionDescriptor);
|
||||
var controller = new TestController();
|
||||
var arguments = new Dictionary<string, object>(StringComparer.Ordinal);
|
||||
|
||||
var factory = GetModelBinderFactory("Hello");
|
||||
var modelMetadataProvider = TestModelMetadataProvider.CreateDefaultProvider();
|
||||
var mockValidator = new Mock<IObjectModelValidator>(MockBehavior.Strict);
|
||||
mockValidator
|
||||
.Setup(o => o.Validate(
|
||||
It.IsAny<ActionContext>(),
|
||||
It.IsAny<ValidationStateDictionary>(),
|
||||
It.IsAny<string>(),
|
||||
It.IsAny<object>()));
|
||||
|
||||
var parameterBinder = new ParameterBinder(
|
||||
modelMetadataProvider,
|
||||
factory,
|
||||
mockValidator.Object,
|
||||
NullLoggerFactory.Instance);
|
||||
|
||||
// Act
|
||||
var binderDelegate = ControllerBinderDelegateProvider.CreateBinderDelegate(
|
||||
parameterBinder,
|
||||
factory,
|
||||
modelMetadataProvider,
|
||||
actionDescriptor);
|
||||
|
||||
await binderDelegate(controllerContext, controller, arguments);
|
||||
|
||||
// Assert
|
||||
Assert.True(controllerContext.ModelState.IsValid);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task BindActionArgumentsAsync_DoesNotCallValidator_ForControllerProperties_IfModelBinderFails()
|
||||
{
|
||||
|
|
@ -487,15 +603,23 @@ namespace Microsoft.AspNetCore.Mvc.Internal
|
|||
.Setup(b => b.BindModelAsync(It.IsAny<DefaultModelBindingContext>()))
|
||||
.Returns(Task.CompletedTask);
|
||||
|
||||
var mockValidator = CreateMockValidator();
|
||||
var mockValidator = new Mock<IModelValidator>(MockBehavior.Strict);
|
||||
mockValidator.Setup(o => o.Validate(It.IsAny<ModelValidationContext>()));
|
||||
var factory = GetModelBinderFactory(binder.Object);
|
||||
var parameterBinder = GetParameterBinder(factory, mockValidator.Object);
|
||||
var modelMetadataProvider = TestModelMetadataProvider.CreateDefaultProvider();
|
||||
var parameterBinder = new ParameterBinder(
|
||||
modelMetadataProvider,
|
||||
factory,
|
||||
new DefaultObjectValidator(
|
||||
modelMetadataProvider,
|
||||
new[] { GetModelValidatorProvider(mockValidator.Object) }),
|
||||
NullLoggerFactory.Instance);
|
||||
|
||||
// Act
|
||||
var binderDelegate = ControllerBinderDelegateProvider.CreateBinderDelegate(
|
||||
parameterBinder,
|
||||
factory,
|
||||
TestModelMetadataProvider.CreateDefaultProvider(),
|
||||
modelMetadataProvider,
|
||||
actionDescriptor);
|
||||
|
||||
await binderDelegate(controllerContext, controller, arguments);
|
||||
|
|
@ -525,14 +649,20 @@ namespace Microsoft.AspNetCore.Mvc.Internal
|
|||
var arguments = new Dictionary<string, object>(StringComparer.Ordinal);
|
||||
|
||||
var factory = GetModelBinderFactory("Hello");
|
||||
var parameterBinder = GetParameterBinder(factory);
|
||||
|
||||
var modelMetadataProvider = TestModelMetadataProvider.CreateDefaultProvider();
|
||||
var parameterBinder = new ParameterBinder(
|
||||
modelMetadataProvider,
|
||||
factory,
|
||||
new DefaultObjectValidator(
|
||||
modelMetadataProvider,
|
||||
new IModelValidatorProvider[] { }),
|
||||
NullLoggerFactory.Instance);
|
||||
|
||||
// Act
|
||||
var binderDelegate = ControllerBinderDelegateProvider.CreateBinderDelegate(
|
||||
parameterBinder,
|
||||
factory,
|
||||
TestModelMetadataProvider.CreateDefaultProvider(),
|
||||
modelMetadataProvider,
|
||||
actionDescriptor);
|
||||
|
||||
await binderDelegate(controllerContext, controller, arguments);
|
||||
|
|
@ -562,13 +692,20 @@ namespace Microsoft.AspNetCore.Mvc.Internal
|
|||
|
||||
var expected = new List<string> { "Hello", "World", "!!" };
|
||||
var factory = GetModelBinderFactory(expected);
|
||||
var parameterBinder = GetParameterBinder(factory);
|
||||
var modelMetadataProvider = TestModelMetadataProvider.CreateDefaultProvider();
|
||||
var parameterBinder = new ParameterBinder(
|
||||
modelMetadataProvider,
|
||||
factory,
|
||||
new DefaultObjectValidator(
|
||||
modelMetadataProvider,
|
||||
new IModelValidatorProvider[] { }),
|
||||
NullLoggerFactory.Instance);
|
||||
|
||||
// Act
|
||||
var binderDelegate = ControllerBinderDelegateProvider.CreateBinderDelegate(
|
||||
parameterBinder,
|
||||
factory,
|
||||
TestModelMetadataProvider.CreateDefaultProvider(),
|
||||
modelMetadataProvider,
|
||||
actionDescriptor);
|
||||
|
||||
await binderDelegate(controllerContext, controller, arguments);
|
||||
|
|
@ -598,8 +735,14 @@ namespace Microsoft.AspNetCore.Mvc.Internal
|
|||
|
||||
var binder = new StubModelBinder(ModelBindingResult.Success(model: null));
|
||||
var factory = GetModelBinderFactory(binder);
|
||||
var parameterBinder = GetParameterBinder(factory);
|
||||
|
||||
var modelMetadataProvider = TestModelMetadataProvider.CreateDefaultProvider();
|
||||
var parameterBinder = new ParameterBinder(
|
||||
modelMetadataProvider,
|
||||
factory,
|
||||
new DefaultObjectValidator(
|
||||
modelMetadataProvider,
|
||||
new IModelValidatorProvider[] { }),
|
||||
NullLoggerFactory.Instance);
|
||||
|
||||
// Some non default value.
|
||||
controller.NonNullableProperty = -1;
|
||||
|
|
@ -608,7 +751,7 @@ namespace Microsoft.AspNetCore.Mvc.Internal
|
|||
var binderDelegate = ControllerBinderDelegateProvider.CreateBinderDelegate(
|
||||
parameterBinder,
|
||||
factory,
|
||||
TestModelMetadataProvider.CreateDefaultProvider(),
|
||||
modelMetadataProvider,
|
||||
actionDescriptor);
|
||||
|
||||
await binderDelegate(controllerContext, controller, arguments);
|
||||
|
|
@ -636,8 +779,14 @@ namespace Microsoft.AspNetCore.Mvc.Internal
|
|||
|
||||
var binder = new StubModelBinder(ModelBindingResult.Success(model: null));
|
||||
var factory = GetModelBinderFactory(binder);
|
||||
var parameterBinder = GetParameterBinder(factory);
|
||||
|
||||
var modelMetadataProvider = TestModelMetadataProvider.CreateDefaultProvider();
|
||||
var parameterBinder = new ParameterBinder(
|
||||
modelMetadataProvider,
|
||||
factory,
|
||||
new DefaultObjectValidator(
|
||||
modelMetadataProvider,
|
||||
new IModelValidatorProvider[] { }),
|
||||
NullLoggerFactory.Instance);
|
||||
|
||||
// Some non default value.
|
||||
controller.NullableProperty = -1;
|
||||
|
|
@ -646,7 +795,7 @@ namespace Microsoft.AspNetCore.Mvc.Internal
|
|||
var binderDelegate = ControllerBinderDelegateProvider.CreateBinderDelegate(
|
||||
parameterBinder,
|
||||
factory,
|
||||
TestModelMetadataProvider.CreateDefaultProvider(),
|
||||
modelMetadataProvider,
|
||||
actionDescriptor);
|
||||
|
||||
await binderDelegate(controllerContext, controller, arguments);
|
||||
|
|
@ -695,7 +844,14 @@ namespace Microsoft.AspNetCore.Mvc.Internal
|
|||
|
||||
var binder = new StubModelBinder(ModelBindingResult.Success(model: null));
|
||||
var factory = GetModelBinderFactory(binder);
|
||||
var parameterBinder = GetParameterBinder(factory);
|
||||
var modelMetadataProvider = TestModelMetadataProvider.CreateDefaultProvider();
|
||||
var parameterBinder = new ParameterBinder(
|
||||
modelMetadataProvider,
|
||||
factory,
|
||||
new DefaultObjectValidator(
|
||||
modelMetadataProvider,
|
||||
new IModelValidatorProvider[] { }),
|
||||
NullLoggerFactory.Instance);
|
||||
|
||||
// Some non default value.
|
||||
controller.NullableProperty = -1;
|
||||
|
|
@ -704,7 +860,7 @@ namespace Microsoft.AspNetCore.Mvc.Internal
|
|||
var binderDelegate = ControllerBinderDelegateProvider.CreateBinderDelegate(
|
||||
parameterBinder,
|
||||
factory,
|
||||
TestModelMetadataProvider.CreateDefaultProvider(),
|
||||
modelMetadataProvider,
|
||||
actionDescriptor);
|
||||
|
||||
await binderDelegate(controllerContext, controller, arguments);
|
||||
|
|
@ -754,7 +910,14 @@ namespace Microsoft.AspNetCore.Mvc.Internal
|
|||
|
||||
var binder = new StubModelBinder(ModelBindingResult.Success(model: null));
|
||||
var factory = GetModelBinderFactory(binder);
|
||||
var parameterBinder = GetParameterBinder(factory);
|
||||
var modelMetadataProvider = TestModelMetadataProvider.CreateDefaultProvider();
|
||||
var parameterBinder = new ParameterBinder(
|
||||
modelMetadataProvider,
|
||||
factory,
|
||||
new DefaultObjectValidator(
|
||||
modelMetadataProvider,
|
||||
new IModelValidatorProvider[] { }),
|
||||
NullLoggerFactory.Instance);
|
||||
|
||||
// Some non default value.
|
||||
controller.NullableProperty = -1;
|
||||
|
|
@ -763,7 +926,7 @@ namespace Microsoft.AspNetCore.Mvc.Internal
|
|||
var binderDelegate = ControllerBinderDelegateProvider.CreateBinderDelegate(
|
||||
parameterBinder,
|
||||
factory,
|
||||
TestModelMetadataProvider.CreateDefaultProvider(),
|
||||
modelMetadataProvider,
|
||||
actionDescriptor);
|
||||
|
||||
await binderDelegate(controllerContext, controller, arguments);
|
||||
|
|
@ -837,13 +1000,20 @@ namespace Microsoft.AspNetCore.Mvc.Internal
|
|||
var arguments = new Dictionary<string, object>(StringComparer.Ordinal);
|
||||
|
||||
var factory = GetModelBinderFactory(inputValue);
|
||||
var parameterBinder = GetParameterBinder(factory);
|
||||
var modelMetadataProvider = TestModelMetadataProvider.CreateDefaultProvider();
|
||||
var parameterBinder = new ParameterBinder(
|
||||
modelMetadataProvider,
|
||||
factory,
|
||||
new DefaultObjectValidator(
|
||||
modelMetadataProvider,
|
||||
new IModelValidatorProvider[] { }),
|
||||
NullLoggerFactory.Instance);
|
||||
|
||||
// Act
|
||||
var binderDelegate = ControllerBinderDelegateProvider.CreateBinderDelegate(
|
||||
parameterBinder,
|
||||
factory,
|
||||
TestModelMetadataProvider.CreateDefaultProvider(),
|
||||
modelMetadataProvider,
|
||||
actionDescriptor);
|
||||
|
||||
await binderDelegate(controllerContext, controller, arguments);
|
||||
|
|
@ -908,13 +1078,20 @@ namespace Microsoft.AspNetCore.Mvc.Internal
|
|||
var factory = GetModelBinderFactory(binder);
|
||||
controllerContext.ValueProviderFactories.Add(new SimpleValueProviderFactory());
|
||||
|
||||
var parameterBinder = GetParameterBinder(factory);
|
||||
var modelMetadataProvider = TestModelMetadataProvider.CreateDefaultProvider();
|
||||
var parameterBinder = new ParameterBinder(
|
||||
modelMetadataProvider,
|
||||
factory,
|
||||
new DefaultObjectValidator(
|
||||
modelMetadataProvider,
|
||||
new IModelValidatorProvider[] { }),
|
||||
NullLoggerFactory.Instance);
|
||||
|
||||
// Act
|
||||
var binderDelegate = ControllerBinderDelegateProvider.CreateBinderDelegate(
|
||||
parameterBinder,
|
||||
factory,
|
||||
TestModelMetadataProvider.CreateDefaultProvider(),
|
||||
modelMetadataProvider,
|
||||
actionDescriptor);
|
||||
|
||||
await binderDelegate(controllerContext, controller, arguments);
|
||||
|
|
@ -1004,7 +1181,8 @@ namespace Microsoft.AspNetCore.Mvc.Internal
|
|||
var parameterBinder = new Mock<ParameterBinder>(
|
||||
new EmptyModelMetadataProvider(),
|
||||
factory,
|
||||
modelValidatorProvider);
|
||||
new DefaultObjectValidator(modelMetadataProvider, new[] { modelValidatorProvider }),
|
||||
NullLoggerFactory.Instance);
|
||||
parameterBinder.Setup(p => p.BindModelAsync(
|
||||
It.IsAny<ActionContext>(),
|
||||
It.IsAny<IModelBinder>(),
|
||||
|
|
@ -1092,6 +1270,27 @@ namespace Microsoft.AspNetCore.Mvc.Internal
|
|||
};
|
||||
}
|
||||
|
||||
private static IModelValidatorProvider GetModelValidatorProvider(IModelValidator validator = null)
|
||||
{
|
||||
if (validator == null)
|
||||
{
|
||||
validator = Mock.Of<IModelValidator>();
|
||||
}
|
||||
|
||||
var validatorProvider = new Mock<IModelValidatorProvider>();
|
||||
validatorProvider
|
||||
.Setup(p => p.CreateValidators(It.IsAny<ModelValidatorProviderContext>()))
|
||||
.Callback<ModelValidatorProviderContext>(context =>
|
||||
{
|
||||
foreach (var result in context.Results)
|
||||
{
|
||||
result.Validator = validator;
|
||||
result.IsReusable = true;
|
||||
}
|
||||
});
|
||||
return validatorProvider.Object;
|
||||
}
|
||||
|
||||
private static ModelBinderFactory GetModelBinderFactory(object model = null)
|
||||
{
|
||||
var binder = new Mock<IModelBinder>();
|
||||
|
|
@ -1118,12 +1317,13 @@ namespace Microsoft.AspNetCore.Mvc.Internal
|
|||
|
||||
private static ParameterBinder GetParameterBinder(
|
||||
IModelBinderFactory factory = null,
|
||||
IModelValidator validator = null,
|
||||
IModelMetadataProvider modelMetadataProvider = null)
|
||||
IObjectModelValidator validator = null,
|
||||
IModelMetadataProvider modelMetadataProvider = null,
|
||||
IModelValidatorProvider modelValidatorProvider = null)
|
||||
{
|
||||
if (validator == null)
|
||||
{
|
||||
validator = CreateMockValidator().Object;
|
||||
validator = CreateObjectValidator();
|
||||
}
|
||||
|
||||
if (factory == null)
|
||||
|
|
@ -1131,32 +1331,32 @@ namespace Microsoft.AspNetCore.Mvc.Internal
|
|||
factory = TestModelBinderFactory.CreateDefault();
|
||||
}
|
||||
|
||||
var validatorProvider = new Mock<IModelValidatorProvider>();
|
||||
validatorProvider
|
||||
.Setup(p => p.CreateValidators(It.IsAny<ModelValidatorProviderContext>()))
|
||||
.Callback<ModelValidatorProviderContext>(context =>
|
||||
{
|
||||
foreach (var result in context.Results)
|
||||
{
|
||||
result.Validator = validator;
|
||||
result.IsReusable = true;
|
||||
}
|
||||
});
|
||||
if (modelValidatorProvider == null)
|
||||
{
|
||||
modelValidatorProvider = Mock.Of<IModelValidatorProvider>();
|
||||
}
|
||||
|
||||
var metadataProvider = modelMetadataProvider ?? TestModelMetadataProvider.CreateDefaultProvider();
|
||||
var objectModelValidator = new DefaultObjectValidator(
|
||||
metadataProvider,
|
||||
new[] { modelValidatorProvider });
|
||||
return new ParameterBinder(
|
||||
modelMetadataProvider ?? TestModelMetadataProvider.CreateDefaultProvider(),
|
||||
metadataProvider,
|
||||
factory,
|
||||
validatorProvider.Object,
|
||||
objectModelValidator,
|
||||
NullLoggerFactory.Instance);
|
||||
}
|
||||
|
||||
private static Mock<IModelValidator> CreateMockValidator()
|
||||
private static IObjectModelValidator CreateObjectValidator()
|
||||
{
|
||||
var mockValidator = new Mock<IModelValidator>(MockBehavior.Strict);
|
||||
var mockValidator = new Mock<IObjectModelValidator>(MockBehavior.Strict);
|
||||
mockValidator
|
||||
.Setup(o => o.Validate(
|
||||
It.IsAny<ModelValidationContext>()));
|
||||
return mockValidator;
|
||||
It.IsAny<ActionContext>(),
|
||||
It.IsAny<ValidationStateDictionary>(),
|
||||
It.IsAny<string>(),
|
||||
It.IsAny<object>()));
|
||||
return mockValidator.Object;
|
||||
}
|
||||
|
||||
// No need for bind-related attributes on properties in this controller class. Properties are added directly
|
||||
|
|
@ -1258,5 +1458,17 @@ namespace Microsoft.AspNetCore.Mvc.Internal
|
|||
{
|
||||
}
|
||||
}
|
||||
|
||||
private class TestObjectModelValidator : IObjectModelValidator
|
||||
{
|
||||
public void Validate(
|
||||
ActionContext actionContext,
|
||||
ValidationStateDictionary validationState,
|
||||
string prefix,
|
||||
object model)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -448,7 +448,7 @@ namespace Microsoft.AspNetCore.Mvc.Internal
|
|||
: base(
|
||||
new EmptyModelMetadataProvider(),
|
||||
TestModelBinderFactory.CreateDefault(),
|
||||
Mock.Of<IModelValidatorProvider>(),
|
||||
Mock.Of<IObjectModelValidator>(),
|
||||
NullLoggerFactory.Instance)
|
||||
{
|
||||
_actionParameters = actionParameters;
|
||||
|
|
|
|||
|
|
@ -98,7 +98,7 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding
|
|||
var parameterBinder = new ParameterBinder(
|
||||
metadataProvider,
|
||||
factory.Object,
|
||||
CreateMockValidatorProvider(),
|
||||
Mock.Of< IObjectModelValidator>(),
|
||||
NullLoggerFactory.Instance);
|
||||
|
||||
var controllerContext = GetControllerContext();
|
||||
|
|
@ -149,7 +149,7 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding
|
|||
var argumentBinder = new ParameterBinder(
|
||||
metadataProvider,
|
||||
factory.Object,
|
||||
CreateMockValidatorProvider(),
|
||||
Mock.Of<IObjectModelValidator>(),
|
||||
NullLoggerFactory.Instance);
|
||||
|
||||
var valueProvider = new SimpleValueProvider
|
||||
|
|
@ -364,10 +364,33 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding
|
|||
return new ParameterBinder(
|
||||
mockModelMetadataProvider.Object,
|
||||
mockModelBinderFactory.Object,
|
||||
CreateMockValidatorProvider(validator),
|
||||
new DefaultObjectValidator(
|
||||
mockModelMetadataProvider.Object,
|
||||
new[] { GetModelValidatorProvider(validator) }),
|
||||
NullLoggerFactory.Instance);
|
||||
}
|
||||
|
||||
private static IModelValidatorProvider GetModelValidatorProvider(IModelValidator validator = null)
|
||||
{
|
||||
if (validator == null)
|
||||
{
|
||||
validator = Mock.Of<IModelValidator>();
|
||||
}
|
||||
|
||||
var validatorProvider = new Mock<IModelValidatorProvider>();
|
||||
validatorProvider
|
||||
.Setup(p => p.CreateValidators(It.IsAny<ModelValidatorProviderContext>()))
|
||||
.Callback<ModelValidatorProviderContext>(context =>
|
||||
{
|
||||
foreach (var result in context.Results)
|
||||
{
|
||||
result.Validator = validator;
|
||||
result.IsReusable = true;
|
||||
}
|
||||
});
|
||||
return validatorProvider.Object;
|
||||
}
|
||||
|
||||
private static ParameterBinder CreateBackCompatParameterBinder(
|
||||
ModelMetadata modelMetadata,
|
||||
IObjectModelValidator validator)
|
||||
|
|
|
|||
|
|
@ -68,7 +68,9 @@ namespace Microsoft.AspNetCore.Mvc.IntegrationTests
|
|||
return new ParameterBinder(
|
||||
metadataProvider,
|
||||
new ModelBinderFactory(metadataProvider, options, serviceProvider),
|
||||
new CompositeModelValidatorProvider(GetModelValidatorProviders(options)),
|
||||
new DefaultObjectValidator(
|
||||
metadataProvider,
|
||||
new[] { new CompositeModelValidatorProvider(GetModelValidatorProviders(options)) }),
|
||||
NullLoggerFactory.Instance);
|
||||
}
|
||||
|
||||
|
|
@ -90,7 +92,9 @@ namespace Microsoft.AspNetCore.Mvc.IntegrationTests
|
|||
return new ParameterBinder(
|
||||
metadataProvider,
|
||||
new ModelBinderFactory(metadataProvider, options, services),
|
||||
new CompositeModelValidatorProvider(GetModelValidatorProviders(options)),
|
||||
new DefaultObjectValidator(
|
||||
metadataProvider,
|
||||
new[] { new CompositeModelValidatorProvider(GetModelValidatorProviders(options)) }),
|
||||
NullLoggerFactory.Instance);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -490,7 +490,7 @@ namespace Microsoft.AspNetCore.Mvc.RazorPages.Internal
|
|||
var parameterBinder = new ParameterBinder(
|
||||
modelMetadataProvider,
|
||||
TestModelBinderFactory.CreateDefault(),
|
||||
Mock.Of<IModelValidatorProvider>(),
|
||||
Mock.Of<IObjectModelValidator>(),
|
||||
NullLoggerFactory.Instance);
|
||||
|
||||
return new PageActionInvokerProvider(
|
||||
|
|
|
|||
|
|
@ -1239,10 +1239,11 @@ namespace Microsoft.AspNetCore.Mvc.RazorPages.Internal
|
|||
factory = TestModelBinderFactory.CreateDefault();
|
||||
}
|
||||
|
||||
var metadataProvider = TestModelMetadataProvider.CreateDefaultProvider();
|
||||
return new ParameterBinder(
|
||||
TestModelMetadataProvider.CreateDefaultProvider(),
|
||||
metadataProvider,
|
||||
factory,
|
||||
validator,
|
||||
new DefaultObjectValidator(metadataProvider, new[] { validator }),
|
||||
NullLoggerFactory.Instance);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -8,6 +8,7 @@ using System.Reflection;
|
|||
using System.Threading.Tasks;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Microsoft.AspNetCore.Mvc.Abstractions;
|
||||
using Microsoft.AspNetCore.Mvc.Internal;
|
||||
using Microsoft.AspNetCore.Mvc.ModelBinding;
|
||||
using Microsoft.AspNetCore.Mvc.ModelBinding.Validation;
|
||||
using Microsoft.AspNetCore.Mvc.RazorPages.Infrastructure;
|
||||
|
|
@ -35,7 +36,7 @@ namespace Microsoft.AspNetCore.Mvc.RazorPages.Internal
|
|||
var binder = new ParameterBinder(
|
||||
modelMetadataProvider,
|
||||
modelBinderFactory,
|
||||
Mock.Of<IModelValidatorProvider>(),
|
||||
Mock.Of<IObjectModelValidator>(),
|
||||
NullLoggerFactory.Instance);
|
||||
|
||||
// Act
|
||||
|
|
@ -60,7 +61,7 @@ namespace Microsoft.AspNetCore.Mvc.RazorPages.Internal
|
|||
var binder = new ParameterBinder(
|
||||
modelMetadataProvider,
|
||||
modelBinderFactory,
|
||||
Mock.Of<IModelValidatorProvider>(),
|
||||
Mock.Of<IObjectModelValidator>(),
|
||||
NullLoggerFactory.Instance);
|
||||
|
||||
// Act
|
||||
|
|
@ -84,7 +85,7 @@ namespace Microsoft.AspNetCore.Mvc.RazorPages.Internal
|
|||
var binder = new ParameterBinder(
|
||||
modelMetadataProvider,
|
||||
modelBinderFactory,
|
||||
Mock.Of<IModelValidatorProvider>(),
|
||||
Mock.Of<IObjectModelValidator>(),
|
||||
NullLoggerFactory.Instance);
|
||||
|
||||
// Act
|
||||
|
|
@ -109,7 +110,7 @@ namespace Microsoft.AspNetCore.Mvc.RazorPages.Internal
|
|||
var binder = new ParameterBinder(
|
||||
modelMetadataProvider,
|
||||
modelBinderFactory,
|
||||
Mock.Of<IModelValidatorProvider>(),
|
||||
Mock.Of<IObjectModelValidator>(),
|
||||
NullLoggerFactory.Instance);
|
||||
|
||||
// Act
|
||||
|
|
@ -133,7 +134,7 @@ namespace Microsoft.AspNetCore.Mvc.RazorPages.Internal
|
|||
var binder = new ParameterBinder(
|
||||
modelMetadataProvider,
|
||||
modelBinderFactory,
|
||||
Mock.Of<IModelValidatorProvider>(),
|
||||
Mock.Of<IObjectModelValidator>(),
|
||||
NullLoggerFactory.Instance);
|
||||
|
||||
// Act
|
||||
|
|
@ -158,7 +159,7 @@ namespace Microsoft.AspNetCore.Mvc.RazorPages.Internal
|
|||
var binder = new ParameterBinder(
|
||||
modelMetadataProvider,
|
||||
modelBinderFactory,
|
||||
Mock.Of<IModelValidatorProvider>(),
|
||||
Mock.Of<IObjectModelValidator>(),
|
||||
NullLoggerFactory.Instance);
|
||||
|
||||
// Act
|
||||
|
|
@ -533,12 +534,13 @@ namespace Microsoft.AspNetCore.Mvc.RazorPages.Internal
|
|||
|
||||
var modelMetadataProvider = TestModelMetadataProvider.CreateDefaultProvider();
|
||||
var modelBinderFactory = TestModelBinderFactory.CreateDefault();
|
||||
var validatorProvider = TestModelValidatorProvider.CreateDefaultProvider();
|
||||
|
||||
var binder = new ParameterBinder(
|
||||
modelMetadataProvider,
|
||||
modelBinderFactory,
|
||||
validatorProvider,
|
||||
new DefaultObjectValidator(
|
||||
modelMetadataProvider,
|
||||
new[] { TestModelValidatorProvider.CreateDefaultProvider() }),
|
||||
NullLoggerFactory.Instance);
|
||||
|
||||
var factory = PageBinderFactory.CreatePropertyBinder(binder, modelMetadataProvider, modelBinderFactory, actionDescriptor);
|
||||
|
|
@ -657,9 +659,14 @@ namespace Microsoft.AspNetCore.Mvc.RazorPages.Internal
|
|||
|
||||
var modelMetadataProvider = TestModelMetadataProvider.CreateDefaultProvider();
|
||||
var modelBinderFactory = TestModelBinderFactory.CreateDefault();
|
||||
var validatorProvider = TestModelValidatorProvider.CreateDefaultProvider();
|
||||
|
||||
var parameterBinder = new ParameterBinder(modelMetadataProvider, modelBinderFactory, validatorProvider, NullLoggerFactory.Instance);
|
||||
var parameterBinder = new ParameterBinder(
|
||||
modelMetadataProvider,
|
||||
modelBinderFactory,
|
||||
new DefaultObjectValidator(
|
||||
modelMetadataProvider,
|
||||
new[] { TestModelValidatorProvider.CreateDefaultProvider() }),
|
||||
NullLoggerFactory.Instance);
|
||||
|
||||
var factory = PageBinderFactory.CreateHandlerBinder(
|
||||
parameterBinder,
|
||||
|
|
@ -748,7 +755,7 @@ namespace Microsoft.AspNetCore.Mvc.RazorPages.Internal
|
|||
: base(
|
||||
TestModelMetadataProvider.CreateDefaultProvider(),
|
||||
TestModelBinderFactory.CreateDefault(),
|
||||
Mock.Of<IModelValidatorProvider>(),
|
||||
Mock.Of<IObjectModelValidator>(),
|
||||
NullLoggerFactory.Instance)
|
||||
{
|
||||
_args = args;
|
||||
|
|
|
|||
Loading…
Reference in New Issue