Remove IExcludeTypeFilter
- Removes IExcludeTypeFilter - Replaced with a property 'ValidateChildren' on ModelMetadata - Teach ValidationVisitor to respect 'ValidateChildren' for enumerable types.
This commit is contained in:
parent
774ee05508
commit
96de1dbe4b
|
|
@ -289,6 +289,11 @@ namespace Microsoft.AspNet.Mvc.ModelBinding
|
|||
/// </summary>
|
||||
public abstract string TemplateHint { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets a value that indicates whether properties or elements of the model should be validated.
|
||||
/// </summary>
|
||||
public abstract bool ValidateChildren { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets a collection of metadata items for validators.
|
||||
/// </summary>
|
||||
|
|
|
|||
|
|
@ -134,12 +134,7 @@ namespace Microsoft.Extensions.DependencyInjection
|
|||
var options = serviceProvider.GetRequiredService<IOptions<MvcOptions>>().Value;
|
||||
return new DefaultCompositeMetadataDetailsProvider(options.ModelMetadataDetailsProviders);
|
||||
}));
|
||||
services.TryAdd(ServiceDescriptor.Singleton<IObjectModelValidator>(serviceProvider =>
|
||||
{
|
||||
var options = serviceProvider.GetRequiredService<IOptions<MvcOptions>>().Value;
|
||||
var modelMetadataProvider = serviceProvider.GetRequiredService<IModelMetadataProvider>();
|
||||
return new DefaultObjectValidator(options.ValidationExcludeFilters, modelMetadataProvider);
|
||||
}));
|
||||
services.TryAddSingleton<IObjectModelValidator, DefaultObjectValidator>();
|
||||
|
||||
//
|
||||
// Random Infrastructure
|
||||
|
|
|
|||
|
|
@ -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.Threading;
|
||||
using Microsoft.AspNet.Http;
|
||||
using Microsoft.AspNet.Mvc.Core;
|
||||
using Microsoft.AspNet.Mvc.Formatters;
|
||||
|
|
@ -63,13 +64,11 @@ namespace Microsoft.AspNet.Mvc.Internal
|
|||
options.ModelValidatorProviders.Add(new DefaultModelValidatorProvider());
|
||||
|
||||
// Add types to be excluded from Validation
|
||||
options.ValidationExcludeFilters.Add(new SimpleTypesExcludeFilter());
|
||||
options.ValidationExcludeFilters.Add(typeof(Type));
|
||||
|
||||
// Any 'known' types that we bind should be marked as excluded from validation.
|
||||
options.ValidationExcludeFilters.Add(typeof(System.Threading.CancellationToken));
|
||||
options.ValidationExcludeFilters.Add(typeof(IFormFile));
|
||||
options.ValidationExcludeFilters.Add(typeof(IFormCollection));
|
||||
options.ModelMetadataDetailsProviders.Add(new ValidationExcludeFilter(typeof(Type)));
|
||||
options.ModelMetadataDetailsProviders.Add(new ValidationExcludeFilter(typeof(Uri)));
|
||||
options.ModelMetadataDetailsProviders.Add(new ValidationExcludeFilter(typeof(CancellationToken)));
|
||||
options.ModelMetadataDetailsProviders.Add(new ValidationExcludeFilter(typeof(IFormFile)));
|
||||
options.ModelMetadataDetailsProviders.Add(new ValidationExcludeFilter(typeof(IFormCollection)));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -29,6 +29,7 @@ namespace Microsoft.AspNet.Mvc.ModelBinding.Metadata
|
|||
private bool? _isReadOnly;
|
||||
private bool? _isRequired;
|
||||
private ModelPropertyCollection _properties;
|
||||
private bool? _validateChildren;
|
||||
private ReadOnlyCollection<object> _validatorMetadata;
|
||||
|
||||
/// <summary>
|
||||
|
|
@ -491,6 +492,31 @@ namespace Microsoft.AspNet.Mvc.ModelBinding.Metadata
|
|||
}
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public override bool ValidateChildren
|
||||
{
|
||||
get
|
||||
{
|
||||
if (!_validateChildren.HasValue)
|
||||
{
|
||||
if (ValidationMetadata.ValidateChildren.HasValue)
|
||||
{
|
||||
_validateChildren = ValidationMetadata.ValidateChildren.Value;
|
||||
}
|
||||
else if (IsComplexType || IsEnumerableType)
|
||||
{
|
||||
_validateChildren = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
_validateChildren = false;
|
||||
}
|
||||
}
|
||||
|
||||
return _validateChildren.Value;
|
||||
}
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public override IReadOnlyList<object> ValidatorMetadata
|
||||
{
|
||||
|
|
|
|||
|
|
@ -18,6 +18,14 @@ namespace Microsoft.AspNet.Mvc.ModelBinding.Metadata
|
|||
/// </summary>
|
||||
public bool? IsRequired { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets a value that indicates whether children of the model should be validated. If <c>null</c>
|
||||
/// then <see cref="ModelMetadata.ValidateChildren"/> will be <c>true</c> if either of
|
||||
/// <see cref="ModelMetadata.IsComplexType"/> or <see cref="ModelMetadata.IsEnumerableType"/> is <c>true</c>;
|
||||
/// <c>false</c> otherwise.
|
||||
/// </summary>
|
||||
public bool? ValidateChildren { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets a list of metadata items for validators.
|
||||
/// </summary>
|
||||
|
|
|
|||
|
|
@ -2,7 +2,6 @@
|
|||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Microsoft.AspNet.Mvc.ModelBinding.Validation
|
||||
{
|
||||
|
|
@ -11,31 +10,21 @@ namespace Microsoft.AspNet.Mvc.ModelBinding.Validation
|
|||
/// </summary>
|
||||
public class DefaultObjectValidator : IObjectModelValidator
|
||||
{
|
||||
private readonly IList<IExcludeTypeValidationFilter> _excludeFilters;
|
||||
private readonly IModelMetadataProvider _modelMetadataProvider;
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of <see cref="DefaultObjectValidator"/>.
|
||||
/// </summary>
|
||||
/// <param name="excludeFilters"><see cref="IExcludeTypeValidationFilter"/>s that determine
|
||||
/// types to exclude from validation.</param>
|
||||
/// <param name="modelMetadataProvider">The <see cref="IModelMetadataProvider"/>.</param>
|
||||
public DefaultObjectValidator(
|
||||
IList<IExcludeTypeValidationFilter> excludeFilters,
|
||||
IModelMetadataProvider modelMetadataProvider)
|
||||
{
|
||||
if (excludeFilters == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(excludeFilters));
|
||||
}
|
||||
|
||||
if (modelMetadataProvider == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(modelMetadataProvider));
|
||||
}
|
||||
|
||||
_modelMetadataProvider = modelMetadataProvider;
|
||||
_excludeFilters = excludeFilters;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
|
|
@ -59,7 +48,6 @@ namespace Microsoft.AspNet.Mvc.ModelBinding.Validation
|
|||
var visitor = new ValidationVisitor(
|
||||
actionContext,
|
||||
validatorProvider,
|
||||
_excludeFilters,
|
||||
validationState);
|
||||
|
||||
var metadata = model == null ? null : _modelMetadataProvider.GetMetadataForType(model.GetType());
|
||||
|
|
|
|||
|
|
@ -1,45 +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;
|
||||
using System.Reflection;
|
||||
|
||||
namespace Microsoft.AspNet.Mvc.ModelBinding.Validation
|
||||
{
|
||||
/// <summary>
|
||||
/// Provides an implementation of <see cref="IExcludeTypeValidationFilter"/> which can filter
|
||||
/// based on a type.
|
||||
/// </summary>
|
||||
public class DefaultTypeBasedExcludeFilter : IExcludeTypeValidationFilter
|
||||
{
|
||||
/// <summary>
|
||||
/// Creates a new instance of <see cref="DefaultTypeBasedExcludeFilter"/>.
|
||||
/// </summary>
|
||||
/// <param name="type">The type which needs to be excluded.</param>
|
||||
public DefaultTypeBasedExcludeFilter(Type type)
|
||||
{
|
||||
if (type == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(type));
|
||||
}
|
||||
|
||||
ExcludedType = type;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the type which is excluded from validation.
|
||||
/// </summary>
|
||||
public Type ExcludedType { get; }
|
||||
|
||||
/// <inheritdoc />
|
||||
public bool IsTypeExcluded(Type propertyType)
|
||||
{
|
||||
if (propertyType == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(propertyType));
|
||||
}
|
||||
|
||||
return ExcludedType.GetTypeInfo().IsAssignableFrom(propertyType.GetTypeInfo());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,60 +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;
|
||||
using System.Reflection;
|
||||
|
||||
namespace Microsoft.AspNet.Mvc.ModelBinding.Validation
|
||||
{
|
||||
/// <summary>
|
||||
/// Provides an implementation of <see cref="IExcludeTypeValidationFilter"/> which can filter
|
||||
/// based on a type full name.
|
||||
/// </summary>
|
||||
public class DefaultTypeNameBasedExcludeFilter : IExcludeTypeValidationFilter
|
||||
{
|
||||
/// <summary>
|
||||
/// Creates a new instance of <see cref="DefaultTypeNameBasedExcludeFilter"/>
|
||||
/// </summary>
|
||||
/// <param name="typeFullName">Fully qualified name of the type which needs to be excluded.</param>
|
||||
public DefaultTypeNameBasedExcludeFilter(string typeFullName)
|
||||
{
|
||||
if (typeFullName == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(typeFullName));
|
||||
}
|
||||
|
||||
ExcludedTypeName = typeFullName;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the type full name which is excluded from validation.
|
||||
/// </summary>
|
||||
public string ExcludedTypeName { get; }
|
||||
|
||||
/// <inheritdoc />
|
||||
public bool IsTypeExcluded(Type propertyType)
|
||||
{
|
||||
if (propertyType == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(propertyType));
|
||||
}
|
||||
|
||||
return CheckIfTypeNameMatches(propertyType);
|
||||
}
|
||||
|
||||
private bool CheckIfTypeNameMatches(Type type)
|
||||
{
|
||||
if (type == null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (string.Equals(type.FullName, ExcludedTypeName, StringComparison.Ordinal))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
return CheckIfTypeNameMatches(type.GetTypeInfo().BaseType);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,43 +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;
|
||||
using System.Collections.ObjectModel;
|
||||
|
||||
namespace Microsoft.AspNet.Mvc.ModelBinding.Validation
|
||||
{
|
||||
public class ExcludeTypeValidationFilterCollection : Collection<IExcludeTypeValidationFilter>
|
||||
{
|
||||
/// <summary>
|
||||
/// Adds an <see cref="IExcludeTypeValidationFilter"/> that excludes the properties of
|
||||
/// the <see cref="Type"/> specified and its derived types from validaton.
|
||||
/// </summary>
|
||||
/// <param name="type"><see cref="Type"/> which should be excluded from validation.</param>
|
||||
public void Add(Type type)
|
||||
{
|
||||
if (type == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(type));
|
||||
}
|
||||
|
||||
var typeBasedExcludeFilter = new DefaultTypeBasedExcludeFilter(type);
|
||||
Add(typeBasedExcludeFilter);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Adds an <see cref="IExcludeTypeValidationFilter"/> that excludes the properties of
|
||||
/// the <see cref="Type"/> specified and its derived types from validaton.
|
||||
/// </summary>
|
||||
/// <param name="typeFullName">Full name of the type which should be excluded from validation.</param>
|
||||
public void Add(string typeFullName)
|
||||
{
|
||||
if (typeFullName == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(typeFullName));
|
||||
}
|
||||
|
||||
var filter = new DefaultTypeNameBasedExcludeFilter(typeFullName);
|
||||
Add(filter);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,20 +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;
|
||||
|
||||
namespace Microsoft.AspNet.Mvc.ModelBinding.Validation
|
||||
{
|
||||
/// <summary>
|
||||
/// Provides an interface which is used to determine if <see cref="Type"/>s are excluded from model validation.
|
||||
/// </summary>
|
||||
public interface IExcludeTypeValidationFilter
|
||||
{
|
||||
/// <summary>
|
||||
/// Determines if the given type is excluded from validation.
|
||||
/// </summary>
|
||||
/// <param name="type">The <see cref="Type"/> for which the check is to be performed.</param>
|
||||
/// <returns>True if the type is to be excluded. False otherwise.</returns>
|
||||
bool IsTypeExcluded(Type type);
|
||||
}
|
||||
}
|
||||
|
|
@ -1,64 +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;
|
||||
using System.Collections.Generic;
|
||||
using System.Reflection;
|
||||
|
||||
namespace Microsoft.AspNet.Mvc.ModelBinding.Validation
|
||||
{
|
||||
/// <summary>
|
||||
/// Identifies the simple types that the default model binding validation will exclude.
|
||||
/// </summary>
|
||||
public class SimpleTypesExcludeFilter : IExcludeTypeValidationFilter
|
||||
{
|
||||
/// <summary>
|
||||
/// Returns true if the given type will be excluded from the default model validation.
|
||||
/// </summary>
|
||||
public bool IsTypeExcluded(Type type)
|
||||
{
|
||||
if (type == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(type));
|
||||
}
|
||||
|
||||
Type[] actualTypes;
|
||||
|
||||
if (type.GetTypeInfo().IsGenericType &&
|
||||
type.GetGenericTypeDefinition() == typeof(KeyValuePair<,>))
|
||||
{
|
||||
actualTypes = type.GenericTypeArguments;
|
||||
}
|
||||
else
|
||||
{
|
||||
actualTypes = new Type[] { type };
|
||||
}
|
||||
|
||||
foreach (var actualType in actualTypes)
|
||||
{
|
||||
var underlyingType = Nullable.GetUnderlyingType(actualType) ?? actualType;
|
||||
if (!IsSimpleType(underlyingType))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns true if the given type is the underlying types that <see cref="IsTypeExcluded"/> will exclude.
|
||||
/// </summary>
|
||||
protected virtual bool IsSimpleType(Type type)
|
||||
{
|
||||
return type.GetTypeInfo().IsPrimitive ||
|
||||
type.Equals(typeof(decimal)) ||
|
||||
type.Equals(typeof(string)) ||
|
||||
type.Equals(typeof(DateTime)) ||
|
||||
type.Equals(typeof(Guid)) ||
|
||||
type.Equals(typeof(DateTimeOffset)) ||
|
||||
type.Equals(typeof(TimeSpan)) ||
|
||||
type.Equals(typeof(Uri));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,109 @@
|
|||
// 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.Diagnostics;
|
||||
using System.Reflection;
|
||||
using Microsoft.AspNet.Mvc.ModelBinding.Metadata;
|
||||
|
||||
namespace Microsoft.AspNet.Mvc.ModelBinding.Validation
|
||||
{
|
||||
/// <summary>
|
||||
/// An <see cref="IValidationMetadataProvider"/> which configures <see cref="ModelMetadata.ValidateChildren"/> to
|
||||
/// <c>false</c> for matching types.
|
||||
/// </summary>
|
||||
public class ValidationExcludeFilter : IValidationMetadataProvider
|
||||
{
|
||||
/// <summary>
|
||||
/// Creates a new <see cref="ValidationExcludeFilter"/> for the given <paramref name="type"/>.
|
||||
/// </summary>
|
||||
/// <param name="type">
|
||||
/// The <see cref="Type"/>. This <see cref="Type"/> and all assignable values will have
|
||||
/// <see cref="ModelMetadata.ValidateChildren"/> set to <c>false</c>.
|
||||
/// </param>
|
||||
public ValidationExcludeFilter(Type type)
|
||||
{
|
||||
if (type == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(type));
|
||||
}
|
||||
|
||||
Type = type;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new <see cref="ValidationExcludeFilter"/> for the given <paramref name="fullTypeName"/>.
|
||||
/// </summary>
|
||||
/// <param name="fullTypeName">
|
||||
/// The type full name. This type and all of its subclasses will have
|
||||
/// <see cref="ModelMetadata.ValidateChildren"/> set to <c>false</c>.
|
||||
/// </param>
|
||||
public ValidationExcludeFilter(string fullTypeName)
|
||||
{
|
||||
if (fullTypeName == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(fullTypeName));
|
||||
}
|
||||
|
||||
FullTypeName = fullTypeName;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the <see cref="Type"/> for which to suppress validation of children.
|
||||
/// </summary>
|
||||
public Type Type { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the full name of a type for which to suppress validation of children.
|
||||
/// </summary>
|
||||
public string FullTypeName { get; }
|
||||
|
||||
/// <inheritdoc />
|
||||
public void GetValidationMetadata(ValidationMetadataProviderContext context)
|
||||
{
|
||||
if (context == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(context));
|
||||
}
|
||||
|
||||
if (Type != null)
|
||||
{
|
||||
if (Type.GetTypeInfo().IsAssignableFrom(context.Key.ModelType.GetTypeInfo()))
|
||||
{
|
||||
context.ValidationMetadata.ValidateChildren = false;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (FullTypeName != null)
|
||||
{
|
||||
if (IsMatchingName(context.Key.ModelType))
|
||||
{
|
||||
context.ValidationMetadata.ValidateChildren = false;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
Debug.Fail("We shouldn't get here.");
|
||||
}
|
||||
|
||||
private bool IsMatchingName(Type type)
|
||||
{
|
||||
Debug.Assert(FullTypeName != null);
|
||||
|
||||
if (type == null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (string.Equals(type.FullName, FullTypeName, StringComparison.Ordinal))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
return IsMatchingName(type.GetTypeInfo().BaseType);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -14,7 +14,6 @@ namespace Microsoft.AspNet.Mvc.ModelBinding.Validation
|
|||
public class ValidationVisitor
|
||||
{
|
||||
private readonly IModelValidatorProvider _validatorProvider;
|
||||
private readonly IList<IExcludeTypeValidationFilter> _excludeFilters;
|
||||
private readonly ActionContext _actionContext;
|
||||
private readonly ModelStateDictionary _modelState;
|
||||
private readonly ValidationStateDictionary _validationState;
|
||||
|
|
@ -33,12 +32,10 @@ namespace Microsoft.AspNet.Mvc.ModelBinding.Validation
|
|||
/// </summary>
|
||||
/// <param name="actionContext">The <see cref="ActionContext"/> associated with the current request.</param>
|
||||
/// <param name="validatorProvider">The <see cref="IModelValidatorProvider"/>.</param>
|
||||
/// <param name="excludeFilters">The list of <see cref="IExcludeTypeValidationFilter"/>.</param>
|
||||
/// <param name="validationState">The <see cref="ValidationStateDictionary"/>.</param>
|
||||
public ValidationVisitor(
|
||||
ActionContext actionContext,
|
||||
IModelValidatorProvider validatorProvider,
|
||||
IList<IExcludeTypeValidationFilter> excludeFilters,
|
||||
ValidationStateDictionary validationState)
|
||||
{
|
||||
if (actionContext == null)
|
||||
|
|
@ -51,14 +48,8 @@ namespace Microsoft.AspNet.Mvc.ModelBinding.Validation
|
|||
throw new ArgumentNullException(nameof(validatorProvider));
|
||||
}
|
||||
|
||||
if (excludeFilters == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(excludeFilters));
|
||||
}
|
||||
|
||||
_actionContext = actionContext;
|
||||
_validatorProvider = validatorProvider;
|
||||
_excludeFilters = excludeFilters;
|
||||
_validationState = validationState;
|
||||
|
||||
_modelState = actionContext.ModelState;
|
||||
|
|
@ -191,11 +182,18 @@ namespace Microsoft.AspNet.Mvc.ModelBinding.Validation
|
|||
{
|
||||
var isValid = true;
|
||||
|
||||
if (_model != null)
|
||||
if (_model != null && _metadata.ValidateChildren)
|
||||
{
|
||||
var strategy = _strategy ?? DefaultCollectionValidationStrategy.Instance;
|
||||
isValid = VisitChildren(strategy);
|
||||
}
|
||||
else if (_model != null)
|
||||
{
|
||||
// Suppress validation for the entries matching this prefix. This will temporarily set
|
||||
// the current node to 'skipped' but we're going to visit it right away, so subsequent
|
||||
// code will set it to 'valid' or 'invalid'
|
||||
SuppressValidation(_key);
|
||||
}
|
||||
|
||||
// Double-checking HasReachedMaxErrors just in case this model has no elements.
|
||||
if (isValid && !_modelState.HasReachedMaxErrors)
|
||||
|
|
@ -210,14 +208,16 @@ namespace Microsoft.AspNet.Mvc.ModelBinding.Validation
|
|||
{
|
||||
var isValid = true;
|
||||
|
||||
if (_model != null && ShouldValidateProperties(_metadata))
|
||||
if (_model != null && _metadata.ValidateChildren)
|
||||
{
|
||||
var strategy = _strategy ?? DefaultComplexObjectValidationStrategy.Instance;
|
||||
isValid = VisitChildren(strategy);
|
||||
}
|
||||
else if (_model != null)
|
||||
{
|
||||
// Suppress validation for the prefix, but we still want to validate the object.
|
||||
// Suppress validation for the entries matching this prefix. This will temporarily set
|
||||
// the current node to 'skipped' but we're going to visit it right away, so subsequent
|
||||
// code will set it to 'valid' or 'invalid'
|
||||
SuppressValidation(_key);
|
||||
}
|
||||
|
||||
|
|
@ -286,20 +286,6 @@ namespace Microsoft.AspNet.Mvc.ModelBinding.Validation
|
|||
}
|
||||
}
|
||||
|
||||
private bool ShouldValidateProperties(ModelMetadata metadata)
|
||||
{
|
||||
var count = _excludeFilters.Count;
|
||||
for (var i = 0; i < _excludeFilters.Count; i++)
|
||||
{
|
||||
if (_excludeFilters[i].IsTypeExcluded(metadata.UnderlyingOrModelType))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private ValidationStateEntry GetValidationEntry(object model)
|
||||
{
|
||||
if (model == null || _validationState == null)
|
||||
|
|
|
|||
|
|
@ -31,7 +31,6 @@ namespace Microsoft.AspNet.Mvc
|
|||
ModelBindingMessageProvider = new ModelBindingMessageProvider();
|
||||
ModelMetadataDetailsProviders = new List<IMetadataDetailsProvider>();
|
||||
ModelValidatorProviders = new List<IModelValidatorProvider>();
|
||||
ValidationExcludeFilters = new ExcludeTypeValidationFilterCollection();
|
||||
ValueProviderFactories = new List<IValueProviderFactory>();
|
||||
}
|
||||
|
||||
|
|
@ -125,11 +124,6 @@ namespace Microsoft.AspNet.Mvc
|
|||
/// </summary>
|
||||
public bool RespectBrowserAcceptHeader { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets a collection of <see cref="IExcludeTypeValidationFilter"/>s that are used by this application.
|
||||
/// </summary>
|
||||
public ExcludeTypeValidationFilterCollection ValidationExcludeFilters { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets a list of <see cref="IValueProviderFactory"/> used by this application.
|
||||
/// </summary>
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
// 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 Microsoft.AspNet.Mvc.ModelBinding.Validation;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Microsoft.Extensions.OptionsModel;
|
||||
using Microsoft.Net.Http.Headers;
|
||||
|
|
@ -30,7 +31,7 @@ namespace Microsoft.AspNet.Mvc.Formatters.Json.Internal
|
|||
|
||||
options.FormatterMappings.SetMediaTypeMappingForFormat("json", MediaTypeHeaderValue.Parse("application/json"));
|
||||
|
||||
options.ValidationExcludeFilters.Add(typeof(JToken));
|
||||
options.ModelMetadataDetailsProviders.Add(new ValidationExcludeFilter(typeof(JToken)));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@
|
|||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using Microsoft.AspNet.Mvc.ModelBinding.Metadata;
|
||||
using Microsoft.AspNet.Mvc.ModelBinding.Validation;
|
||||
using Microsoft.Extensions.OptionsModel;
|
||||
|
||||
namespace Microsoft.AspNet.Mvc.Formatters.Xml.Internal
|
||||
|
|
@ -31,8 +32,8 @@ namespace Microsoft.AspNet.Mvc.Formatters.Xml.Internal
|
|||
options.OutputFormatters.Add(new XmlDataContractSerializerOutputFormatter());
|
||||
options.InputFormatters.Add(new XmlDataContractSerializerInputFormatter());
|
||||
|
||||
options.ValidationExcludeFilters.Add(typeFullName: "System.Xml.Linq.XObject");
|
||||
options.ValidationExcludeFilters.Add(typeFullName: "System.Xml.XmlNode");
|
||||
options.ModelMetadataDetailsProviders.Add(new ValidationExcludeFilter("System.Xml.Linq.XObject"));
|
||||
options.ModelMetadataDetailsProviders.Add(new ValidationExcludeFilter("System.Xml.XmlNode"));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@
|
|||
|
||||
using System.Net.Http;
|
||||
using System.Net.Http.Formatting;
|
||||
using Microsoft.AspNet.Mvc.ModelBinding.Validation;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Microsoft.Extensions.OptionsModel;
|
||||
|
||||
|
|
@ -32,8 +33,8 @@ namespace Microsoft.AspNet.Mvc.WebApiCompatShim
|
|||
// Add a formatter to write out an HttpResponseMessage to the response
|
||||
options.OutputFormatters.Insert(0, new HttpResponseMessageOutputFormatter());
|
||||
|
||||
options.ValidationExcludeFilters.Add(typeof(HttpRequestMessage));
|
||||
options.ValidationExcludeFilters.Add(typeof(HttpResponseMessage));
|
||||
options.ModelMetadataDetailsProviders.Add(new ValidationExcludeFilter(typeof(HttpRequestMessage)));
|
||||
options.ModelMetadataDetailsProviders.Add(new ValidationExcludeFilter(typeof(HttpResponseMessage)));
|
||||
}
|
||||
|
||||
public void Configure(WebApiCompatShimOptions options)
|
||||
|
|
|
|||
|
|
@ -568,6 +568,14 @@ namespace Microsoft.AspNet.Mvc.ModelBinding
|
|||
}
|
||||
}
|
||||
|
||||
public override bool ValidateChildren
|
||||
{
|
||||
get
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
}
|
||||
|
||||
public override IReadOnlyList<object> ValidatorMetadata
|
||||
{
|
||||
get
|
||||
|
|
|
|||
|
|
@ -2112,7 +2112,7 @@ namespace Microsoft.AspNet.Mvc.Controllers
|
|||
new IInputFormatter[0],
|
||||
new DefaultControllerActionArgumentBinder(
|
||||
metadataProvider,
|
||||
new DefaultObjectValidator(new IExcludeTypeValidationFilter[0], metadataProvider)),
|
||||
new DefaultObjectValidator(metadataProvider)),
|
||||
new IModelBinder[] { binder.Object },
|
||||
new IModelValidatorProvider[0],
|
||||
new IValueProviderFactory[0],
|
||||
|
|
|
|||
|
|
@ -251,7 +251,7 @@ namespace Microsoft.AspNet.Mvc.Controllers
|
|||
services.Setup(s => s.GetService(typeof(IModelMetadataProvider)))
|
||||
.Returns(metadataProvider);
|
||||
services.Setup(s => s.GetService(typeof(IObjectModelValidator)))
|
||||
.Returns(new DefaultObjectValidator(new IExcludeTypeValidationFilter[0], metadataProvider));
|
||||
.Returns(new DefaultObjectValidator(metadataProvider));
|
||||
return services.Object;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@ using System.Collections;
|
|||
using System.Collections.Generic;
|
||||
using System.Collections.ObjectModel;
|
||||
using System.Linq;
|
||||
using System.Xml;
|
||||
using Moq;
|
||||
using Xunit;
|
||||
|
||||
|
|
@ -605,6 +606,103 @@ namespace Microsoft.AspNet.Mvc.ModelBinding.Metadata
|
|||
Assert.False(isReadOnly);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData(typeof(int))] // Primitive
|
||||
[InlineData(typeof(int?))] // Nullable
|
||||
[InlineData(typeof(Guid))] // TypeConverter
|
||||
[InlineData(typeof(Guid?))] // Nullable + TypeConverter
|
||||
[InlineData(typeof(string))]
|
||||
public void ValidateChildren_SimpleTypes(Type modelType)
|
||||
{
|
||||
// Arrange
|
||||
var detailsProvider = new EmptyCompositeMetadataDetailsProvider();
|
||||
var provider = new DefaultModelMetadataProvider(detailsProvider);
|
||||
|
||||
var key = ModelMetadataIdentity.ForType(modelType);
|
||||
var cache = new DefaultMetadataDetails(key, new ModelAttributes(new object[0]));
|
||||
|
||||
var metadata = new DefaultModelMetadata(provider, detailsProvider, cache);
|
||||
|
||||
// Act
|
||||
var validateChildren = metadata.ValidateChildren;
|
||||
|
||||
// Assert
|
||||
Assert.False(validateChildren);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData(typeof(int[]))]
|
||||
[InlineData(typeof(List<decimal>))]
|
||||
[InlineData(typeof(IEnumerable))]
|
||||
[InlineData(typeof(Dictionary<string, string>))]
|
||||
[InlineData(typeof(KeyValuePair<string, string>))]
|
||||
[InlineData(typeof(KeyValuePair<string, string>?))]
|
||||
[InlineData(typeof(TypeWithProperties))]
|
||||
[InlineData(typeof(List<TypeWithProperties>))]
|
||||
public void ValidateChildren_ComplexAndEnumerableTypes(Type modelType)
|
||||
{
|
||||
// Arrange
|
||||
var detailsProvider = new EmptyCompositeMetadataDetailsProvider();
|
||||
var provider = new DefaultModelMetadataProvider(detailsProvider);
|
||||
|
||||
var key = ModelMetadataIdentity.ForType(typeof(TypeWithProperties));
|
||||
var cache = new DefaultMetadataDetails(key, new ModelAttributes(new object[0]));
|
||||
|
||||
var metadata = new DefaultModelMetadata(provider, detailsProvider, cache);
|
||||
|
||||
// Act
|
||||
var validateChildren = metadata.ValidateChildren;
|
||||
|
||||
// Assert
|
||||
Assert.True(validateChildren);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ValidateChildren_OverrideTrue()
|
||||
{
|
||||
// Arrange
|
||||
var detailsProvider = new EmptyCompositeMetadataDetailsProvider();
|
||||
var provider = new DefaultModelMetadataProvider(detailsProvider);
|
||||
|
||||
var key = ModelMetadataIdentity.ForType(typeof(int));
|
||||
var cache = new DefaultMetadataDetails(key, new ModelAttributes(new object[0]));
|
||||
cache.ValidationMetadata = new ValidationMetadata()
|
||||
{
|
||||
ValidateChildren = true,
|
||||
};
|
||||
|
||||
var metadata = new DefaultModelMetadata(provider, detailsProvider, cache);
|
||||
|
||||
// Act
|
||||
var validateChildren = metadata.ValidateChildren;
|
||||
|
||||
// Assert
|
||||
Assert.True(validateChildren);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ValidateChildren_OverrideFalse()
|
||||
{
|
||||
// Arrange
|
||||
var detailsProvider = new EmptyCompositeMetadataDetailsProvider();
|
||||
var provider = new DefaultModelMetadataProvider(detailsProvider);
|
||||
|
||||
var key = ModelMetadataIdentity.ForType(typeof(XmlDocument));
|
||||
var cache = new DefaultMetadataDetails(key, new ModelAttributes(new object[0]));
|
||||
cache.ValidationMetadata = new ValidationMetadata()
|
||||
{
|
||||
ValidateChildren = false,
|
||||
};
|
||||
|
||||
var metadata = new DefaultModelMetadata(provider, detailsProvider, cache);
|
||||
|
||||
// Act
|
||||
var validateChildren = metadata.ValidateChildren;
|
||||
|
||||
// Assert
|
||||
Assert.False(validateChildren);
|
||||
}
|
||||
|
||||
private void ActionMethod(string input)
|
||||
{
|
||||
}
|
||||
|
|
|
|||
|
|
@ -95,7 +95,7 @@ namespace Microsoft.AspNet.Mvc.ModelBinding
|
|||
GetCompositeBinder(binders),
|
||||
valueProvider,
|
||||
new List<IInputFormatter>(),
|
||||
new DefaultObjectValidator(new IExcludeTypeValidationFilter[0], modelMetadataProvider),
|
||||
new DefaultObjectValidator(modelMetadataProvider),
|
||||
validator);
|
||||
|
||||
// Assert
|
||||
|
|
@ -136,7 +136,7 @@ namespace Microsoft.AspNet.Mvc.ModelBinding
|
|||
GetCompositeBinder(binders),
|
||||
valueProvider,
|
||||
new List<IInputFormatter>(),
|
||||
new DefaultObjectValidator(new IExcludeTypeValidationFilter[0], metadataProvider),
|
||||
new DefaultObjectValidator(metadataProvider),
|
||||
validator);
|
||||
|
||||
// Assert
|
||||
|
|
@ -221,7 +221,7 @@ namespace Microsoft.AspNet.Mvc.ModelBinding
|
|||
GetCompositeBinder(binders),
|
||||
valueProvider,
|
||||
new List<IInputFormatter>(),
|
||||
new DefaultObjectValidator(new IExcludeTypeValidationFilter[0], metadataProvider),
|
||||
new DefaultObjectValidator(metadataProvider),
|
||||
validator,
|
||||
includePredicate);
|
||||
|
||||
|
|
@ -305,7 +305,7 @@ namespace Microsoft.AspNet.Mvc.ModelBinding
|
|||
GetCompositeBinder(binders),
|
||||
valueProvider,
|
||||
new List<IInputFormatter>(),
|
||||
new DefaultObjectValidator(new IExcludeTypeValidationFilter[0], metadataProvider),
|
||||
new DefaultObjectValidator(metadataProvider),
|
||||
validator,
|
||||
m => m.IncludedProperty,
|
||||
m => m.MyProperty);
|
||||
|
|
@ -357,7 +357,7 @@ namespace Microsoft.AspNet.Mvc.ModelBinding
|
|||
GetCompositeBinder(binders),
|
||||
valueProvider,
|
||||
new List<IInputFormatter>(),
|
||||
new DefaultObjectValidator(new IExcludeTypeValidationFilter[0], metadataProvider),
|
||||
new DefaultObjectValidator(metadataProvider),
|
||||
validator);
|
||||
|
||||
// Assert
|
||||
|
|
@ -568,9 +568,7 @@ namespace Microsoft.AspNet.Mvc.ModelBinding
|
|||
GetCompositeBinder(binders),
|
||||
valueProvider,
|
||||
new List<IInputFormatter>(),
|
||||
new DefaultObjectValidator(
|
||||
new IExcludeTypeValidationFilter[0],
|
||||
metadataProvider),
|
||||
new DefaultObjectValidator(metadataProvider),
|
||||
validator,
|
||||
includePredicate);
|
||||
|
||||
|
|
@ -645,9 +643,7 @@ namespace Microsoft.AspNet.Mvc.ModelBinding
|
|||
GetCompositeBinder(binders),
|
||||
valueProvider,
|
||||
new List<IInputFormatter>(),
|
||||
new DefaultObjectValidator(
|
||||
new IExcludeTypeValidationFilter[0],
|
||||
metadataProvider),
|
||||
new DefaultObjectValidator(metadataProvider),
|
||||
validator);
|
||||
|
||||
// Assert
|
||||
|
|
@ -679,9 +675,7 @@ namespace Microsoft.AspNet.Mvc.ModelBinding
|
|||
GetCompositeBinder(binder.Object),
|
||||
Mock.Of<IValueProvider>(),
|
||||
new List<IInputFormatter>(),
|
||||
new DefaultObjectValidator(
|
||||
new IExcludeTypeValidationFilter[0],
|
||||
metadataProvider),
|
||||
new DefaultObjectValidator(metadataProvider),
|
||||
Mock.Of<IModelValidatorProvider>(),
|
||||
includePredicate));
|
||||
|
||||
|
|
|
|||
|
|
@ -8,6 +8,7 @@ using System.Linq;
|
|||
#if DNXCORE50
|
||||
using System.Reflection;
|
||||
#endif
|
||||
using Microsoft.AspNet.Mvc.ModelBinding.Metadata;
|
||||
using Microsoft.AspNet.Testing;
|
||||
using Moq;
|
||||
using Xunit;
|
||||
|
|
@ -655,13 +656,40 @@ namespace Microsoft.AspNet.Mvc.ModelBinding.Validation
|
|||
Assert.Equal(ValidationAttributeUtil.GetRequiredErrorMessage("Profession"), error.ErrorMessage);
|
||||
}
|
||||
|
||||
public static TheoryData<object, Type> ValidCollectionData
|
||||
{
|
||||
get
|
||||
{
|
||||
return new TheoryData<object, Type>()
|
||||
{
|
||||
{ new int[] { 1, 2, 3 }, typeof(int[]) },
|
||||
{ new string[] { "Foo", "Bar", "Baz" }, typeof(string[]) },
|
||||
{ new List<string> { "Foo", "Bar", "Baz" }, typeof(IList<string>)},
|
||||
{ new HashSet<string> { "Foo", "Bar", "Baz" }, typeof(string[]) },
|
||||
{
|
||||
new List<DateTime>
|
||||
{
|
||||
DateTime.Parse("1/1/14"),
|
||||
DateTime.Parse("2/1/14"),
|
||||
DateTime.Parse("3/1/14"),
|
||||
},
|
||||
typeof(ICollection<DateTime>)
|
||||
},
|
||||
{
|
||||
new HashSet<Uri>
|
||||
{
|
||||
new Uri("http://example.com/1"),
|
||||
new Uri("http://example.com/2"),
|
||||
new Uri("http://example.com/3"),
|
||||
},
|
||||
typeof(HashSet<Uri>)
|
||||
},
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData(new[] { "Foo", "Bar", "Baz" }, typeof(string[]))]
|
||||
[InlineData(new[] { 1, 2, 3 }, typeof(int[]))]
|
||||
[InlineData(new[] { "Foo", "Bar", "Baz" }, typeof(IList<string>))]
|
||||
[InlineData(new[] { "Foo", "Bar", "Baz" }, typeof(HashSet<string>))]
|
||||
[InlineData(new[] { "1/1/14", "2/2/14", "3/3/14" }, typeof(ICollection<DateTime>))]
|
||||
[InlineData(new[] { "Foo", "Bar", "Baz" }, typeof(HashSet<Uri>))]
|
||||
[MemberData(nameof(ValidCollectionData))]
|
||||
public void Validate_IndexedCollectionTypes_Valid(object model, Type type)
|
||||
{
|
||||
// Arrange
|
||||
|
|
@ -670,7 +698,7 @@ namespace Microsoft.AspNet.Mvc.ModelBinding.Validation
|
|||
var modelState = actionContext.ModelState;
|
||||
var validationState = new ValidationStateDictionary();
|
||||
|
||||
var validator = CreateValidator(new SimpleTypesExcludeFilter());
|
||||
var validator = CreateValidator();
|
||||
|
||||
modelState.Add("items[0]", new ModelStateEntry());
|
||||
modelState.Add("items[1]", new ModelStateEntry());
|
||||
|
|
@ -712,7 +740,7 @@ namespace Microsoft.AspNet.Mvc.ModelBinding.Validation
|
|||
var modelState = actionContext.ModelState;
|
||||
var validationState = new ValidationStateDictionary();
|
||||
|
||||
var validator = CreateValidator(new SimpleTypesExcludeFilter());
|
||||
var validator = CreateValidator();
|
||||
|
||||
var model = new Dictionary<string, string>()
|
||||
{
|
||||
|
|
@ -734,19 +762,19 @@ namespace Microsoft.AspNet.Mvc.ModelBinding.Validation
|
|||
AssertKeysEqual(modelState, "items[0].Key", "items[0].Value", "items[1].Key", "items[1].Value");
|
||||
|
||||
var entry = modelState["items[0].Key"];
|
||||
Assert.Equal(ModelValidationState.Skipped, entry.ValidationState);
|
||||
Assert.Equal(ModelValidationState.Valid, entry.ValidationState);
|
||||
Assert.Empty(entry.Errors);
|
||||
|
||||
entry = modelState["items[0].Value"];
|
||||
Assert.Equal(ModelValidationState.Skipped, entry.ValidationState);
|
||||
Assert.Equal(ModelValidationState.Valid, entry.ValidationState);
|
||||
Assert.Empty(entry.Errors);
|
||||
|
||||
entry = modelState["items[1].Key"];
|
||||
Assert.Equal(ModelValidationState.Skipped, entry.ValidationState);
|
||||
Assert.Equal(ModelValidationState.Valid, entry.ValidationState);
|
||||
Assert.Empty(entry.Errors);
|
||||
|
||||
entry = modelState["items[1].Value"];
|
||||
Assert.Equal(ModelValidationState.Skipped, entry.ValidationState);
|
||||
Assert.Equal(ModelValidationState.Valid, entry.ValidationState);
|
||||
Assert.Empty(entry.Errors);
|
||||
}
|
||||
|
||||
|
|
@ -857,7 +885,7 @@ namespace Microsoft.AspNet.Mvc.ModelBinding.Validation
|
|||
}
|
||||
|
||||
[Fact]
|
||||
public void Validate_ForExcludedType_PropertiesMarkedAsSkipped()
|
||||
public void Validate_ForExcludedComplexType_PropertiesMarkedAsSkipped()
|
||||
{
|
||||
// Arrange
|
||||
var validatorProvider = CreateValidatorProvider();
|
||||
|
|
@ -890,6 +918,37 @@ namespace Microsoft.AspNet.Mvc.ModelBinding.Validation
|
|||
Assert.Empty(entry.Errors);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Validate_ForExcludedCollectionType_PropertiesMarkedAsSkipped()
|
||||
{
|
||||
// Arrange
|
||||
var validatorProvider = CreateValidatorProvider();
|
||||
var actionContext = new ActionContext();
|
||||
var modelState = actionContext.ModelState;
|
||||
var validationState = new ValidationStateDictionary();
|
||||
|
||||
var validator = CreateValidator(typeof(List<string>));
|
||||
|
||||
var model = new List<string>()
|
||||
{
|
||||
"15",
|
||||
};
|
||||
|
||||
modelState.SetModelValue("userIds[0]", "15", "15");
|
||||
validationState.Add(model, new ValidationStateEntry() { Key = "userIds", });
|
||||
|
||||
// Act
|
||||
validator.Validate(actionContext, validatorProvider, validationState, "userIds", model);
|
||||
|
||||
// Assert
|
||||
Assert.Equal(ModelValidationState.Valid, modelState.ValidationState);
|
||||
AssertKeysEqual(modelState, "userIds[0]");
|
||||
|
||||
var entry = modelState["userIds[0]"];
|
||||
Assert.Equal(ModelValidationState.Skipped, entry.ValidationState);
|
||||
Assert.Empty(entry.Errors);
|
||||
}
|
||||
|
||||
private static IModelValidatorProvider CreateValidatorProvider()
|
||||
{
|
||||
return TestModelValidatorProvider.CreateDefaultProvider();
|
||||
|
|
@ -897,23 +956,20 @@ namespace Microsoft.AspNet.Mvc.ModelBinding.Validation
|
|||
|
||||
private static DefaultObjectValidator CreateValidator(Type excludedType)
|
||||
{
|
||||
var excludeFilters = new List<IExcludeTypeValidationFilter>();
|
||||
var excludeFilters = new List<ValidationExcludeFilter>();
|
||||
if (excludedType != null)
|
||||
{
|
||||
var excludeFilter = new Mock<IExcludeTypeValidationFilter>();
|
||||
excludeFilter
|
||||
.Setup(o => o.IsTypeExcluded(It.IsAny<Type>()))
|
||||
.Returns<Type>(t => t.IsAssignableFrom(excludedType));
|
||||
|
||||
excludeFilters.Add(excludeFilter.Object);
|
||||
excludeFilters.Add(new ValidationExcludeFilter(excludedType));
|
||||
}
|
||||
|
||||
return new DefaultObjectValidator(excludeFilters, TestModelMetadataProvider.CreateDefaultProvider());
|
||||
var provider = TestModelMetadataProvider.CreateDefaultProvider(excludeFilters.ToArray());
|
||||
return new DefaultObjectValidator(provider);
|
||||
}
|
||||
|
||||
private static DefaultObjectValidator CreateValidator(params IExcludeTypeValidationFilter[] excludeFilters)
|
||||
private static DefaultObjectValidator CreateValidator(params IMetadataDetailsProvider[] providers)
|
||||
{
|
||||
return new DefaultObjectValidator(excludeFilters, TestModelMetadataProvider.CreateDefaultProvider());
|
||||
var provider = TestModelMetadataProvider.CreateDefaultProvider(providers);
|
||||
return new DefaultObjectValidator(provider);
|
||||
}
|
||||
|
||||
private static void AssertKeysEqual(ModelStateDictionary modelState, params string[] keys)
|
||||
|
|
|
|||
|
|
@ -1,45 +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 Microsoft.AspNet.Mvc.ModelBinding.Validation;
|
||||
using Xunit;
|
||||
|
||||
namespace Microsoft.AspNet.Mvc.ModelBinding
|
||||
{
|
||||
public class ExcludeTypeValidationFilterCollectionTest
|
||||
{
|
||||
[Fact]
|
||||
public void AddFilter_ByType()
|
||||
{
|
||||
// Arrange
|
||||
var type = typeof(BaseType);
|
||||
var collection = new ExcludeTypeValidationFilterCollection();
|
||||
|
||||
// Act
|
||||
collection.Add(type);
|
||||
|
||||
// Assert
|
||||
var filter = Assert.IsType<DefaultTypeBasedExcludeFilter>(Assert.Single(collection));
|
||||
Assert.Equal(type, filter.ExcludedType);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void AddFilter_ByTypeName()
|
||||
{
|
||||
// Arrange
|
||||
var type = typeof(BaseType);
|
||||
var collection = new ExcludeTypeValidationFilterCollection();
|
||||
|
||||
// Act
|
||||
collection.Add(type.FullName);
|
||||
|
||||
// Assert
|
||||
var filter = Assert.IsType<DefaultTypeNameBasedExcludeFilter>(Assert.Single(collection));
|
||||
Assert.Equal(type.FullName, filter.ExcludedTypeName);
|
||||
}
|
||||
|
||||
private class BaseType
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,89 +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;
|
||||
using System.Collections.Generic;
|
||||
using Xunit;
|
||||
|
||||
namespace Microsoft.AspNet.Mvc.ModelBinding.Validation
|
||||
{
|
||||
public class SimpleTypeExcludeFilterTest
|
||||
{
|
||||
[Theory]
|
||||
[MemberData(nameof(ExcludedTypes))]
|
||||
public void SimpleTypeExcludeFilter_ExcludedTypes(Type type)
|
||||
{
|
||||
// Arrange
|
||||
var filter = new SimpleTypesExcludeFilter();
|
||||
|
||||
// Act & Assert
|
||||
Assert.True(filter.IsTypeExcluded(type));
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[MemberData(nameof(IncludedTypes))]
|
||||
public void SimpleTypeExcludeFilter_IncludedTypes(Type type)
|
||||
{
|
||||
// Arrange
|
||||
var filter = new SimpleTypesExcludeFilter();
|
||||
|
||||
// Act & Assert
|
||||
Assert.False(filter.IsTypeExcluded(type));
|
||||
}
|
||||
|
||||
private class TestType
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public static TheoryData<Type> ExcludedTypes
|
||||
{
|
||||
get
|
||||
{
|
||||
return new TheoryData<Type>()
|
||||
{
|
||||
// Simple types
|
||||
typeof(int),
|
||||
typeof(DateTime),
|
||||
|
||||
// Nullable types
|
||||
typeof(int?),
|
||||
|
||||
// KeyValue types
|
||||
typeof(KeyValuePair<string, string>)
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
public static TheoryData<Type> IncludedTypes
|
||||
{
|
||||
get
|
||||
{
|
||||
return new TheoryData<Type>()
|
||||
{
|
||||
// Enumerable types
|
||||
typeof(int[]),
|
||||
typeof(List<decimal>),
|
||||
typeof(SortedSet<int>),
|
||||
typeof(ICollection<string>),
|
||||
typeof(int?[]),
|
||||
typeof(SortedSet<int?>),
|
||||
typeof(HashSet<Uri>),
|
||||
typeof(HashSet<string>),
|
||||
typeof(IList<DateTime>),
|
||||
typeof(Dictionary<int, string>),
|
||||
typeof(IReadOnlyDictionary<int?, char>),
|
||||
|
||||
// Complex types
|
||||
typeof(TestType),
|
||||
typeof(TestType[]),
|
||||
typeof(SortedSet<TestType>),
|
||||
typeof(Dictionary<int, TestType>),
|
||||
typeof(Dictionary<TestType, int>),
|
||||
typeof(Dictionary<TestType, TestType>),
|
||||
typeof(KeyValuePair<string, TestType>)
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -129,14 +129,12 @@ namespace Microsoft.AspNet.Mvc.IntegrationTests
|
|||
var entry = Assert.Single(modelState, kvp => kvp.Key == "parameter[low].Key").Value;
|
||||
Assert.Equal("key0", entry.AttemptedValue);
|
||||
Assert.Equal("key0", entry.RawValue);
|
||||
|
||||
// Key and Value are skipped if they have simple types.
|
||||
Assert.Equal(ModelValidationState.Skipped, entry.ValidationState);
|
||||
Assert.Equal(ModelValidationState.Valid, entry.ValidationState);
|
||||
|
||||
entry = Assert.Single(modelState, kvp => kvp.Key == "parameter[low].Value").Value;
|
||||
Assert.Equal("10", entry.AttemptedValue);
|
||||
Assert.Equal("10", entry.RawValue);
|
||||
Assert.Equal(ModelValidationState.Skipped, entry.ValidationState);
|
||||
Assert.Equal(ModelValidationState.Valid, entry.ValidationState);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
|
|
|
|||
|
|
@ -104,9 +104,7 @@ namespace Microsoft.AspNet.Mvc.IntegrationTests
|
|||
binding.ModelBindingMessageProvider.MissingKeyOrValueAccessor = () => $"Hurts when nothing is provided.";
|
||||
}));
|
||||
|
||||
var argumentBinder = new DefaultControllerActionArgumentBinder(
|
||||
metadataProvider,
|
||||
ModelBindingTestHelper.GetObjectValidator());
|
||||
var argumentBinder = ModelBindingTestHelper.GetArgumentBinder(metadataProvider);
|
||||
var parameter = new ParameterDescriptor
|
||||
{
|
||||
Name = "parameter",
|
||||
|
|
@ -188,9 +186,8 @@ namespace Microsoft.AspNet.Mvc.IntegrationTests
|
|||
// A real details provider could customize message based on BindingMetadataProviderContext.
|
||||
binding.ModelBindingMessageProvider.MissingKeyOrValueAccessor = () => $"Hurts when nothing is provided.";
|
||||
}));
|
||||
var argumentBinder = new DefaultControllerActionArgumentBinder(
|
||||
metadataProvider,
|
||||
ModelBindingTestHelper.GetObjectValidator());
|
||||
|
||||
var argumentBinder = ModelBindingTestHelper.GetArgumentBinder(metadataProvider);
|
||||
|
||||
var parameter = new ParameterDescriptor
|
||||
{
|
||||
|
|
|
|||
|
|
@ -42,20 +42,28 @@ namespace Microsoft.AspNet.Mvc.IntegrationTests
|
|||
|
||||
public static DefaultControllerActionArgumentBinder GetArgumentBinder(MvcOptions options = null)
|
||||
{
|
||||
var metadataProvider = TestModelMetadataProvider.CreateDefaultProvider();
|
||||
return new DefaultControllerActionArgumentBinder(
|
||||
metadataProvider,
|
||||
GetObjectValidator(options));
|
||||
if (options == null)
|
||||
{
|
||||
var metadataProvider = TestModelMetadataProvider.CreateDefaultProvider();
|
||||
return GetArgumentBinder(metadataProvider);
|
||||
}
|
||||
else
|
||||
{
|
||||
var metadataProvider = TestModelMetadataProvider.CreateProvider(options.ModelMetadataDetailsProviders);
|
||||
return GetArgumentBinder(metadataProvider);
|
||||
}
|
||||
}
|
||||
|
||||
public static IObjectModelValidator GetObjectValidator(MvcOptions options = null)
|
||||
public static DefaultControllerActionArgumentBinder GetArgumentBinder(IModelMetadataProvider metadataProvider)
|
||||
{
|
||||
options = options ?? new TestMvcOptions().Value;
|
||||
options.MaxModelValidationErrors = 5;
|
||||
var metadataProvider = TestModelMetadataProvider.CreateDefaultProvider();
|
||||
return new DefaultObjectValidator(
|
||||
options.ValidationExcludeFilters,
|
||||
metadataProvider);
|
||||
return new DefaultControllerActionArgumentBinder(
|
||||
metadataProvider,
|
||||
GetObjectValidator(metadataProvider));
|
||||
}
|
||||
|
||||
public static IObjectModelValidator GetObjectValidator(IModelMetadataProvider metadataProvider)
|
||||
{
|
||||
return new DefaultObjectValidator(metadataProvider);
|
||||
}
|
||||
|
||||
private static HttpContext GetHttpContext(
|
||||
|
|
|
|||
|
|
@ -1424,9 +1424,8 @@ namespace Microsoft.AspNet.Mvc.IntegrationTests
|
|||
binding.ModelBindingMessageProvider.MissingBindRequiredValueAccessor =
|
||||
name => $"Hurts when '{ name }' is not provided.";
|
||||
}));
|
||||
var argumentBinder = new DefaultControllerActionArgumentBinder(
|
||||
metadataProvider,
|
||||
ModelBindingTestHelper.GetObjectValidator());
|
||||
|
||||
var argumentBinder = ModelBindingTestHelper.GetArgumentBinder(metadataProvider);
|
||||
var parameter = new ParameterDescriptor()
|
||||
{
|
||||
Name = "parameter",
|
||||
|
|
|
|||
|
|
@ -312,9 +312,8 @@ namespace Microsoft.AspNet.Mvc.IntegrationTests
|
|||
binding.ModelBindingMessageProvider.ValueMustNotBeNullAccessor =
|
||||
value => $"Hurts when '{ value }' is provided.";
|
||||
}));
|
||||
var argumentBinder = new DefaultControllerActionArgumentBinder(
|
||||
metadataProvider,
|
||||
ModelBindingTestHelper.GetObjectValidator());
|
||||
var argumentBinder = ModelBindingTestHelper.GetArgumentBinder(metadataProvider);
|
||||
|
||||
var parameter = new ParameterDescriptor
|
||||
{
|
||||
Name = "Parameter1",
|
||||
|
|
|
|||
|
|
@ -1109,7 +1109,7 @@ namespace Microsoft.AspNet.Mvc.IntegrationTests
|
|||
operationContext.ModelBinder,
|
||||
operationContext.ValueProvider,
|
||||
operationContext.InputFormatters,
|
||||
ModelBindingTestHelper.GetObjectValidator(),
|
||||
ModelBindingTestHelper.GetObjectValidator(operationContext.MetadataProvider),
|
||||
operationContext.ValidatorProvider);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -9,6 +9,8 @@ using System.Threading.Tasks;
|
|||
using Microsoft.AspNet.Http;
|
||||
using Microsoft.AspNet.Mvc.Abstractions;
|
||||
using Microsoft.AspNet.Mvc.ModelBinding;
|
||||
using Microsoft.AspNet.Mvc.ModelBinding.Validation;
|
||||
using Newtonsoft.Json.Linq;
|
||||
using Xunit;
|
||||
|
||||
namespace Microsoft.AspNet.Mvc.IntegrationTests
|
||||
|
|
@ -1129,7 +1131,7 @@ namespace Microsoft.AspNet.Mvc.IntegrationTests
|
|||
},
|
||||
options =>
|
||||
{
|
||||
options.ValidationExcludeFilters.Add(typeof(Address));
|
||||
options.ModelMetadataDetailsProviders.Add(new ValidationExcludeFilter(typeof(Address)));
|
||||
testOptions = options;
|
||||
});
|
||||
|
||||
|
|
@ -1167,6 +1169,55 @@ namespace Microsoft.AspNet.Mvc.IntegrationTests
|
|||
Assert.Equal(ModelValidationState.Valid, entry.ValidationState);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task FromBody_JToken_ExcludedFromValidation()
|
||||
{
|
||||
// Arrange
|
||||
var argumentBinder = ModelBindingTestHelper.GetArgumentBinder(new TestMvcOptions().Value);
|
||||
var parameter = new ParameterDescriptor
|
||||
{
|
||||
Name = "Parameter1",
|
||||
BindingInfo = new BindingInfo
|
||||
{
|
||||
BinderModelName = "CustomParameter",
|
||||
BindingSource = BindingSource.Body
|
||||
},
|
||||
ParameterType = typeof(JToken)
|
||||
};
|
||||
|
||||
var operationContext = ModelBindingTestHelper.GetOperationBindingContext(
|
||||
request =>
|
||||
{
|
||||
request.Body = new MemoryStream(Encoding.UTF8.GetBytes("{ message: \"Hello\" }"));
|
||||
request.ContentType = "application/json";
|
||||
});
|
||||
|
||||
var httpContext = operationContext.HttpContext;
|
||||
var modelState = operationContext.ActionContext.ModelState;
|
||||
|
||||
// We need to add another model state entry which should get marked as skipped so
|
||||
// we can prove that the JObject was skipped.
|
||||
modelState.SetModelValue("message", "Hello", "Hello");
|
||||
|
||||
// Act
|
||||
var modelBindingResult = await argumentBinder.BindModelAsync(parameter, operationContext);
|
||||
|
||||
// Assert
|
||||
Assert.True(modelBindingResult.IsModelSet);
|
||||
Assert.NotNull(modelBindingResult.Model);
|
||||
var message = Assert.IsType<JObject>(modelBindingResult.Model).GetValue("message").Value<string>();
|
||||
Assert.Equal("Hello", message);
|
||||
|
||||
Assert.True(modelState.IsValid);
|
||||
Assert.Equal(2, modelState.Count);
|
||||
|
||||
var entry = Assert.Single(modelState, kvp => kvp.Key == string.Empty);
|
||||
Assert.Equal(ModelValidationState.Valid, entry.Value.ValidationState);
|
||||
|
||||
entry = Assert.Single(modelState, kvp => kvp.Key == "message");
|
||||
Assert.Equal(ModelValidationState.Skipped, entry.Value.ValidationState);
|
||||
}
|
||||
|
||||
private static void AssertRequiredError(string key, ModelError error)
|
||||
{
|
||||
// Mono issue - https://github.com/aspnet/External/issues/19
|
||||
|
|
|
|||
|
|
@ -19,6 +19,9 @@ using Moq;
|
|||
using Newtonsoft.Json.Linq;
|
||||
using Xunit;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using System.Threading;
|
||||
using Microsoft.AspNet.Http;
|
||||
using Microsoft.AspNet.Mvc.ModelBinding.Metadata;
|
||||
|
||||
namespace Microsoft.AspNet.Mvc
|
||||
{
|
||||
|
|
@ -134,7 +137,7 @@ namespace Microsoft.AspNet.Mvc
|
|||
}
|
||||
|
||||
[Fact]
|
||||
public void Setup_SetsUpExcludeFromValidationDelegates()
|
||||
public void Setup_SetsUpMetadataDetailsProviders()
|
||||
{
|
||||
// Arrange & Act
|
||||
var options = GetOptions<MvcOptions>(services =>
|
||||
|
|
@ -144,48 +147,40 @@ namespace Microsoft.AspNet.Mvc
|
|||
});
|
||||
|
||||
// Assert
|
||||
Assert.Equal(8, options.ValidationExcludeFilters.Count);
|
||||
var providers = options.ModelMetadataDetailsProviders;
|
||||
Assert.Equal(12, providers.Count);
|
||||
var i = 0;
|
||||
|
||||
// Verify if the delegates registered by default exclude the given types.
|
||||
Assert.IsType(typeof(SimpleTypesExcludeFilter), options.ValidationExcludeFilters[i++]);
|
||||
Assert.IsType<DefaultBindingMetadataProvider>(providers[i++]);
|
||||
Assert.IsType<DefaultValidationMetadataProvider>(providers[i++]);
|
||||
|
||||
Assert.IsType(typeof(DefaultTypeBasedExcludeFilter), options.ValidationExcludeFilters[i]);
|
||||
var typeFilter
|
||||
= Assert.IsType<DefaultTypeBasedExcludeFilter>(options.ValidationExcludeFilters[i++]);
|
||||
Assert.Equal(typeFilter.ExcludedType, typeof(Type));
|
||||
var excludeFilter = Assert.IsType<ValidationExcludeFilter>(providers[i++]);
|
||||
Assert.Equal(typeof(Type), excludeFilter.Type);
|
||||
|
||||
Assert.IsType(typeof(DefaultTypeBasedExcludeFilter), options.ValidationExcludeFilters[i]);
|
||||
var cancellationTokenFilter
|
||||
= Assert.IsType<DefaultTypeBasedExcludeFilter>(options.ValidationExcludeFilters[i++]);
|
||||
Assert.Equal(cancellationTokenFilter.ExcludedType, typeof(System.Threading.CancellationToken));
|
||||
excludeFilter = Assert.IsType<ValidationExcludeFilter>(providers[i++]);
|
||||
Assert.Equal(typeof(Uri), excludeFilter.Type);
|
||||
|
||||
Assert.IsType(typeof(DefaultTypeBasedExcludeFilter), options.ValidationExcludeFilters[i]);
|
||||
var formFileFilter
|
||||
= Assert.IsType<DefaultTypeBasedExcludeFilter>(options.ValidationExcludeFilters[i++]);
|
||||
Assert.Equal(formFileFilter.ExcludedType, typeof(Http.IFormFile));
|
||||
excludeFilter = Assert.IsType<ValidationExcludeFilter>(providers[i++]);
|
||||
Assert.Equal(typeof(CancellationToken), excludeFilter.Type);
|
||||
|
||||
Assert.IsType(
|
||||
typeof(DefaultTypeBasedExcludeFilter),
|
||||
options.ValidationExcludeFilters[i]);
|
||||
var formCollectionFilter
|
||||
= Assert.IsType<DefaultTypeBasedExcludeFilter>(options.ValidationExcludeFilters[i++]);
|
||||
Assert.Equal(formCollectionFilter.ExcludedType, typeof(Http.IFormCollection));
|
||||
excludeFilter = Assert.IsType<ValidationExcludeFilter>(providers[i++]);
|
||||
Assert.Equal(typeof(IFormFile), excludeFilter.Type);
|
||||
|
||||
Assert.IsType(typeof(DefaultTypeBasedExcludeFilter), options.ValidationExcludeFilters[i]);
|
||||
var jTokenFilter
|
||||
= Assert.IsType<DefaultTypeBasedExcludeFilter>(options.ValidationExcludeFilters[i++]);
|
||||
Assert.Equal(jTokenFilter.ExcludedType, typeof(JToken));
|
||||
excludeFilter = Assert.IsType<ValidationExcludeFilter>(providers[i++]);
|
||||
Assert.Equal(typeof(IFormCollection), excludeFilter.Type);
|
||||
|
||||
Assert.IsType(typeof(DefaultTypeNameBasedExcludeFilter), options.ValidationExcludeFilters[i]);
|
||||
var xObjectFilter
|
||||
= Assert.IsType<DefaultTypeNameBasedExcludeFilter>(options.ValidationExcludeFilters[i++]);
|
||||
Assert.Equal(xObjectFilter.ExcludedTypeName, typeof(XObject).FullName);
|
||||
Assert.IsType<DataAnnotationsMetadataProvider>(providers[i++]);
|
||||
|
||||
Assert.IsType(typeof(DefaultTypeNameBasedExcludeFilter), options.ValidationExcludeFilters[i]);
|
||||
var xmlNodeFilter =
|
||||
Assert.IsType<DefaultTypeNameBasedExcludeFilter>(options.ValidationExcludeFilters[i++]);
|
||||
Assert.Equal(xmlNodeFilter.ExcludedTypeName, "System.Xml.XmlNode");
|
||||
excludeFilter = Assert.IsType<ValidationExcludeFilter>(providers[i++]);
|
||||
Assert.Equal(typeof(JToken), excludeFilter.Type);
|
||||
|
||||
Assert.IsType<DataMemberRequiredBindingMetadataProvider>(providers[i++]);
|
||||
|
||||
excludeFilter = Assert.IsType<ValidationExcludeFilter>(providers[i++]);
|
||||
Assert.Equal(typeof(XObject).FullName, excludeFilter.FullTypeName);
|
||||
|
||||
excludeFilter = Assert.IsType<ValidationExcludeFilter>(providers[i++]);
|
||||
Assert.Equal("System.Xml.XmlNode", excludeFilter.FullTypeName);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
|
|
|
|||
|
|
@ -26,6 +26,34 @@ namespace Microsoft.AspNet.Mvc.ModelBinding
|
|||
return new DefaultModelMetadataProvider(compositeDetailsProvider);
|
||||
}
|
||||
|
||||
public static IModelMetadataProvider CreateDefaultProvider(IList<IMetadataDetailsProvider> providers)
|
||||
{
|
||||
var detailsProviders = new List<IMetadataDetailsProvider>()
|
||||
{
|
||||
new DefaultBindingMetadataProvider(CreateMessageProvider()),
|
||||
new DefaultValidationMetadataProvider(),
|
||||
new DataAnnotationsMetadataProvider(),
|
||||
new DataMemberRequiredBindingMetadataProvider(),
|
||||
};
|
||||
|
||||
detailsProviders.AddRange(providers);
|
||||
|
||||
var compositeDetailsProvider = new DefaultCompositeMetadataDetailsProvider(detailsProviders);
|
||||
return new DefaultModelMetadataProvider(compositeDetailsProvider);
|
||||
}
|
||||
|
||||
public static IModelMetadataProvider CreateProvider(IList<IMetadataDetailsProvider> providers)
|
||||
{
|
||||
var detailsProviders = new List<IMetadataDetailsProvider>();
|
||||
if (providers != null)
|
||||
{
|
||||
detailsProviders.AddRange(providers);
|
||||
}
|
||||
|
||||
var compositeDetailsProvider = new DefaultCompositeMetadataDetailsProvider(detailsProviders);
|
||||
return new DefaultModelMetadataProvider(compositeDetailsProvider);
|
||||
}
|
||||
|
||||
private readonly TestModelMetadataDetailsProvider _detailsProvider;
|
||||
|
||||
public TestModelMetadataProvider()
|
||||
|
|
|
|||
|
|
@ -1873,7 +1873,7 @@ namespace Microsoft.AspNet.Mvc.Test
|
|||
{
|
||||
ControllerContext = controllerContext,
|
||||
MetadataProvider = metadataProvider,
|
||||
ObjectValidator = new DefaultObjectValidator(new IExcludeTypeValidationFilter[0], metadataProvider),
|
||||
ObjectValidator = new DefaultObjectValidator(metadataProvider),
|
||||
TempData = tempData,
|
||||
ViewData = viewData,
|
||||
};
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@
|
|||
|
||||
using Microsoft.AspNet.Builder;
|
||||
using Microsoft.AspNet.Mvc;
|
||||
using Microsoft.AspNet.Mvc.ModelBinding.Validation;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
|
||||
namespace FormatterWebSite
|
||||
|
|
@ -13,8 +14,8 @@ namespace FormatterWebSite
|
|||
{
|
||||
services.AddMvc(options =>
|
||||
{
|
||||
options.ValidationExcludeFilters.Add(typeof(Developer));
|
||||
options.ValidationExcludeFilters.Add(typeof(Supplier));
|
||||
options.ModelMetadataDetailsProviders.Add(new ValidationExcludeFilter(typeof(Developer)));
|
||||
options.ModelMetadataDetailsProviders.Add(new ValidationExcludeFilter(typeof(Supplier)));
|
||||
|
||||
options.InputFormatters.Add(new StringInputFormatter());
|
||||
})
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@
|
|||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using Microsoft.AspNet.Builder;
|
||||
using Microsoft.AspNet.Mvc.ModelBinding.Validation;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using ModelBindingWebSite.Models;
|
||||
using ModelBindingWebSite.Services;
|
||||
|
|
@ -20,7 +21,7 @@ namespace ModelBindingWebSite
|
|||
m.MaxModelValidationErrors = 8;
|
||||
m.ModelBinders.Insert(0, new TestBindingSourceModelBinder());
|
||||
|
||||
m.ValidationExcludeFilters.Add(typeof(Address));
|
||||
m.ModelMetadataDetailsProviders.Add(new ValidationExcludeFilter(typeof(Address)));
|
||||
|
||||
// ModelMetadataController relies on additional values AdditionalValuesMetadataProvider provides.
|
||||
m.ModelMetadataDetailsProviders.Add(new AdditionalValuesMetadataProvider());
|
||||
|
|
|
|||
Loading…
Reference in New Issue