Adding support for excluding types for validation, based on type names for body bound models.
This commit is contained in:
parent
bff70e0dd1
commit
6b2f331e8d
|
|
@ -0,0 +1,39 @@
|
||||||
|
// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved.
|
||||||
|
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||||
|
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using Microsoft.AspNet.Mvc.ModelBinding;
|
||||||
|
using Microsoft.Framework.DependencyInjection;
|
||||||
|
using Microsoft.Framework.OptionsModel;
|
||||||
|
|
||||||
|
namespace Microsoft.AspNet.Mvc.OptionDescriptors
|
||||||
|
{
|
||||||
|
/// <inheritdoc />
|
||||||
|
public class DefaultValidationExcludeFiltersProvider
|
||||||
|
: OptionDescriptorBasedProvider<IExcludeTypeValidationFilter>, IValidationExcludeFiltersProvider
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Initializes a new instance of the DefaultBodyValidationExcludeFiltersProvider class.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="options">An accessor to the <see cref="MvcOptions"/> configured for this application.</param>
|
||||||
|
/// <param name="typeActivator">An <see cref="ITypeActivator"/> instance used to instantiate types.</param>
|
||||||
|
/// <param name="serviceProvider">A <see cref="IServiceProvider"/> instance that retrieves services from the
|
||||||
|
/// service collection.</param>
|
||||||
|
public DefaultValidationExcludeFiltersProvider(IOptions<MvcOptions> optionsAccessor,
|
||||||
|
ITypeActivator typeActivator,
|
||||||
|
IServiceProvider serviceProvider)
|
||||||
|
: base(optionsAccessor.Options.ValidationExcludeFilters, typeActivator, serviceProvider)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public IReadOnlyList<IExcludeTypeValidationFilter> ExcludeFilters
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return Options;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,35 @@
|
||||||
|
// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved.
|
||||||
|
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||||
|
|
||||||
|
using System;
|
||||||
|
using Microsoft.AspNet.Mvc.ModelBinding;
|
||||||
|
|
||||||
|
namespace Microsoft.AspNet.Mvc
|
||||||
|
{
|
||||||
|
/// <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([NotNull] Type type)
|
||||||
|
{
|
||||||
|
ExcludedType = type;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the type which is excluded from validation.
|
||||||
|
/// </summary>
|
||||||
|
public Type ExcludedType { get; }
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public bool IsTypeExcluded([NotNull] Type propertyType)
|
||||||
|
{
|
||||||
|
return ExcludedType.IsAssignableFrom(propertyType);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,50 @@
|
||||||
|
// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved.
|
||||||
|
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||||
|
|
||||||
|
using System;
|
||||||
|
using Microsoft.AspNet.Mvc.ModelBinding;
|
||||||
|
|
||||||
|
namespace Microsoft.AspNet.Mvc
|
||||||
|
{
|
||||||
|
/// <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([NotNull] string typeFullName)
|
||||||
|
{
|
||||||
|
ExcludedTypeName = typeFullName;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the type full name which is excluded from validation.
|
||||||
|
/// </summary>
|
||||||
|
public string ExcludedTypeName { get; }
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public bool IsTypeExcluded([NotNull] Type 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.BaseType());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,19 @@
|
||||||
|
// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved.
|
||||||
|
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||||
|
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using Microsoft.AspNet.Mvc.ModelBinding;
|
||||||
|
|
||||||
|
namespace Microsoft.AspNet.Mvc
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Provides an activated collection of <see cref="IExcludeTypeValidationFilter"/> instances.
|
||||||
|
/// </summary>
|
||||||
|
public interface IValidationExcludeFiltersProvider
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Gets a collection of activated <see cref="IExcludeTypeValidationFilter"/> instances.
|
||||||
|
/// </summary>
|
||||||
|
IReadOnlyList<IExcludeTypeValidationFilter> ExcludeFilters { get; }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -1,14 +1,10 @@
|
||||||
// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved.
|
// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved.
|
||||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||||
|
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using Microsoft.AspNet.Mvc.Core;
|
using Microsoft.AspNet.Mvc.Core;
|
||||||
using Microsoft.AspNet.Mvc.ModelBinding;
|
using Microsoft.AspNet.Mvc.ModelBinding;
|
||||||
using Microsoft.Framework.DependencyInjection;
|
using Microsoft.Framework.DependencyInjection;
|
||||||
using Microsoft.Framework.OptionsModel;
|
|
||||||
|
|
||||||
namespace Microsoft.AspNet.Mvc
|
namespace Microsoft.AspNet.Mvc
|
||||||
{
|
{
|
||||||
|
|
@ -21,17 +17,17 @@ namespace Microsoft.AspNet.Mvc
|
||||||
private readonly ActionContext _actionContext;
|
private readonly ActionContext _actionContext;
|
||||||
private readonly IInputFormatterSelector _formatterSelector;
|
private readonly IInputFormatterSelector _formatterSelector;
|
||||||
private readonly IBodyModelValidator _bodyModelValidator;
|
private readonly IBodyModelValidator _bodyModelValidator;
|
||||||
private readonly IOptions<MvcOptions> _mvcOptions;
|
private readonly IValidationExcludeFiltersProvider _bodyValidationExcludeFiltersProvider;
|
||||||
|
|
||||||
public BodyModelBinder([NotNull] IContextAccessor<ActionContext> context,
|
public BodyModelBinder([NotNull] IContextAccessor<ActionContext> context,
|
||||||
[NotNull] IInputFormatterSelector selector,
|
[NotNull] IInputFormatterSelector selector,
|
||||||
[NotNull] IBodyModelValidator bodyModelValidator,
|
[NotNull] IBodyModelValidator bodyModelValidator,
|
||||||
[NotNull] IOptions<MvcOptions> mvcOptions)
|
[NotNull] IValidationExcludeFiltersProvider bodyValidationExcludeFiltersProvider)
|
||||||
{
|
{
|
||||||
_actionContext = context.Value;
|
_actionContext = context.Value;
|
||||||
_formatterSelector = selector;
|
_formatterSelector = selector;
|
||||||
_bodyModelValidator = bodyModelValidator;
|
_bodyModelValidator = bodyModelValidator;
|
||||||
_mvcOptions = mvcOptions;
|
_bodyValidationExcludeFiltersProvider = bodyValidationExcludeFiltersProvider;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override async Task<bool> BindAsync(
|
protected override async Task<bool> BindAsync(
|
||||||
|
|
@ -60,7 +56,7 @@ namespace Microsoft.AspNet.Mvc
|
||||||
bindingContext.ModelState,
|
bindingContext.ModelState,
|
||||||
bindingContext.ModelMetadata,
|
bindingContext.ModelMetadata,
|
||||||
containerMetadata: null,
|
containerMetadata: null,
|
||||||
excludeFromValidationDelegate: _mvcOptions.Options.ExcludeFromValidationDelegates);
|
excludeFromValidationFilters: _bodyValidationExcludeFiltersProvider.ExcludeFilters);
|
||||||
_bodyModelValidator.Validate(validationContext, bindingContext.ModelName);
|
_bodyModelValidator.Validate(validationContext, bindingContext.ModelName);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,26 +0,0 @@
|
||||||
// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved.
|
|
||||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
|
||||||
|
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using Microsoft.AspNet.Mvc.ModelBinding;
|
|
||||||
|
|
||||||
namespace Microsoft.AspNet.Mvc
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// Extensions for <see cref="MvcOptions.ExcludeFromValidationDelegates"/>.
|
|
||||||
/// </summary>
|
|
||||||
public static class ExcludeFromValidationDelegateExtensions
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// Adds a delegate to the specified <paramref name="list" />
|
|
||||||
/// that exludes the properties of the specified and it's derived types from validaton.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="list"><see cref="IList{T}"/> of <see cref="ExcludeFromValidationDelegate"/>.</param>
|
|
||||||
/// <param name="type"><see cref="Type"/> which should be excluded from validation.</param>
|
|
||||||
public static void Add(this IList<ExcludeFromValidationDelegate> list, Type type)
|
|
||||||
{
|
|
||||||
list.Add(t => t.IsAssignableFrom(type));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -0,0 +1,35 @@
|
||||||
|
// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved.
|
||||||
|
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||||
|
|
||||||
|
using System;
|
||||||
|
using Microsoft.AspNet.Mvc.ModelBinding;
|
||||||
|
|
||||||
|
namespace Microsoft.AspNet.Mvc.OptionDescriptors
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Encapsulates information that describes an <see cref="IExcludeTypeValidationFilter"/>.
|
||||||
|
/// </summary>
|
||||||
|
public class ExcludeValidationDescriptor : OptionDescriptor<IExcludeTypeValidationFilter>
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Creates a new instance of <see cref="ExcludeValidationDescriptor"/>.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="type">
|
||||||
|
/// A <see cref="IExcludeTypeValidationFilter"/> type that the descriptor represents.
|
||||||
|
/// </param>
|
||||||
|
public ExcludeValidationDescriptor([NotNull] Type type)
|
||||||
|
: base(type)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Creates a new instance of <see cref="ExcludeValidationDescriptor"/>.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="validationFilter">An instance of <see cref="IExcludeTypeValidationFilter"/>
|
||||||
|
/// that the descriptor represents.</param>
|
||||||
|
public ExcludeValidationDescriptor([NotNull] IExcludeTypeValidationFilter validationFilter)
|
||||||
|
: base(validationFilter)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,45 @@
|
||||||
|
// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved.
|
||||||
|
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||||
|
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using Microsoft.AspNet.Mvc.OptionDescriptors;
|
||||||
|
|
||||||
|
namespace Microsoft.AspNet.Mvc
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Extensions for <see cref="MvcOptions.ValidationExcludeFilters"/>.
|
||||||
|
/// </summary>
|
||||||
|
public static class ValidationExcludeFiltersExtensions
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Adds a descriptor to the specified <paramref name="excludeBodyValidationDescriptorCollection" />
|
||||||
|
/// that excludes the properties of the <see cref="Type"/> specified and it's derived types from validaton.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="excludeBodyValidationDescriptorCollection">A list of <see cref="ExcludeValidationDescriptor"/>
|
||||||
|
/// which are used to get a collection of exclude filters to be applied for filtering model properties during validation.
|
||||||
|
/// </param>
|
||||||
|
/// <param name="type"><see cref="Type"/> which should be excluded from validation.</param>
|
||||||
|
public static void Add(this IList<ExcludeValidationDescriptor> excludeBodyValidationDescriptorCollection,
|
||||||
|
Type type)
|
||||||
|
{
|
||||||
|
var typeBasedExcludeFilter = new DefaultTypeBasedExcludeFilter(type);
|
||||||
|
excludeBodyValidationDescriptorCollection.Add(new ExcludeValidationDescriptor(typeBasedExcludeFilter));
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Adds a descriptor to the specified <paramref name="excludeBodyValidationDescriptorCollection" />
|
||||||
|
/// that excludes the properties of the type specified and it's derived types from validaton.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="excludeBodyValidationDescriptorCollection">A list of <see cref="ExcludeValidationDescriptor"/>
|
||||||
|
/// which are used to get a collection of exclude filters to be applied for filtering model properties during validation.
|
||||||
|
/// </param>
|
||||||
|
/// <param name="typeFullName">Full name of the type which should be excluded from validation.</param>
|
||||||
|
public static void Add(this IList<ExcludeValidationDescriptor> excludeBodyValidationDescriptorCollection,
|
||||||
|
string typeFullName)
|
||||||
|
{
|
||||||
|
var filter = new DefaultTypeNameBasedExcludeFilter(typeFullName);
|
||||||
|
excludeBodyValidationDescriptorCollection.Add(new ExcludeValidationDescriptor(filter));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -71,11 +71,11 @@ namespace Microsoft.AspNet.Mvc
|
||||||
public List<InputFormatterDescriptor> InputFormatters { get; private set; }
|
public List<InputFormatterDescriptor> InputFormatters { get; private set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets a list of <see cref="ExcludeFromValidationDelegate"/> which return whether the given type
|
/// Gets a list of <see cref="ExcludeValidationDescriptor"/> which are used to construct a list
|
||||||
/// should be excluded from Validation in <see cref="IBodyModelValidator"/>
|
/// of exclude filters by <see cref="IValidationExcludeFiltersProvider"/>,
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public List<ExcludeFromValidationDelegate> ExcludeFromValidationDelegates { get; }
|
public List<ExcludeValidationDescriptor> ValidationExcludeFilters { get; }
|
||||||
= new List<ExcludeFromValidationDelegate>();
|
= new List<ExcludeValidationDescriptor>();
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets or sets the maximum number of validation errors that are allowed by this application before further
|
/// Gets or sets the maximum number of validation errors that are allowed by this application before further
|
||||||
|
|
@ -58,7 +58,7 @@ namespace Microsoft.AspNet.Mvc.ModelBinding
|
||||||
var modelType = metadata.Model.GetType();
|
var modelType = metadata.Model.GetType();
|
||||||
if (TypeHelper.IsSimpleType(modelType) ||
|
if (TypeHelper.IsSimpleType(modelType) ||
|
||||||
IsTypeExcludedFromValidation(
|
IsTypeExcludedFromValidation(
|
||||||
validationContext.ModelValidationContext.ExcludeFromValidationDelegate, modelType))
|
validationContext.ModelValidationContext.ExcludeFromValidationFilters, modelType))
|
||||||
{
|
{
|
||||||
return ShallowValidate(metadata, validationContext, validators);
|
return ShallowValidate(metadata, validationContext, validators);
|
||||||
}
|
}
|
||||||
|
|
@ -197,15 +197,15 @@ namespace Microsoft.AspNet.Mvc.ModelBinding
|
||||||
}
|
}
|
||||||
|
|
||||||
private bool IsTypeExcludedFromValidation(
|
private bool IsTypeExcludedFromValidation(
|
||||||
IReadOnlyList<ExcludeFromValidationDelegate> predicates, Type type)
|
IReadOnlyList<IExcludeTypeValidationFilter> filters, Type type)
|
||||||
{
|
{
|
||||||
// This can be set to null in ModelBinding scenarios which does not flow through this path.
|
// This can be set to null in ModelBinding scenarios which does not flow through this path.
|
||||||
if (predicates == null)
|
if (filters == null)
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
return predicates.Any(t => t(type));
|
return filters.Any(filter => filter.IsTypeExcluded(type));
|
||||||
}
|
}
|
||||||
|
|
||||||
private static Type GetElementType(Type type)
|
private static Type GetElementType(Type type)
|
||||||
|
|
|
||||||
|
|
@ -1,14 +0,0 @@
|
||||||
// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved.
|
|
||||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
|
||||||
|
|
||||||
using System;
|
|
||||||
|
|
||||||
namespace Microsoft.AspNet.Mvc.ModelBinding
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// Delegate that determines if the specified <paramref name="type"/> is excluded from validation.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="type"><see cref="Type"/> which needs to be checked.</param>
|
|
||||||
/// <returns><c>true</c> if excluded, <c>false</c> otherwise.</returns>
|
|
||||||
public delegate bool ExcludeFromValidationDelegate(Type type);
|
|
||||||
}
|
|
||||||
|
|
@ -0,0 +1,20 @@
|
||||||
|
// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved.
|
||||||
|
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||||
|
|
||||||
|
using System;
|
||||||
|
|
||||||
|
namespace Microsoft.AspNet.Mvc.ModelBinding
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 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([NotNull] Type type);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -27,7 +27,7 @@ namespace Microsoft.AspNet.Mvc.ModelBinding
|
||||||
modelState,
|
modelState,
|
||||||
metadata,
|
metadata,
|
||||||
containerMetadata,
|
containerMetadata,
|
||||||
excludeFromValidationDelegate: null)
|
excludeFromValidationFilters: null)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -36,14 +36,14 @@ namespace Microsoft.AspNet.Mvc.ModelBinding
|
||||||
[NotNull] ModelStateDictionary modelState,
|
[NotNull] ModelStateDictionary modelState,
|
||||||
[NotNull] ModelMetadata metadata,
|
[NotNull] ModelMetadata metadata,
|
||||||
ModelMetadata containerMetadata,
|
ModelMetadata containerMetadata,
|
||||||
IReadOnlyList<ExcludeFromValidationDelegate> excludeFromValidationDelegate)
|
IReadOnlyList<IExcludeTypeValidationFilter> excludeFromValidationFilters)
|
||||||
{
|
{
|
||||||
ModelMetadata = metadata;
|
ModelMetadata = metadata;
|
||||||
ModelState = modelState;
|
ModelState = modelState;
|
||||||
MetadataProvider = metadataProvider;
|
MetadataProvider = metadataProvider;
|
||||||
ValidatorProvider = validatorProvider;
|
ValidatorProvider = validatorProvider;
|
||||||
ContainerMetadata = containerMetadata;
|
ContainerMetadata = containerMetadata;
|
||||||
ExcludeFromValidationDelegate = excludeFromValidationDelegate;
|
ExcludeFromValidationFilters = excludeFromValidationFilters;
|
||||||
}
|
}
|
||||||
|
|
||||||
public ModelValidationContext([NotNull] ModelValidationContext parentContext,
|
public ModelValidationContext([NotNull] ModelValidationContext parentContext,
|
||||||
|
|
@ -54,19 +54,19 @@ namespace Microsoft.AspNet.Mvc.ModelBinding
|
||||||
ModelState = parentContext.ModelState;
|
ModelState = parentContext.ModelState;
|
||||||
MetadataProvider = parentContext.MetadataProvider;
|
MetadataProvider = parentContext.MetadataProvider;
|
||||||
ValidatorProvider = parentContext.ValidatorProvider;
|
ValidatorProvider = parentContext.ValidatorProvider;
|
||||||
ExcludeFromValidationDelegate = parentContext.ExcludeFromValidationDelegate;
|
ExcludeFromValidationFilters = parentContext.ExcludeFromValidationFilters;
|
||||||
}
|
}
|
||||||
|
|
||||||
public ModelMetadata ModelMetadata { get; private set; }
|
public ModelMetadata ModelMetadata { get; }
|
||||||
|
|
||||||
public ModelMetadata ContainerMetadata { get; private set; }
|
public ModelMetadata ContainerMetadata { get; }
|
||||||
|
|
||||||
public ModelStateDictionary ModelState { get; private set; }
|
public ModelStateDictionary ModelState { get; }
|
||||||
|
|
||||||
public IModelMetadataProvider MetadataProvider { get; private set; }
|
public IModelMetadataProvider MetadataProvider { get; }
|
||||||
|
|
||||||
public IModelValidatorProvider ValidatorProvider { get; private set; }
|
public IModelValidatorProvider ValidatorProvider { get; }
|
||||||
|
|
||||||
public IReadOnlyList<ExcludeFromValidationDelegate> ExcludeFromValidationDelegate { get; private set; }
|
public IReadOnlyList<IExcludeTypeValidationFilter> ExcludeFromValidationFilters { get; }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -12,7 +12,6 @@ using Microsoft.AspNet.Mvc.ModelBinding;
|
||||||
using Microsoft.AspNet.Mvc.WebApiCompatShim;
|
using Microsoft.AspNet.Mvc.WebApiCompatShim;
|
||||||
using Microsoft.AspNet.Routing;
|
using Microsoft.AspNet.Routing;
|
||||||
using Microsoft.Framework.DependencyInjection;
|
using Microsoft.Framework.DependencyInjection;
|
||||||
using Microsoft.Framework.OptionsModel;
|
|
||||||
using Newtonsoft.Json;
|
using Newtonsoft.Json;
|
||||||
using MvcMediaTypeHeaderValue = Microsoft.AspNet.Mvc.HeaderValueAbstractions.MediaTypeHeaderValue;
|
using MvcMediaTypeHeaderValue = Microsoft.AspNet.Mvc.HeaderValueAbstractions.MediaTypeHeaderValue;
|
||||||
|
|
||||||
|
|
@ -402,7 +401,8 @@ namespace System.Web.Http
|
||||||
/// </param>
|
/// </param>
|
||||||
public void Validate<TEntity>(TEntity entity, string keyPrefix)
|
public void Validate<TEntity>(TEntity entity, string keyPrefix)
|
||||||
{
|
{
|
||||||
var mvcOptions = Context.RequestServices.GetRequiredService<IOptions<MvcOptions>>();
|
var bodyValidationExcludeFiltersProvider = Context.RequestServices
|
||||||
|
.GetRequiredService<IValidationExcludeFiltersProvider>();
|
||||||
var validator = Context.RequestServices.GetRequiredService<IBodyModelValidator>();
|
var validator = Context.RequestServices.GetRequiredService<IBodyModelValidator>();
|
||||||
var metadataProvider = Context.RequestServices.GetRequiredService<IModelMetadataProvider>();
|
var metadataProvider = Context.RequestServices.GetRequiredService<IModelMetadataProvider>();
|
||||||
var modelMetadata = metadataProvider.GetMetadataForType(() => entity, typeof(TEntity));
|
var modelMetadata = metadataProvider.GetMetadataForType(() => entity, typeof(TEntity));
|
||||||
|
|
@ -413,7 +413,7 @@ namespace System.Web.Http
|
||||||
ModelState,
|
ModelState,
|
||||||
modelMetadata,
|
modelMetadata,
|
||||||
containerMetadata: null,
|
containerMetadata: null,
|
||||||
excludeFromValidationDelegate: mvcOptions.Options.ExcludeFromValidationDelegates);
|
excludeFromValidationFilters: bodyValidationExcludeFiltersProvider.ExcludeFilters);
|
||||||
validator.Validate(modelValidationContext, keyPrefix);
|
validator.Validate(modelValidationContext, keyPrefix);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -58,11 +58,11 @@ namespace Microsoft.AspNet.Mvc
|
||||||
options.ModelValidatorProviders.Add(new DataMemberModelValidatorProvider());
|
options.ModelValidatorProviders.Add(new DataMemberModelValidatorProvider());
|
||||||
|
|
||||||
// Add types to be excluded from Validation
|
// Add types to be excluded from Validation
|
||||||
options.ExcludeFromValidationDelegates.Add(typeof(XmlNode));
|
options.ValidationExcludeFilters.Add(typeof(XObject));
|
||||||
options.ExcludeFromValidationDelegates.Add(typeof(XObject));
|
options.ValidationExcludeFilters.Add(typeof(Type));
|
||||||
options.ExcludeFromValidationDelegates.Add(typeof(Type));
|
options.ValidationExcludeFilters.Add(typeof(byte[]));
|
||||||
options.ExcludeFromValidationDelegates.Add(typeof(byte[]));
|
options.ValidationExcludeFilters.Add(typeof(JToken));
|
||||||
options.ExcludeFromValidationDelegates.Add(typeof(JToken));
|
options.ValidationExcludeFilters.Add(typeFullName: "System.Xml.XmlNode");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -99,6 +99,7 @@ namespace Microsoft.AspNet.Mvc
|
||||||
yield return describe.Transient<IModelValidatorProviderProvider, DefaultModelValidatorProviderProvider>();
|
yield return describe.Transient<IModelValidatorProviderProvider, DefaultModelValidatorProviderProvider>();
|
||||||
yield return describe.Scoped<ICompositeModelValidatorProvider, CompositeModelValidatorProvider>();
|
yield return describe.Scoped<ICompositeModelValidatorProvider, CompositeModelValidatorProvider>();
|
||||||
yield return describe.Transient<IBodyModelValidator, DefaultBodyModelValidator>();
|
yield return describe.Transient<IBodyModelValidator, DefaultBodyModelValidator>();
|
||||||
|
yield return describe.Transient<IValidationExcludeFiltersProvider, DefaultValidationExcludeFiltersProvider>();
|
||||||
|
|
||||||
//
|
//
|
||||||
// Razor, Views and runtime compilation
|
// Razor, Views and runtime compilation
|
||||||
|
|
|
||||||
|
|
@ -10,10 +10,6 @@
|
||||||
},
|
},
|
||||||
"frameworks": {
|
"frameworks": {
|
||||||
"aspnet50": {},
|
"aspnet50": {},
|
||||||
"aspnetcore50": {
|
"aspnetcore50": {}
|
||||||
"dependencies": {
|
|
||||||
"System.Xml.XmlDocument": "4.0.0-beta-*"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -33,7 +33,7 @@ namespace Microsoft.AspNet.Mvc
|
||||||
var bindingContext = GetBindingContext(typeof(Person), inputFormatter: mockInputFormatter.Object);
|
var bindingContext = GetBindingContext(typeof(Person), inputFormatter: mockInputFormatter.Object);
|
||||||
bindingContext.ModelMetadata.BinderMetadata = Mock.Of<IFormatterBinderMetadata>();
|
bindingContext.ModelMetadata.BinderMetadata = Mock.Of<IFormatterBinderMetadata>();
|
||||||
|
|
||||||
var binder = GetBodyBinder(mockInputFormatter.Object, mockValidator.Object, null);
|
var binder = GetBodyBinder(mockInputFormatter.Object, mockValidator.Object);
|
||||||
|
|
||||||
// Act
|
// Act
|
||||||
var binderResult = await binder.BindModelAsync(bindingContext);
|
var binderResult = await binder.BindModelAsync(bindingContext);
|
||||||
|
|
@ -88,7 +88,7 @@ namespace Microsoft.AspNet.Mvc
|
||||||
ModelMetadata = metadataProvider.GetMetadataForType(null, modelType),
|
ModelMetadata = metadataProvider.GetMetadataForType(null, modelType),
|
||||||
ModelName = "someName",
|
ModelName = "someName",
|
||||||
ValueProvider = Mock.Of<IValueProvider>(),
|
ValueProvider = Mock.Of<IValueProvider>(),
|
||||||
ModelBinder = GetBodyBinder(inputFormatter, null, null),
|
ModelBinder = GetBodyBinder(inputFormatter, null),
|
||||||
MetadataProvider = metadataProvider,
|
MetadataProvider = metadataProvider,
|
||||||
HttpContext = new DefaultHttpContext(),
|
HttpContext = new DefaultHttpContext(),
|
||||||
ModelState = new ModelStateDictionary()
|
ModelState = new ModelStateDictionary()
|
||||||
|
|
@ -98,7 +98,7 @@ namespace Microsoft.AspNet.Mvc
|
||||||
}
|
}
|
||||||
|
|
||||||
private static BodyModelBinder GetBodyBinder(
|
private static BodyModelBinder GetBodyBinder(
|
||||||
IInputFormatter inputFormatter, IBodyModelValidator validator, IOptions<MvcOptions> mvcOptions)
|
IInputFormatter inputFormatter, IBodyModelValidator validator)
|
||||||
{
|
{
|
||||||
var actionContext = CreateActionContext(new DefaultHttpContext());
|
var actionContext = CreateActionContext(new DefaultHttpContext());
|
||||||
var inputFormatterSelector = new Mock<IInputFormatterSelector>();
|
var inputFormatterSelector = new Mock<IInputFormatterSelector>();
|
||||||
|
|
@ -113,19 +113,14 @@ namespace Microsoft.AspNet.Mvc
|
||||||
validator = mockValidator.Object;
|
validator = mockValidator.Object;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mvcOptions == null)
|
var bodyValidationPredicatesProvidwer = new Mock<IValidationExcludeFiltersProvider>();
|
||||||
{
|
bodyValidationPredicatesProvidwer.SetupGet(o => o.ExcludeFilters)
|
||||||
var options = new Mock<MvcOptions>();
|
.Returns(new List<IExcludeTypeValidationFilter>());
|
||||||
options.CallBase = true;
|
|
||||||
var mockMvcOptions = new Mock<IOptions<MvcOptions>>();
|
|
||||||
mockMvcOptions.SetupGet(o => o.Options).Returns(options.Object);
|
|
||||||
mvcOptions = mockMvcOptions.Object;
|
|
||||||
}
|
|
||||||
|
|
||||||
var binder = new BodyModelBinder(actionContext,
|
var binder = new BodyModelBinder(actionContext,
|
||||||
inputFormatterSelector.Object,
|
inputFormatterSelector.Object,
|
||||||
validator,
|
validator,
|
||||||
mvcOptions);
|
bodyValidationPredicatesProvidwer.Object);
|
||||||
return binder;
|
return binder;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,138 @@
|
||||||
|
// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved.
|
||||||
|
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||||
|
|
||||||
|
using System;
|
||||||
|
using Microsoft.Framework.DependencyInjection;
|
||||||
|
using Microsoft.Framework.OptionsModel;
|
||||||
|
using Moq;
|
||||||
|
using Xunit;
|
||||||
|
|
||||||
|
namespace Microsoft.AspNet.Mvc.OptionDescriptors
|
||||||
|
{
|
||||||
|
public class DefaultValidationExcludeFiltersProviderTests
|
||||||
|
{
|
||||||
|
[Theory]
|
||||||
|
[InlineData(typeof(BaseType))]
|
||||||
|
[InlineData(typeof(DerivedType))]
|
||||||
|
public void Add_WithType_RegistersTypesAndDerivedType_ToBeExcluded(Type type)
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var options = new MvcOptions();
|
||||||
|
options.ValidationExcludeFilters.Add(type);
|
||||||
|
var optionsAccessor = new Mock<IOptions<MvcOptions>>();
|
||||||
|
optionsAccessor.SetupGet(o => o.Options)
|
||||||
|
.Returns(options);
|
||||||
|
var activator = new TypeActivator();
|
||||||
|
var serviceProvider = new Mock<IServiceProvider>();
|
||||||
|
var provider = new DefaultValidationExcludeFiltersProvider(optionsAccessor.Object,
|
||||||
|
activator,
|
||||||
|
serviceProvider.Object);
|
||||||
|
|
||||||
|
// Act
|
||||||
|
var filters = provider.ExcludeFilters;
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
Assert.Equal(1, filters.Count);
|
||||||
|
Assert.True(filters[0].IsTypeExcluded(type));
|
||||||
|
}
|
||||||
|
|
||||||
|
[Theory]
|
||||||
|
[InlineData(typeof(BaseType))]
|
||||||
|
[InlineData(typeof(UnRelatedType))]
|
||||||
|
[InlineData(typeof(UnRelatedType))]
|
||||||
|
public void Add_RegisterDerivedType_BaseAndUnrealatedTypesAreNotExcluded(Type type)
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var options = new MvcOptions();
|
||||||
|
options.ValidationExcludeFilters.Add(typeof(DerivedType));
|
||||||
|
var optionsAccessor = new Mock<IOptions<MvcOptions>>();
|
||||||
|
optionsAccessor.SetupGet(o => o.Options)
|
||||||
|
.Returns(options);
|
||||||
|
var activator = new TypeActivator();
|
||||||
|
var serviceProvider = new Mock<IServiceProvider>();
|
||||||
|
var provider = new DefaultValidationExcludeFiltersProvider(optionsAccessor.Object,
|
||||||
|
activator,
|
||||||
|
serviceProvider.Object);
|
||||||
|
|
||||||
|
// Act
|
||||||
|
var filters = provider.ExcludeFilters;
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
Assert.Equal(1, filters.Count);
|
||||||
|
Assert.False(filters[0].IsTypeExcluded(type));
|
||||||
|
}
|
||||||
|
|
||||||
|
[Theory]
|
||||||
|
[InlineData(typeof(BaseType))]
|
||||||
|
[InlineData(typeof(DerivedType))]
|
||||||
|
public void Add_WithTypeName_RegistersTypesAndDerivedType_ToBeExcluded(Type type)
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var options = new MvcOptions();
|
||||||
|
options.ValidationExcludeFilters.Add(type.FullName);
|
||||||
|
var optionsAccessor = new Mock<IOptions<MvcOptions>>();
|
||||||
|
optionsAccessor.SetupGet(o => o.Options)
|
||||||
|
.Returns(options);
|
||||||
|
var activator = new TypeActivator();
|
||||||
|
var serviceProvider = new Mock<IServiceProvider>();
|
||||||
|
var provider = new DefaultValidationExcludeFiltersProvider(optionsAccessor.Object,
|
||||||
|
activator,
|
||||||
|
serviceProvider.Object);
|
||||||
|
|
||||||
|
// Act
|
||||||
|
var filters = provider.ExcludeFilters;
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
Assert.Equal(1, filters.Count);
|
||||||
|
Assert.True(filters[0].IsTypeExcluded(type));
|
||||||
|
}
|
||||||
|
|
||||||
|
[Theory]
|
||||||
|
[InlineData(typeof(BaseType))]
|
||||||
|
[InlineData(typeof(UnRelatedType))]
|
||||||
|
[InlineData(typeof(SubNameSpace.UnRelatedType))]
|
||||||
|
public void Add_WithTypeName_RegisterDerivedType_BaseAndUnrealatedTypesAreNotExcluded(Type type)
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var options = new MvcOptions();
|
||||||
|
options.ValidationExcludeFilters.Add(typeof(DerivedType).FullName);
|
||||||
|
var optionsAccessor = new Mock<IOptions<MvcOptions>>();
|
||||||
|
optionsAccessor.SetupGet(o => o.Options)
|
||||||
|
.Returns(options);
|
||||||
|
var activator = new TypeActivator();
|
||||||
|
var serviceProvider = new Mock<IServiceProvider>();
|
||||||
|
var provider = new DefaultValidationExcludeFiltersProvider(optionsAccessor.Object,
|
||||||
|
activator,
|
||||||
|
serviceProvider.Object);
|
||||||
|
|
||||||
|
// Act
|
||||||
|
var filters = provider.ExcludeFilters;
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
Assert.Equal(1, filters.Count);
|
||||||
|
Assert.False(filters[0].IsTypeExcluded(type));
|
||||||
|
}
|
||||||
|
|
||||||
|
private class BaseType
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
private class DerivedType : BaseType
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
private class UnRelatedType
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace SubNameSpace
|
||||||
|
{
|
||||||
|
public class UnRelatedType
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -0,0 +1,61 @@
|
||||||
|
// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved.
|
||||||
|
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||||
|
|
||||||
|
using System;
|
||||||
|
using Microsoft.AspNet.Mvc.ModelBinding;
|
||||||
|
using Microsoft.AspNet.Testing;
|
||||||
|
using Xunit;
|
||||||
|
|
||||||
|
namespace Microsoft.AspNet.Mvc.OptionDescriptors
|
||||||
|
{
|
||||||
|
public class ExcludeValidationDescriptorTests
|
||||||
|
{
|
||||||
|
[Fact]
|
||||||
|
public void ConstructorThrows_IfTypeIsNotIExcludeTypeFromBodyValidation()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var expected = "The type 'System.String' must derive from " +
|
||||||
|
"'Microsoft.AspNet.Mvc.ModelBinding.IExcludeTypeValidationFilter'.";
|
||||||
|
var type = typeof(string);
|
||||||
|
|
||||||
|
// Act & Assert
|
||||||
|
ExceptionAssert.ThrowsArgument(() => new ExcludeValidationDescriptor(type), "type", expected);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void ConstructorSetsOptionType()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var type = typeof(TestExcludeFilter);
|
||||||
|
|
||||||
|
// Act
|
||||||
|
var descriptor = new ExcludeValidationDescriptor(type);
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
Assert.Equal(type, descriptor.OptionType);
|
||||||
|
Assert.Null(descriptor.Instance);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void ConstructorSetsInstanceeAndOptionType()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var instance = new TestExcludeFilter();
|
||||||
|
|
||||||
|
// Act
|
||||||
|
var descriptor = new ExcludeValidationDescriptor(instance);
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
Assert.Same(instance, descriptor.Instance);
|
||||||
|
Assert.Equal(instance.GetType(), descriptor.OptionType);
|
||||||
|
}
|
||||||
|
|
||||||
|
private class TestExcludeFilter : IExcludeTypeValidationFilter
|
||||||
|
{
|
||||||
|
public bool IsTypeExcluded([NotNull] Type propertyType)
|
||||||
|
{
|
||||||
|
throw new NotImplementedException();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,33 @@
|
||||||
|
// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved.
|
||||||
|
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||||
|
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using Microsoft.AspNet.Mvc.OptionDescriptors;
|
||||||
|
using Xunit;
|
||||||
|
|
||||||
|
namespace Microsoft.AspNet.Mvc
|
||||||
|
{
|
||||||
|
public class ValidationExcludeFiltersExtensionsTests
|
||||||
|
{
|
||||||
|
[Fact]
|
||||||
|
public void InputFormatterDescriptors_AddsTypesAndTypeNames()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var type1 = typeof(BaseType);
|
||||||
|
var collection = new List<ExcludeValidationDescriptor>();
|
||||||
|
|
||||||
|
// Act
|
||||||
|
collection.Add(type1);
|
||||||
|
collection.Add(type1.FullName);
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
Assert.Equal(2, collection.Count);
|
||||||
|
Assert.Equal(typeof(DefaultTypeBasedExcludeFilter), collection[0].OptionType);
|
||||||
|
Assert.Equal(typeof(DefaultTypeNameBasedExcludeFilter), collection[1].OptionType);
|
||||||
|
}
|
||||||
|
|
||||||
|
private class BaseType
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -2,9 +2,10 @@
|
||||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
|
using System.IO;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Net.Http;
|
using System.Net.Http;
|
||||||
using System.Xml;
|
using System.Xml.Linq;
|
||||||
|
|
||||||
namespace Microsoft.AspNet.Mvc.FunctionalTests
|
namespace Microsoft.AspNet.Mvc.FunctionalTests
|
||||||
{
|
{
|
||||||
|
|
@ -12,33 +13,22 @@ namespace Microsoft.AspNet.Mvc.FunctionalTests
|
||||||
{
|
{
|
||||||
public static string RetrieveAntiForgeryToken(string htmlContent, string actionUrl)
|
public static string RetrieveAntiForgeryToken(string htmlContent, string actionUrl)
|
||||||
{
|
{
|
||||||
int startSearchIndex = 0;
|
htmlContent = "<Root>" + htmlContent + "</Root>";
|
||||||
|
var reader = new StringReader(htmlContent);
|
||||||
while (startSearchIndex < htmlContent.Length)
|
var htmlDocument = XDocument.Load(reader);
|
||||||
|
foreach (var form in htmlDocument.Descendants("form"))
|
||||||
{
|
{
|
||||||
var formStartIndex = htmlContent.IndexOf("<form", startSearchIndex, StringComparison.OrdinalIgnoreCase);
|
foreach (var attribute in form.Attributes())
|
||||||
var formEndIndex = htmlContent.IndexOf("</form>", startSearchIndex, StringComparison.OrdinalIgnoreCase);
|
|
||||||
|
|
||||||
if (formStartIndex == -1 || formEndIndex == -1)
|
|
||||||
{
|
{
|
||||||
//Unable to find the form start or end - finish the search
|
if (string.Equals(attribute.Name.LocalName, "action", StringComparison.OrdinalIgnoreCase) &&
|
||||||
return null;
|
attribute.Value.EndsWith(actionUrl, StringComparison.OrdinalIgnoreCase))
|
||||||
}
|
|
||||||
|
|
||||||
formEndIndex = formEndIndex + "</form>".Length;
|
|
||||||
startSearchIndex = formEndIndex + 1;
|
|
||||||
|
|
||||||
var htmlDocument = new XmlDocument();
|
|
||||||
htmlDocument.LoadXml(htmlContent.Substring(formStartIndex, formEndIndex - formStartIndex));
|
|
||||||
foreach (XmlAttribute attribute in htmlDocument.DocumentElement.Attributes)
|
|
||||||
{
|
|
||||||
if (string.Equals(attribute.Name, "action", StringComparison.OrdinalIgnoreCase) && attribute.Value.EndsWith(actionUrl, StringComparison.OrdinalIgnoreCase))
|
|
||||||
{
|
{
|
||||||
foreach (XmlNode input in htmlDocument.GetElementsByTagName("input"))
|
foreach (var input in form.Descendants("input"))
|
||||||
{
|
{
|
||||||
if (input.Attributes["name"].Value == "__RequestVerificationToken" && input.Attributes["type"].Value == "hidden")
|
if (input.Attributes("name").First().Value == "__RequestVerificationToken" &&
|
||||||
|
input.Attributes("type").First().Value == "hidden")
|
||||||
{
|
{
|
||||||
return input.Attributes["value"].Value;
|
return input.Attributes("value").First().Value;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -77,16 +77,31 @@ namespace Microsoft.AspNet.Mvc.FunctionalTests
|
||||||
// Arrange
|
// Arrange
|
||||||
var server = TestServer.Create(_services, _app);
|
var server = TestServer.Create(_services, _app);
|
||||||
var client = server.CreateClient();
|
var client = server.CreateClient();
|
||||||
var sampleString = "RandomString";
|
var content = new StringContent("{\"Alias\":\"xyz\"}", Encoding.UTF8, "application/json");
|
||||||
var input = "{ NameThatThrowsOnGet:'" + sampleString + "'}";
|
|
||||||
var content = new StringContent(input, Encoding.UTF8, "application/json");
|
|
||||||
|
|
||||||
// Act
|
// Act
|
||||||
var response = await client.PostAsync("http://localhost/Validation/GetDeveloperName", content);
|
var response = await client.PostAsync("http://localhost/Validation/GetDeveloperName", content);
|
||||||
|
|
||||||
//Assert
|
//Assert
|
||||||
Assert.Equal(HttpStatusCode.OK, response.StatusCode);
|
Assert.Equal(HttpStatusCode.OK, response.StatusCode);
|
||||||
Assert.Equal("Developer's get was not accessed after set.", await response.Content.ReadAsStringAsync());
|
Assert.Equal("No model validation for developer, even though developer.Name is empty.", await response.Content.ReadAsStringAsync());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public async Task CheckIfExcludedField_IsValidatedForNonBodyBoundModels()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var server = TestServer.Create(_services, _app);
|
||||||
|
var client = server.CreateClient();
|
||||||
|
var content = new StringContent("{\"Alias\":\"xyz\"}", Encoding.UTF8, "application/json");
|
||||||
|
|
||||||
|
// Act
|
||||||
|
var response = await client.PostAsync("http://localhost/Validation/GetDeveloperAlias", content);
|
||||||
|
|
||||||
|
//Assert
|
||||||
|
Assert.Equal(HttpStatusCode.OK, response.StatusCode);
|
||||||
|
Assert.Equal("The Name field is required.", await response.Content.ReadAsStringAsync());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -25,7 +25,7 @@
|
||||||
"UrlHelperWebSite": "1.0.0",
|
"UrlHelperWebSite": "1.0.0",
|
||||||
"ValueProvidersSite": "1.0.0",
|
"ValueProvidersSite": "1.0.0",
|
||||||
"VersioningWebSite": "1.0.0",
|
"VersioningWebSite": "1.0.0",
|
||||||
"ViewComponentWebSite": "1.0.0",
|
"ViewComponentWebSite": "1.0.0",
|
||||||
"XmlSerializerWebSite": "1.0.0",
|
"XmlSerializerWebSite": "1.0.0",
|
||||||
"WebApiCompatShimWebSite": "1.0.0",
|
"WebApiCompatShimWebSite": "1.0.0",
|
||||||
"Microsoft.AspNet.TestHost": "1.0.0-*",
|
"Microsoft.AspNet.TestHost": "1.0.0-*",
|
||||||
|
|
|
||||||
|
|
@ -5,7 +5,10 @@
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.ComponentModel.DataAnnotations;
|
using System.ComponentModel.DataAnnotations;
|
||||||
|
using System.IO;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
using System.Xml;
|
||||||
|
using System.Xml.Linq;
|
||||||
using Microsoft.AspNet.Testing;
|
using Microsoft.AspNet.Testing;
|
||||||
using Moq;
|
using Moq;
|
||||||
using Xunit;
|
using Xunit;
|
||||||
|
|
@ -259,11 +262,6 @@ namespace Microsoft.AspNet.Mvc.ModelBinding
|
||||||
typeof(Uri),
|
typeof(Uri),
|
||||||
new List<Type>() { typeof(Uri) }
|
new List<Type>() { typeof(Uri) }
|
||||||
};
|
};
|
||||||
yield return new object[] {
|
|
||||||
new DerivedUri("/api/values", UriKind.Relative),
|
|
||||||
typeof(Uri),
|
|
||||||
new List<Type>() { typeof(Uri) }
|
|
||||||
};
|
|
||||||
yield return new object[] { new Dictionary<string, Uri> {
|
yield return new object[] { new Dictionary<string, Uri> {
|
||||||
{ "values", new Uri("/api/values", UriKind.Relative) },
|
{ "values", new Uri("/api/values", UriKind.Relative) },
|
||||||
{ "hello", new Uri("/api/hello", UriKind.Relative) }
|
{ "hello", new Uri("/api/hello", UriKind.Relative) }
|
||||||
|
|
@ -355,17 +353,16 @@ namespace Microsoft.AspNet.Mvc.ModelBinding
|
||||||
new DataMemberModelValidatorProvider()
|
new DataMemberModelValidatorProvider()
|
||||||
});
|
});
|
||||||
var modelMetadataProvider = new EmptyModelMetadataProvider();
|
var modelMetadataProvider = new EmptyModelMetadataProvider();
|
||||||
List<ExcludeFromValidationDelegate> excludedValidationTypesPredicate =
|
var excludedValidationTypesPredicate =
|
||||||
new List<ExcludeFromValidationDelegate>();
|
new List<IExcludeTypeValidationFilter>();
|
||||||
if (excludedTypes != null)
|
if (excludedTypes != null)
|
||||||
{
|
{
|
||||||
excludedValidationTypesPredicate = new List<ExcludeFromValidationDelegate>()
|
var mockExcludeTypeFilter = new Mock<IExcludeTypeValidationFilter>();
|
||||||
{
|
mockExcludeTypeFilter.Setup(o => o.IsTypeExcluded(It.IsAny<Type>()))
|
||||||
(excludedType) =>
|
.Returns<Type>(excludedType =>
|
||||||
{
|
excludedTypes.Any(t => t.IsAssignableFrom(excludedType)));
|
||||||
return excludedTypes.Any(t => t.IsAssignableFrom(excludedType));
|
|
||||||
}
|
excludedValidationTypesPredicate.Add(mockExcludeTypeFilter.Object);
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return new ModelValidationContext(
|
return new ModelValidationContext(
|
||||||
|
|
@ -379,7 +376,7 @@ namespace Microsoft.AspNet.Mvc.ModelBinding
|
||||||
modelType: type,
|
modelType: type,
|
||||||
propertyName: null),
|
propertyName: null),
|
||||||
containerMetadata: null,
|
containerMetadata: null,
|
||||||
excludeFromValidationDelegate: excludedValidationTypesPredicate);
|
excludeFromValidationFilters: excludedValidationTypesPredicate);
|
||||||
}
|
}
|
||||||
|
|
||||||
public class Person
|
public class Person
|
||||||
|
|
@ -482,16 +479,6 @@ namespace Microsoft.AspNet.Mvc.ModelBinding
|
||||||
|
|
||||||
public Team Test { get; set; }
|
public Team Test { get; set; }
|
||||||
}
|
}
|
||||||
|
|
||||||
public class DerivedUri : Uri
|
|
||||||
{
|
|
||||||
public DerivedUri(string uri, UriKind kind) :base(uri, kind)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
[Required]
|
|
||||||
public string UriPurpose { get; set; }
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
@ -1,8 +1,12 @@
|
||||||
// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved.
|
// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved.
|
||||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||||
|
|
||||||
|
using System;
|
||||||
|
using System.Xml;
|
||||||
|
using System.Xml.Linq;
|
||||||
using Microsoft.AspNet.Mvc.ModelBinding;
|
using Microsoft.AspNet.Mvc.ModelBinding;
|
||||||
using Microsoft.AspNet.Mvc.Razor;
|
using Microsoft.AspNet.Mvc.Razor;
|
||||||
|
using Newtonsoft.Json.Linq;
|
||||||
using Xunit;
|
using Xunit;
|
||||||
|
|
||||||
namespace Microsoft.AspNet.Mvc
|
namespace Microsoft.AspNet.Mvc
|
||||||
|
|
@ -113,5 +117,36 @@ namespace Microsoft.AspNet.Mvc
|
||||||
Assert.IsType<DataAnnotationsModelValidatorProvider>(mvcOptions.ModelValidatorProviders[0].Instance);
|
Assert.IsType<DataAnnotationsModelValidatorProvider>(mvcOptions.ModelValidatorProviders[0].Instance);
|
||||||
Assert.IsType<DataMemberModelValidatorProvider>(mvcOptions.ModelValidatorProviders[1].Instance);
|
Assert.IsType<DataMemberModelValidatorProvider>(mvcOptions.ModelValidatorProviders[1].Instance);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void Setup_SetsUpExcludeFromValidationDelegates()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var mvcOptions = new MvcOptions();
|
||||||
|
var setup = new MvcOptionsSetup();
|
||||||
|
|
||||||
|
// Act
|
||||||
|
setup.Configure(mvcOptions);
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
Assert.Equal(5, mvcOptions.ValidationExcludeFilters.Count);
|
||||||
|
|
||||||
|
// Verify if the delegates registered by default exclude the given types.
|
||||||
|
Assert.Equal(typeof(DefaultTypeBasedExcludeFilter), mvcOptions.ValidationExcludeFilters[0].OptionType);
|
||||||
|
var instance = Assert.IsType<DefaultTypeBasedExcludeFilter>(mvcOptions.ValidationExcludeFilters[0].Instance);
|
||||||
|
Assert.Equal(instance.ExcludedType, typeof(XObject));
|
||||||
|
Assert.Equal(typeof(DefaultTypeBasedExcludeFilter), mvcOptions.ValidationExcludeFilters[1].OptionType);
|
||||||
|
var instance2 = Assert.IsType<DefaultTypeBasedExcludeFilter>(mvcOptions.ValidationExcludeFilters[1].Instance);
|
||||||
|
Assert.Equal(instance2.ExcludedType, typeof(Type));
|
||||||
|
Assert.Equal(typeof(DefaultTypeBasedExcludeFilter), mvcOptions.ValidationExcludeFilters[2].OptionType);
|
||||||
|
var instance3 = Assert.IsType<DefaultTypeBasedExcludeFilter>(mvcOptions.ValidationExcludeFilters[2].Instance);
|
||||||
|
Assert.Equal(instance3.ExcludedType, typeof(byte[]));
|
||||||
|
Assert.Equal(typeof(DefaultTypeBasedExcludeFilter), mvcOptions.ValidationExcludeFilters[3].OptionType);
|
||||||
|
var instance4 = Assert.IsType<DefaultTypeBasedExcludeFilter>(mvcOptions.ValidationExcludeFilters[3].Instance);
|
||||||
|
Assert.Equal(instance4.ExcludedType, typeof(JToken));
|
||||||
|
Assert.Equal(typeof(DefaultTypeNameBasedExcludeFilter), mvcOptions.ValidationExcludeFilters[4].OptionType);
|
||||||
|
var instance5 = Assert.IsType<DefaultTypeNameBasedExcludeFilter>(mvcOptions.ValidationExcludeFilters[4].Instance);
|
||||||
|
Assert.Equal(instance5.ExcludedTypeName, "System.Xml.XmlNode");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -35,6 +35,7 @@
|
||||||
</div>
|
</div>
|
||||||
}
|
}
|
||||||
</section>
|
</section>
|
||||||
|
</div>
|
||||||
|
|
||||||
@using (Html.BeginForm("UseFacebookLogin", "Account", FormMethod.Post, new { @class = "form-horizontal", role = "form" }))
|
@using (Html.BeginForm("UseFacebookLogin", "Account", FormMethod.Post, new { @class = "form-horizontal", role = "form" }))
|
||||||
{
|
{
|
||||||
|
|
@ -60,4 +61,4 @@
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
}
|
}
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
|
|
@ -23,16 +23,36 @@ namespace FormatterWebSite
|
||||||
}
|
}
|
||||||
|
|
||||||
[HttpPost]
|
[HttpPost]
|
||||||
public string GetDeveloperName([FromBody]Developer developer)
|
public string GetDeveloperName([FromBody] Developer developer)
|
||||||
{
|
{
|
||||||
|
// Developer is excluded in startup, hence the value should never be passed.
|
||||||
if (ModelState.IsValid)
|
if (ModelState.IsValid)
|
||||||
{
|
{
|
||||||
return "Developer's get was not accessed after set.";
|
if (string.IsNullOrEmpty(developer.Name))
|
||||||
|
{
|
||||||
|
return "No model validation for developer, even though developer.Name is empty.";
|
||||||
|
}
|
||||||
|
|
||||||
|
return developer.Name;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
throw new InvalidOperationException();
|
throw new InvalidOperationException();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[HttpPost]
|
||||||
|
public string GetDeveloperAlias(Developer developer)
|
||||||
|
{
|
||||||
|
// Since validation exclusion is currently only effective in case of body bound models.
|
||||||
|
if (ModelState.IsValid)
|
||||||
|
{
|
||||||
|
return developer.Alias;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return ModelState["Name"].Errors[0].ErrorMessage;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -8,24 +8,9 @@ namespace FormatterWebSite
|
||||||
{
|
{
|
||||||
public class Developer
|
public class Developer
|
||||||
{
|
{
|
||||||
private string _name;
|
|
||||||
|
|
||||||
[Required]
|
[Required]
|
||||||
public string NameThatThrowsOnGet
|
public string Name { get; set; }
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
|
||||||
if (_name == "RandomString")
|
|
||||||
{
|
|
||||||
throw new InvalidOperationException();
|
|
||||||
}
|
|
||||||
|
|
||||||
return _name;
|
public string Alias { get; set; }
|
||||||
}
|
|
||||||
set
|
|
||||||
{
|
|
||||||
_name = value;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -22,7 +22,7 @@ namespace FormatterWebSite
|
||||||
|
|
||||||
services.Configure<MvcOptions>(options =>
|
services.Configure<MvcOptions>(options =>
|
||||||
{
|
{
|
||||||
options.ExcludeFromValidationDelegates.Add(typeof(Developer));
|
options.ValidationExcludeFilters.Add(typeof(Developer));
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue