Updates to the extensibility for validator providers
This change removes reflection from validator providers, and instead relies on cached metadata in in the modelmetadata. In general this means that our MVPs don't need to cache anything, they just look at the metadata and create what they need. In the case of data-annotations, we update the model details provider to add validation attributes to the modelmetadata. This would allow someone to replace the DataAnnotationsValidatorProvider, but still use the metadata in these attributes. The change to the IModelValidatorProvider api (to use a context) is intended to minimize allocations. Currently each validator provider needs to return a list so you end up with N+1 lists (N validators + a final list to compine them all). This change will let us just create the final list (and a small context object). This is a very very high traffic API so it seemed worth doing. There's also some general massaging of namespaces and file locations.
This commit is contained in:
parent
1ba4700339
commit
f5e7a69693
|
|
@ -10,6 +10,7 @@ using System.Threading.Tasks;
|
|||
using Microsoft.AspNet.Http;
|
||||
using Microsoft.AspNet.Mvc.Core;
|
||||
using Microsoft.AspNet.Mvc.ModelBinding;
|
||||
using Microsoft.AspNet.Mvc.ModelBinding.Validation;
|
||||
using Microsoft.AspNet.Mvc.Rendering;
|
||||
using Microsoft.AspNet.Routing;
|
||||
using Microsoft.Framework.Internal;
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@ using System.Collections.Generic;
|
|||
using System.Diagnostics;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.AspNet.Mvc.ModelBinding;
|
||||
using Microsoft.Framework.DependencyInjection;
|
||||
using Microsoft.AspNet.Mvc.ModelBinding.Validation;
|
||||
using Microsoft.Framework.Internal;
|
||||
|
||||
namespace Microsoft.AspNet.Mvc.Core
|
||||
|
|
|
|||
|
|
@ -1,11 +1,10 @@
|
|||
// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Microsoft.AspNet.Mvc.ModelBinding;
|
||||
using Microsoft.Framework.DependencyInjection;
|
||||
using Microsoft.AspNet.Mvc.ModelBinding.Validation;
|
||||
using Microsoft.Framework.Internal;
|
||||
|
||||
namespace Microsoft.AspNet.Mvc.Core
|
||||
|
|
|
|||
|
|
@ -9,6 +9,7 @@ using System.Threading.Tasks;
|
|||
using Microsoft.AspNet.Mvc.Core;
|
||||
using Microsoft.AspNet.Mvc.ModelBinding;
|
||||
using Microsoft.AspNet.Mvc.ModelBinding.Metadata;
|
||||
using Microsoft.AspNet.Mvc.ModelBinding.Validation;
|
||||
using Microsoft.Framework.OptionsModel;
|
||||
|
||||
namespace Microsoft.AspNet.Mvc
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@
|
|||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using Microsoft.AspNet.Mvc.ModelBinding;
|
||||
using Microsoft.AspNet.Mvc.ModelBinding.Validation;
|
||||
using Microsoft.Framework.OptionsModel;
|
||||
|
||||
namespace Microsoft.AspNet.Mvc.OptionDescriptors
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@ using System.Linq;
|
|||
using System.Runtime.ExceptionServices;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.AspNet.Mvc.ModelBinding;
|
||||
using Microsoft.Framework.DependencyInjection;
|
||||
using Microsoft.AspNet.Mvc.ModelBinding.Validation;
|
||||
using Microsoft.Framework.Internal;
|
||||
|
||||
namespace Microsoft.AspNet.Mvc.Core
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@
|
|||
|
||||
using System.Collections.Generic;
|
||||
using Microsoft.AspNet.Mvc.ModelBinding;
|
||||
using Microsoft.AspNet.Mvc.ModelBinding.Validation;
|
||||
|
||||
namespace Microsoft.AspNet.Mvc
|
||||
{
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
// 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.Mvc.ModelBinding.Validation;
|
||||
using Microsoft.Framework.Internal;
|
||||
|
||||
namespace Microsoft.AspNet.Mvc
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
// 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.Mvc.ModelBinding.Validation;
|
||||
using Microsoft.Framework.Internal;
|
||||
|
||||
namespace Microsoft.AspNet.Mvc
|
||||
|
|
|
|||
|
|
@ -1,8 +1,7 @@
|
|||
// 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.Mvc.ModelBinding.Validation;
|
||||
|
||||
namespace Microsoft.AspNet.Mvc.Internal
|
||||
{
|
||||
|
|
|
|||
|
|
@ -6,6 +6,9 @@ using System.Linq;
|
|||
using System.Reflection;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.AspNet.Mvc.Core;
|
||||
using Microsoft.AspNet.Mvc.ModelBinding;
|
||||
using Microsoft.AspNet.Mvc.ModelBinding.Validation;
|
||||
using Microsoft.Framework.DependencyInjection;
|
||||
using Microsoft.Framework.Internal;
|
||||
|
||||
namespace Microsoft.AspNet.Mvc.ModelBinding
|
||||
|
|
|
|||
|
|
@ -84,7 +84,7 @@ namespace Microsoft.AspNet.Mvc
|
|||
|
||||
/// <summary>
|
||||
/// Gets a list of <see cref="ExcludeValidationDescriptor"/> which are used to construct a list
|
||||
/// of exclude filters by <see cref="IValidationExcludeFiltersProvider"/>.
|
||||
/// of exclude filters by <see cref="ModelBinding.Validation.IValidationExcludeFiltersProvider"/>.
|
||||
/// </summary>
|
||||
public IList<ExcludeValidationDescriptor> ValidationExcludeFilters { get; }
|
||||
|
||||
|
|
@ -115,7 +115,7 @@ namespace Microsoft.AspNet.Mvc
|
|||
|
||||
/// <summary>
|
||||
/// Gets a list of the <see cref="ModelValidatorProviderDescriptor" />s used by
|
||||
/// <see cref="ModelBinding.CompositeModelValidatorProvider"/>.
|
||||
/// <see cref="ModelBinding.Validation.CompositeModelValidatorProvider"/>.
|
||||
/// </summary>
|
||||
public IList<ModelValidatorProviderDescriptor> ModelValidatorProviders { get; }
|
||||
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@
|
|||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using Microsoft.AspNet.Mvc.ModelBinding;
|
||||
using Microsoft.AspNet.Mvc.ModelBinding.Validation;
|
||||
using Microsoft.Framework.OptionsModel;
|
||||
|
||||
namespace Microsoft.AspNet.Mvc.OptionDescriptors
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
// 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.Mvc.ModelBinding.Validation;
|
||||
using Microsoft.Framework.Internal;
|
||||
|
||||
namespace Microsoft.AspNet.Mvc.OptionDescriptors
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
// 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.Mvc.ModelBinding.Validation;
|
||||
using Microsoft.Framework.Internal;
|
||||
|
||||
namespace Microsoft.AspNet.Mvc.OptionDescriptors
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@
|
|||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using Microsoft.AspNet.Mvc.ModelBinding;
|
||||
using Microsoft.AspNet.Mvc.ModelBinding.Validation;
|
||||
using Microsoft.AspNet.Mvc.OptionDescriptors;
|
||||
using Microsoft.Framework.Internal;
|
||||
|
||||
|
|
@ -57,7 +57,7 @@ namespace Microsoft.AspNet.Mvc
|
|||
/// Adds an <see cref="IModelValidatorProvider"/> to <paramref name="descriptors"/>.
|
||||
/// </summary>
|
||||
/// <param name="descriptors">A list of <see cref="ModelValidatorProviderDescriptor"/>.</param>
|
||||
/// <param name="modelValidatorProvider">An <see cref="IModelBinder"/> instance.</param>
|
||||
/// <param name="modelValidatorProvider">An <see cref="IModelValidatorProvider"/> instance.</param>
|
||||
/// <returns>A <see cref="ModelValidatorProviderDescriptor"/> representing the added instance.</returns>
|
||||
public static ModelValidatorProviderDescriptor Add(
|
||||
[NotNull] this IList<ModelValidatorProviderDescriptor> descriptors,
|
||||
|
|
@ -75,7 +75,7 @@ namespace Microsoft.AspNet.Mvc
|
|||
/// <param name="descriptors">A list of <see cref="ModelValidatorProviderDescriptor"/>.</param>
|
||||
/// <param name="index">The zero-based index at which <paramref name="modelValidatorProvider"/>
|
||||
/// should be inserted.</param>
|
||||
/// <param name="modelValidatorProvider">An <see cref="IModelBinder"/> instance.</param>
|
||||
/// <param name="modelValidatorProvider">An <see cref="IModelValidatorProvider"/> instance.</param>
|
||||
/// <returns>A <see cref="ModelValidatorProviderDescriptor"/> representing the added instance.</returns>
|
||||
public static ModelValidatorProviderDescriptor Insert(
|
||||
[NotNull] this IList<ModelValidatorProviderDescriptor> descriptors,
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@
|
|||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using Microsoft.AspNet.Mvc.ModelBinding;
|
||||
using Microsoft.AspNet.Mvc.ModelBinding.Validation;
|
||||
using Microsoft.AspNet.Mvc.OptionDescriptors;
|
||||
|
||||
namespace Microsoft.AspNet.Mvc
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@
|
|||
|
||||
using System.Collections.Generic;
|
||||
using Microsoft.AspNet.Mvc.ModelBinding;
|
||||
using Microsoft.AspNet.Mvc.ModelBinding.Validation;
|
||||
|
||||
namespace Microsoft.AspNet.Mvc
|
||||
{
|
||||
|
|
|
|||
|
|
@ -12,6 +12,7 @@ using System.Threading.Tasks;
|
|||
using Microsoft.AspNet.Http;
|
||||
using Microsoft.AspNet.Mvc.Core;
|
||||
using Microsoft.AspNet.Mvc.ModelBinding;
|
||||
using Microsoft.AspNet.Mvc.ModelBinding.Validation;
|
||||
using Microsoft.Framework.Internal;
|
||||
|
||||
namespace Microsoft.AspNet.Mvc
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@ using System.Globalization;
|
|||
using System.Linq;
|
||||
using Microsoft.AspNet.Mvc.Core;
|
||||
using Microsoft.AspNet.Mvc.Internal;
|
||||
using Microsoft.AspNet.Mvc.ModelBinding;
|
||||
using Microsoft.AspNet.Mvc.ModelBinding.Validation;
|
||||
using Microsoft.AspNet.Routing;
|
||||
using Microsoft.Framework.DependencyInjection;
|
||||
using Microsoft.Framework.Internal;
|
||||
|
|
|
|||
|
|
@ -10,8 +10,8 @@ using System.Linq;
|
|||
using System.Text;
|
||||
using Microsoft.AspNet.Mvc.Core;
|
||||
using Microsoft.AspNet.Mvc.ModelBinding;
|
||||
using Microsoft.AspNet.Mvc.ModelBinding.Validation;
|
||||
using Microsoft.AspNet.Mvc.Rendering.Expressions;
|
||||
using Microsoft.Framework.DependencyInjection;
|
||||
using Microsoft.Framework.Internal;
|
||||
using Microsoft.Framework.WebEncoders;
|
||||
|
||||
|
|
@ -746,9 +746,14 @@ namespace Microsoft.AspNet.Mvc.Rendering
|
|||
modelExplorer.Metadata,
|
||||
_metadataProvider,
|
||||
viewContext.HttpContext.RequestServices);
|
||||
|
||||
var validatorProviderContext = new ModelValidatorProviderContext(modelExplorer.Metadata);
|
||||
validatorProvider.GetValidators(validatorProviderContext);
|
||||
|
||||
return validatorProvider
|
||||
.GetValidators(modelExplorer.Metadata)
|
||||
var validators = validatorProviderContext.Validators;
|
||||
|
||||
return
|
||||
validators
|
||||
.OfType<IClientModelValidator>()
|
||||
.SelectMany(v => v.GetClientValidationRules(validationContext));
|
||||
}
|
||||
|
|
|
|||
|
|
@ -9,6 +9,7 @@ using System.Text;
|
|||
using System.Threading.Tasks;
|
||||
using Microsoft.AspNet.Mvc.Core;
|
||||
using Microsoft.AspNet.Mvc.ModelBinding;
|
||||
using Microsoft.AspNet.Mvc.ModelBinding.Validation;
|
||||
using Microsoft.AspNet.Mvc.Rendering.Expressions;
|
||||
using Microsoft.Framework.Internal;
|
||||
using Microsoft.Framework.WebEncoders;
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@
|
|||
|
||||
using System.Collections.Generic;
|
||||
using Microsoft.AspNet.Mvc.ModelBinding;
|
||||
using Microsoft.AspNet.Mvc.ModelBinding.Validation;
|
||||
using Microsoft.Framework.Internal;
|
||||
|
||||
namespace Microsoft.AspNet.Mvc.Rendering
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@
|
|||
using System.Collections.Generic;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.AspNet.Mvc.ModelBinding;
|
||||
using Microsoft.AspNet.Mvc.ModelBinding.Validation;
|
||||
using Microsoft.Framework.Internal;
|
||||
using Microsoft.Framework.WebEncoders;
|
||||
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@ using System;
|
|||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Microsoft.AspNet.Mvc.Core;
|
||||
using Microsoft.AspNet.Mvc.ModelBinding;
|
||||
using Microsoft.AspNet.Mvc.ModelBinding.Validation;
|
||||
using Microsoft.Framework.Internal;
|
||||
|
||||
namespace Microsoft.AspNet.Mvc.Rendering
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@ using System.Reflection;
|
|||
using System.Threading.Tasks;
|
||||
using Microsoft.AspNet.Mvc.ModelBinding.Internal;
|
||||
using Microsoft.AspNet.Mvc.ModelBinding.Metadata;
|
||||
using Microsoft.Framework.DependencyInjection;
|
||||
using Microsoft.AspNet.Mvc.ModelBinding.Validation;
|
||||
|
||||
namespace Microsoft.AspNet.Mvc.ModelBinding
|
||||
{
|
||||
|
|
@ -326,10 +326,11 @@ namespace Microsoft.AspNet.Mvc.ModelBinding
|
|||
continue;
|
||||
}
|
||||
|
||||
var requiredValidator = bindingContext.OperationBindingContext
|
||||
.ValidatorProvider
|
||||
.GetValidators(propertyMetadata)
|
||||
.FirstOrDefault(v => v != null && v.IsRequired);
|
||||
var validatorProviderContext = new ModelValidatorProviderContext(propertyMetadata);
|
||||
bindingContext.OperationBindingContext.ValidatorProvider.GetValidators(validatorProviderContext);
|
||||
|
||||
var requiredValidator = validatorProviderContext.Validators
|
||||
.FirstOrDefault(v => v != null && v.IsRequired);
|
||||
if (requiredValidator != null)
|
||||
{
|
||||
validationInfo.RequiredValidators[propertyName] = requiredValidator;
|
||||
|
|
|
|||
|
|
@ -1,7 +1,6 @@
|
|||
// 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 System.ComponentModel.DataAnnotations;
|
||||
using System.Linq;
|
||||
using Microsoft.Framework.Internal;
|
||||
|
|
@ -12,9 +11,10 @@ namespace Microsoft.AspNet.Mvc.ModelBinding.Metadata
|
|||
/// An implementation of <see cref="IBindingMetadataProvider"/> and <see cref="IDisplayMetadataProvider"/> for
|
||||
/// the System.ComponentModel.DataAnnotations attribute classes.
|
||||
/// </summary>
|
||||
public class DataAnnotationsMetadataDetailsProvider :
|
||||
public class DataAnnotationsMetadataProvider :
|
||||
IBindingMetadataProvider,
|
||||
IDisplayMetadataProvider
|
||||
IDisplayMetadataProvider,
|
||||
IValidationMetadataProvider
|
||||
{
|
||||
/// <inheritdoc />
|
||||
public void GetBindingMetadata([NotNull] BindingMetadataProviderContext context)
|
||||
|
|
@ -167,5 +167,14 @@ namespace Microsoft.AspNet.Mvc.ModelBinding.Metadata
|
|||
displayMetadata.TemplateHint = "HiddenInput";
|
||||
}
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public void GetValidationMetadata([NotNull] ValidationMetadataProviderContext context)
|
||||
{
|
||||
foreach (var attribute in context.Attributes.OfType<ValidationAttribute>())
|
||||
{
|
||||
context.ValidationMetadata.ValiatorMetadata.Add(attribute);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -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.Linq;
|
||||
using System.Reflection;
|
||||
using System.Runtime.Serialization;
|
||||
using Microsoft.Framework.Internal;
|
||||
|
||||
namespace Microsoft.AspNet.Mvc.ModelBinding.Metadata
|
||||
{
|
||||
/// <summary>
|
||||
/// An <see cref="IBindingMetadataProvider"/> for <see cref="DataMemberAttribute.IsRequired"/>.
|
||||
/// </summary>
|
||||
public class DataMemberRequiredValidationMetadataProvider : IBindingMetadataProvider
|
||||
{
|
||||
/// <inheritdoc />
|
||||
public void GetBindingMetadata([NotNull] BindingMetadataProviderContext context)
|
||||
{
|
||||
// Types cannot be required; only properties can
|
||||
if (context.Key.MetadataKind != ModelMetadataKind.Property)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
var dataMemberAttribute = context
|
||||
.Attributes
|
||||
.OfType<DataMemberAttribute>()
|
||||
.FirstOrDefault();
|
||||
if (dataMemberAttribute == null || !dataMemberAttribute.IsRequired)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// isDataContract == true iff the container type has at least one DataContractAttribute
|
||||
var containerType = context.Key.ContainerType.GetTypeInfo();
|
||||
var isDataContract = containerType.GetCustomAttribute<DataContractAttribute>() != null;
|
||||
if (isDataContract)
|
||||
{
|
||||
// We don't need to add a validator, just to set IsRequired = true. The validation
|
||||
// system will do the right thing.
|
||||
context.BindingMetadata.IsRequired = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -22,6 +22,7 @@ namespace Microsoft.AspNet.Mvc.ModelBinding.Metadata
|
|||
private bool? _isReadOnly;
|
||||
private bool? _isRequired;
|
||||
private ModelPropertyCollection _properties;
|
||||
private ReadOnlyCollection<object> _validatorMetadata;
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new <see cref="DefaultModelMetadata"/>.
|
||||
|
|
@ -356,5 +357,19 @@ namespace Microsoft.AspNet.Mvc.ModelBinding.Metadata
|
|||
return DisplayMetadata.TemplateHint;
|
||||
}
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public override IReadOnlyList<object> ValidatorMetadata
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_validatorMetadata == null)
|
||||
{
|
||||
_validatorMetadata = new ReadOnlyCollection<object>(ValidationMetadata.ValiatorMetadata);
|
||||
}
|
||||
|
||||
return _validatorMetadata;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -88,10 +88,39 @@ namespace Microsoft.AspNet.Mvc.ModelBinding.Metadata
|
|||
{
|
||||
var propertyHelpers = PropertyHelper.GetProperties(key.ModelType);
|
||||
|
||||
var propertyEntries = new DefaultMetadataDetailsCache[propertyHelpers.Length];
|
||||
var propertyEntries = new List<DefaultMetadataDetailsCache>(propertyHelpers.Length);
|
||||
for (var i = 0; i < propertyHelpers.Length; i++)
|
||||
{
|
||||
var propertyHelper = propertyHelpers[i];
|
||||
if (propertyHelper.Property.DeclaringType != key.ModelType)
|
||||
{
|
||||
// If this property was declared on a base type then look for the definition closest to the
|
||||
// the model type to see if we should include it.
|
||||
var ignoreProperty = false;
|
||||
|
||||
// Walk up the hierarchy until we find the type that actally declares this
|
||||
// PropertyInfo.
|
||||
var currentType = key.ModelType.GetTypeInfo();
|
||||
while (currentType != propertyHelper.Property.DeclaringType.GetTypeInfo())
|
||||
{
|
||||
// We've found a 'more proximal' public definition
|
||||
var declaredProperty = currentType.GetDeclaredProperty(propertyHelper.Name);
|
||||
if (declaredProperty != null)
|
||||
{
|
||||
ignoreProperty = true;
|
||||
break;
|
||||
}
|
||||
|
||||
currentType = currentType.BaseType.GetTypeInfo();
|
||||
}
|
||||
|
||||
if (ignoreProperty)
|
||||
{
|
||||
// There's a better definition, ignore this.
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
var propertyKey = ModelMetadataIdentity.ForProperty(
|
||||
propertyHelper.Property.PropertyType,
|
||||
propertyHelper.Name,
|
||||
|
|
@ -101,19 +130,21 @@ namespace Microsoft.AspNet.Mvc.ModelBinding.Metadata
|
|||
key.ModelType,
|
||||
propertyHelper.Property));
|
||||
|
||||
propertyEntries[i] = new DefaultMetadataDetailsCache(propertyKey, attributes);
|
||||
var propertyEntry = new DefaultMetadataDetailsCache(propertyKey, attributes);
|
||||
if (propertyHelper.Property.CanRead && propertyHelper.Property.GetMethod?.IsPrivate == true)
|
||||
{
|
||||
propertyEntries[i].PropertyAccessor = PropertyHelper.MakeFastPropertyGetter(propertyHelper.Property);
|
||||
propertyEntry.PropertyAccessor = PropertyHelper.MakeFastPropertyGetter(propertyHelper.Property);
|
||||
}
|
||||
|
||||
if (propertyHelper.Property.CanWrite && propertyHelper.Property.SetMethod?.IsPrivate == true)
|
||||
{
|
||||
propertyEntries[i].PropertySetter = PropertyHelper.MakeFastPropertySetter(propertyHelper.Property);
|
||||
propertyEntry.PropertySetter = PropertyHelper.MakeFastPropertySetter(propertyHelper.Property);
|
||||
}
|
||||
|
||||
propertyEntries.Add(propertyEntry);
|
||||
}
|
||||
|
||||
return propertyEntries;
|
||||
return propertyEntries.ToArray();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
|
|
|||
|
|
@ -0,0 +1,24 @@
|
|||
// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System.Linq;
|
||||
using Microsoft.AspNet.Mvc.ModelBinding.Validation;
|
||||
using Microsoft.Framework.Internal;
|
||||
|
||||
namespace Microsoft.AspNet.Mvc.ModelBinding.Metadata
|
||||
{
|
||||
/// <summary>
|
||||
/// A default implementation of <see cref="IValidationMetadataProvider"/>.
|
||||
/// </summary>
|
||||
public class DefaultValidationMetadataProvider : IValidationMetadataProvider
|
||||
{
|
||||
/// <inheritdoc />
|
||||
public void GetValidationMetadata([NotNull] ValidationMetadataProviderContext context)
|
||||
{
|
||||
foreach (var attribute in context.Attributes.OfType<IModelValidator>())
|
||||
{
|
||||
context.ValidationMetadata.ValiatorMetadata.Add(attribute);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -6,7 +6,7 @@ namespace Microsoft.AspNet.Mvc.ModelBinding.Metadata
|
|||
/// <summary>
|
||||
/// Marker interface for a provider of metadata details about model objects. Implementations should
|
||||
/// implement one or more of <see cref="IBindingMetadataProvider"/>, <see cref="IDisplayMetadataProvider"/>,
|
||||
/// and <see cref="IModelValidatorProvider"/>.
|
||||
/// and <see cref="IValidationMetadataProvider"/>.
|
||||
/// </summary>
|
||||
public interface IMetadataDetailsProvider
|
||||
{
|
||||
|
|
|
|||
|
|
@ -1,6 +1,8 @@
|
|||
// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Microsoft.AspNet.Mvc.ModelBinding.Metadata
|
||||
{
|
||||
/// <summary>
|
||||
|
|
@ -8,5 +10,13 @@ namespace Microsoft.AspNet.Mvc.ModelBinding.Metadata
|
|||
/// </summary>
|
||||
public class ValidationMetadata
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets a list of metadata items for validators.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// <see cref="IValidationMetadataProvider"/> implementations should store metadata items
|
||||
/// in this list, to be consumed later by an <see cref="Validation.IModelValidatorProvider"/>.
|
||||
/// </remarks>
|
||||
public IList<object> ValiatorMetadata { get; } = new List<object>();
|
||||
}
|
||||
}
|
||||
|
|
@ -199,6 +199,11 @@ namespace Microsoft.AspNet.Mvc.ModelBinding
|
|||
/// </summary>
|
||||
public abstract string TemplateHint { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets a collection of metadata items for validators.
|
||||
/// </summary>
|
||||
public abstract IReadOnlyList<object> ValidatorMetadata { get;}
|
||||
|
||||
/// <summary>
|
||||
/// Gets a value indicating whether <see cref="ModelType"/> is a simple type.
|
||||
/// </summary>
|
||||
|
|
|
|||
|
|
@ -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.Http;
|
||||
using Microsoft.AspNet.Mvc.ModelBinding.Validation;
|
||||
|
||||
namespace Microsoft.AspNet.Mvc.ModelBinding
|
||||
{
|
||||
|
|
|
|||
|
|
@ -1,54 +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 System.Linq;
|
||||
using System.Reflection;
|
||||
using Microsoft.Framework.Internal;
|
||||
|
||||
namespace Microsoft.AspNet.Mvc.ModelBinding
|
||||
{
|
||||
public abstract class AssociatedValidatorProvider : IModelValidatorProvider
|
||||
{
|
||||
public IEnumerable<IModelValidator> GetValidators([NotNull] ModelMetadata metadata)
|
||||
{
|
||||
if (metadata.ContainerType != null && !string.IsNullOrEmpty(metadata.PropertyName))
|
||||
{
|
||||
return GetValidatorsForProperty(metadata);
|
||||
}
|
||||
|
||||
return GetValidatorsForType(metadata);
|
||||
}
|
||||
|
||||
protected abstract IEnumerable<IModelValidator> GetValidators(ModelMetadata metadata,
|
||||
IEnumerable<object> attributes);
|
||||
|
||||
private IEnumerable<IModelValidator> GetValidatorsForProperty(ModelMetadata metadata)
|
||||
{
|
||||
var propertyName = metadata.PropertyName;
|
||||
var bindingFlags = BindingFlags.Public | BindingFlags.Instance | BindingFlags.IgnoreCase;
|
||||
var property = metadata.ContainerType
|
||||
.GetProperty(propertyName, bindingFlags);
|
||||
|
||||
if (property == null)
|
||||
{
|
||||
throw new ArgumentException(
|
||||
Resources.FormatCommon_PropertyNotFound(
|
||||
metadata.ContainerType.FullName,
|
||||
metadata.PropertyName),
|
||||
"metadata");
|
||||
}
|
||||
|
||||
var attributes = ModelAttributes.GetAttributesForProperty(metadata.ContainerType, property);
|
||||
return GetValidators(metadata, attributes);
|
||||
}
|
||||
|
||||
private IEnumerable<IModelValidator> GetValidatorsForType(ModelMetadata metadata)
|
||||
{
|
||||
var attributes = ModelAttributes.GetAttributesForType(metadata.ModelType);
|
||||
|
||||
return GetValidators(metadata, attributes);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -4,7 +4,7 @@
|
|||
using System;
|
||||
using Microsoft.Framework.Internal;
|
||||
|
||||
namespace Microsoft.AspNet.Mvc.ModelBinding
|
||||
namespace Microsoft.AspNet.Mvc.ModelBinding.Validation
|
||||
{
|
||||
public class ClientModelValidationContext
|
||||
{
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@ using System.ComponentModel.DataAnnotations;
|
|||
using System.Globalization;
|
||||
using Microsoft.Framework.Internal;
|
||||
|
||||
namespace Microsoft.AspNet.Mvc.ModelBinding
|
||||
namespace Microsoft.AspNet.Mvc.ModelBinding.Validation
|
||||
{
|
||||
public class CompareAttributeAdapter : DataAnnotationsModelValidator<CompareAttribute>
|
||||
{
|
||||
|
|
|
|||
|
|
@ -2,10 +2,9 @@
|
|||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Microsoft.Framework.Internal;
|
||||
|
||||
namespace Microsoft.AspNet.Mvc.ModelBinding
|
||||
namespace Microsoft.AspNet.Mvc.ModelBinding.Validation
|
||||
{
|
||||
/// <summary>
|
||||
/// Default implementation for <see cref="ICompositeModelValidatorProvider"/>.
|
||||
|
|
@ -25,9 +24,12 @@ namespace Microsoft.AspNet.Mvc.ModelBinding
|
|||
|
||||
public IReadOnlyList<IModelValidatorProvider> ValidatorProviders { get; }
|
||||
|
||||
public IEnumerable<IModelValidator> GetValidators(ModelMetadata metadata)
|
||||
public void GetValidators(ModelValidatorProviderContext context)
|
||||
{
|
||||
return ValidatorProviders.SelectMany(v => v.GetValidators(metadata));
|
||||
foreach (var validatorProvider in ValidatorProviders)
|
||||
{
|
||||
validatorProvider.GetValidators(context);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -7,7 +7,7 @@ using System.ComponentModel.DataAnnotations;
|
|||
using System.Linq;
|
||||
using Microsoft.Framework.Internal;
|
||||
|
||||
namespace Microsoft.AspNet.Mvc.ModelBinding
|
||||
namespace Microsoft.AspNet.Mvc.ModelBinding.Validation
|
||||
{
|
||||
public class DataAnnotationsModelValidator : IModelValidator, IClientModelValidator
|
||||
{
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@
|
|||
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
|
||||
namespace Microsoft.AspNet.Mvc.ModelBinding
|
||||
namespace Microsoft.AspNet.Mvc.ModelBinding.Validation
|
||||
{
|
||||
public class DataAnnotationsModelValidator<TAttribute> : DataAnnotationsModelValidator
|
||||
where TAttribute : ValidationAttribute
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@ using System.Collections.Generic;
|
|||
using System.ComponentModel.DataAnnotations;
|
||||
using System.Linq;
|
||||
|
||||
namespace Microsoft.AspNet.Mvc.ModelBinding
|
||||
namespace Microsoft.AspNet.Mvc.ModelBinding.Validation
|
||||
{
|
||||
/// <summary>
|
||||
/// An implementation of <see cref="IModelValidatorProvider"/> which providers validators
|
||||
|
|
@ -17,7 +17,7 @@ namespace Microsoft.AspNet.Mvc.ModelBinding
|
|||
/// <see cref="IClientModelValidator"/>. The logic to support <see cref="IClientModelValidator"/>
|
||||
/// is implemented in <see cref="DataAnnotationsModelValidator"/>.
|
||||
/// </summary>
|
||||
public class DataAnnotationsModelValidatorProvider : AssociatedValidatorProvider
|
||||
public class DataAnnotationsModelValidatorProvider : IModelValidatorProvider
|
||||
{
|
||||
// A factory for validators based on ValidationAttribute.
|
||||
internal delegate IModelValidator DataAnnotationsModelValidationFactory(ValidationAttribute attribute);
|
||||
|
|
@ -30,7 +30,6 @@ namespace Microsoft.AspNet.Mvc.ModelBinding
|
|||
private static readonly DataAnnotationsValidatableObjectAdapterFactory _defaultValidatableFactory =
|
||||
() => new ValidatableObjectAdapter();
|
||||
|
||||
private static bool _addImplicitRequiredAttributeForValueTypes = true;
|
||||
private readonly Dictionary<Type, DataAnnotationsModelValidationFactory> _attributeFactories =
|
||||
BuildAttributeFactoriesDictionary();
|
||||
|
||||
|
|
@ -42,35 +41,24 @@ namespace Microsoft.AspNet.Mvc.ModelBinding
|
|||
get { return _attributeFactories; }
|
||||
}
|
||||
|
||||
private static bool AddImplicitRequiredAttributeForValueTypes
|
||||
public void GetValidators(ModelValidatorProviderContext context)
|
||||
{
|
||||
get { return _addImplicitRequiredAttributeForValueTypes; }
|
||||
set { _addImplicitRequiredAttributeForValueTypes = value; }
|
||||
}
|
||||
|
||||
protected override IEnumerable<IModelValidator> GetValidators(ModelMetadata metadata,
|
||||
IEnumerable<object> attributes)
|
||||
{
|
||||
var results = new List<IModelValidator>();
|
||||
|
||||
// Produce a validator for each validation attribute we find
|
||||
foreach (var attribute in attributes.OfType<ValidationAttribute>())
|
||||
foreach (var attribute in context.ValidatorMetadata.OfType<ValidationAttribute>())
|
||||
{
|
||||
DataAnnotationsModelValidationFactory factory;
|
||||
if (!_attributeFactories.TryGetValue(attribute.GetType(), out factory))
|
||||
{
|
||||
factory = _defaultAttributeFactory;
|
||||
}
|
||||
results.Add(factory(attribute));
|
||||
|
||||
context.Validators.Add(factory(attribute));
|
||||
}
|
||||
|
||||
// Produce a validator if the type supports IValidatableObject
|
||||
if (typeof(IValidatableObject).IsAssignableFrom(metadata.ModelType))
|
||||
if (typeof(IValidatableObject).IsAssignableFrom(context.ModelMetadata.ModelType))
|
||||
{
|
||||
results.Add(_defaultValidatableFactory());
|
||||
context.Validators.Add(_defaultValidatableFactory());
|
||||
}
|
||||
|
||||
return results;
|
||||
}
|
||||
|
||||
private static Dictionary<Type, DataAnnotationsModelValidationFactory> BuildAttributeFactoriesDictionary()
|
||||
|
|
|
|||
|
|
@ -1,54 +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 System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Runtime.Serialization;
|
||||
|
||||
namespace Microsoft.AspNet.Mvc.ModelBinding
|
||||
{
|
||||
/// <summary>
|
||||
/// This <see cref="IModelValidatorProvider"/> provides a required ModelValidator for members marked
|
||||
/// as <c>[DataMember(IsRequired=true)]</c>.
|
||||
/// </summary>
|
||||
public class DataMemberModelValidatorProvider : AssociatedValidatorProvider
|
||||
{
|
||||
protected override IEnumerable<IModelValidator> GetValidators(ModelMetadata metadata,
|
||||
IEnumerable<object> attributes)
|
||||
{
|
||||
// Types cannot be required; only properties can
|
||||
if (metadata.ContainerType == null || string.IsNullOrEmpty(metadata.PropertyName))
|
||||
{
|
||||
return Enumerable.Empty<IModelValidator>();
|
||||
}
|
||||
|
||||
if (IsRequiredDataMember(metadata.ContainerType, attributes))
|
||||
{
|
||||
return new[] { new RequiredMemberModelValidator() };
|
||||
}
|
||||
|
||||
return Enumerable.Empty<IModelValidator>();
|
||||
}
|
||||
|
||||
internal static bool IsRequiredDataMember(Type containerType, IEnumerable<object> attributes)
|
||||
{
|
||||
var dataMemberAttribute = attributes.OfType<DataMemberAttribute>()
|
||||
.FirstOrDefault();
|
||||
if (dataMemberAttribute != null)
|
||||
{
|
||||
// isDataContract == true iff the container type has at least one DataContractAttribute
|
||||
var isDataContract = containerType.GetTypeInfo()
|
||||
.GetCustomAttributes()
|
||||
.OfType<DataContractAttribute>()
|
||||
.Any();
|
||||
if (isDataContract && dataMemberAttribute.IsRequired)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -6,7 +6,7 @@ using System.Collections.Generic;
|
|||
using System.ComponentModel.DataAnnotations;
|
||||
using Microsoft.Framework.Internal;
|
||||
|
||||
namespace Microsoft.AspNet.Mvc.ModelBinding
|
||||
namespace Microsoft.AspNet.Mvc.ModelBinding.Validation
|
||||
{
|
||||
/// <summary>
|
||||
/// A validation adapter that is used to map <see cref="DataTypeAttribute"/>'s to a single client side validation
|
||||
|
|
|
|||
|
|
@ -0,0 +1,28 @@
|
|||
// 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.
|
||||
|
||||
namespace Microsoft.AspNet.Mvc.ModelBinding.Validation
|
||||
{
|
||||
/// <summary>
|
||||
/// A default <see cref="IModelValidatorProvider"/>.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// The <see cref="DefaultModelValidatorProvider"/> provides validators from <see cref="IModelValidator"/>
|
||||
/// instances in <see cref="ModelMetadata.ValidatorMetadata"/>.
|
||||
/// </remarks>
|
||||
public class DefaultModelValidatorProvider : IModelValidatorProvider
|
||||
{
|
||||
/// <inheritdoc />
|
||||
public void GetValidators(ModelValidatorProviderContext context)
|
||||
{
|
||||
foreach (var metadata in context.ValidatorMetadata)
|
||||
{
|
||||
var validator = metadata as IModelValidator;
|
||||
if (validator != null)
|
||||
{
|
||||
context.Validators.Add(validator);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -10,7 +10,7 @@ using System.Runtime.CompilerServices;
|
|||
using Microsoft.AspNet.Mvc.ModelBinding.Internal;
|
||||
using Microsoft.Framework.Internal;
|
||||
|
||||
namespace Microsoft.AspNet.Mvc.ModelBinding
|
||||
namespace Microsoft.AspNet.Mvc.ModelBinding.Validation
|
||||
{
|
||||
/// <summary>
|
||||
/// Recursively validate an object.
|
||||
|
|
@ -49,7 +49,7 @@ namespace Microsoft.AspNet.Mvc.ModelBinding
|
|||
string modelKey,
|
||||
ModelExplorer modelExplorer,
|
||||
ValidationContext validationContext,
|
||||
IEnumerable<IModelValidator> validators)
|
||||
IList<IModelValidator> validators)
|
||||
{
|
||||
// Recursion guard to avoid stack overflows
|
||||
RuntimeHelpers.EnsureSufficientExecutionStack();
|
||||
|
|
@ -84,7 +84,10 @@ namespace Microsoft.AspNet.Mvc.ModelBinding
|
|||
// the same for all the elements of the array, we do not do GetValidators for each element,
|
||||
// instead we just pass them over. See ValidateElements function.
|
||||
var validatorProvider = validationContext.ModelValidationContext.ValidatorProvider;
|
||||
validators = validatorProvider.GetValidators(modelExplorer.Metadata);
|
||||
var validatorProviderContext = new ModelValidatorProviderContext(modelExplorer.Metadata);
|
||||
validatorProvider.GetValidators(validatorProviderContext);
|
||||
|
||||
validators = validatorProviderContext.Validators;
|
||||
}
|
||||
|
||||
// We don't need to recursively traverse the graph for null values
|
||||
|
|
@ -186,7 +189,11 @@ namespace Microsoft.AspNet.Mvc.ModelBinding
|
|||
var elementType = GetElementType(model.GetType());
|
||||
var elementMetadata = _modelMetadataProvider.GetMetadataForType(elementType);
|
||||
|
||||
var validators = validationContext.ModelValidationContext.ValidatorProvider.GetValidators(elementMetadata);
|
||||
var validatorProvider = validationContext.ModelValidationContext.ValidatorProvider;
|
||||
var validatorProviderContext = new ModelValidatorProviderContext(elementMetadata);
|
||||
validatorProvider.GetValidators(validatorProviderContext);
|
||||
|
||||
var validators = validatorProviderContext.Validators;
|
||||
|
||||
// If there are no validators or the object is null we bail out quickly
|
||||
// when there are large arrays of null, this will save a significant amount of processing
|
||||
|
|
@ -220,20 +227,28 @@ namespace Microsoft.AspNet.Mvc.ModelBinding
|
|||
string modelKey,
|
||||
ModelExplorer modelExplorer,
|
||||
ValidationContext validationContext,
|
||||
IEnumerable<IModelValidator> validators)
|
||||
IList<IModelValidator> validators)
|
||||
{
|
||||
var isValid = true;
|
||||
|
||||
var modelState = validationContext.ModelValidationContext.ModelState;
|
||||
var fieldValidationState = modelState.GetFieldValidationState(modelKey);
|
||||
if (fieldValidationState == ModelValidationState.Invalid)
|
||||
{
|
||||
// Even if we have no validators it's possible that model binding may have added a
|
||||
// validation error (conversion error, missing data). We want to still run
|
||||
// validators even if that's the case.
|
||||
isValid = false;
|
||||
}
|
||||
|
||||
// When the are no validators we bail quickly. This saves a GetEnumerator allocation.
|
||||
// In a large array (tens of thousands or more) scenario it's very significant.
|
||||
var validatorsAsCollection = validators as ICollection;
|
||||
if (validatorsAsCollection == null || validatorsAsCollection.Count > 0)
|
||||
if (validators == null || validators.Count > 0)
|
||||
{
|
||||
var modelValidationContext =
|
||||
new ModelValidationContext(validationContext.ModelValidationContext, modelExplorer);
|
||||
var modelState = validationContext.ModelValidationContext.ModelState;
|
||||
|
||||
var modelValidationState = modelState.GetValidationState(modelKey);
|
||||
var fieldValidationState = modelState.GetFieldValidationState(modelKey);
|
||||
|
||||
// If either the model or its properties are unvalidated, validate them now.
|
||||
if (modelValidationState == ModelValidationState.Unvalidated ||
|
||||
|
|
@ -257,10 +272,6 @@ namespace Microsoft.AspNet.Mvc.ModelBinding
|
|||
}
|
||||
}
|
||||
}
|
||||
else if (fieldValidationState == ModelValidationState.Invalid)
|
||||
{
|
||||
isValid = false;
|
||||
}
|
||||
}
|
||||
|
||||
if (isValid)
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@
|
|||
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Microsoft.AspNet.Mvc.ModelBinding
|
||||
namespace Microsoft.AspNet.Mvc.ModelBinding.Validation
|
||||
{
|
||||
public interface IClientModelValidator
|
||||
{
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
// 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.
|
||||
|
||||
namespace Microsoft.AspNet.Mvc.ModelBinding
|
||||
namespace Microsoft.AspNet.Mvc.ModelBinding.Validation
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents aggregate of <see cref="IModelValidatorProvider"/>s that delegates to its underlying providers.
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@
|
|||
using System;
|
||||
using Microsoft.Framework.Internal;
|
||||
|
||||
namespace Microsoft.AspNet.Mvc.ModelBinding
|
||||
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.
|
||||
|
|
|
|||
|
|
@ -3,12 +3,26 @@
|
|||
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Microsoft.AspNet.Mvc.ModelBinding
|
||||
namespace Microsoft.AspNet.Mvc.ModelBinding.Validation
|
||||
{
|
||||
/// <summary>
|
||||
/// Validates a model value.
|
||||
/// </summary>
|
||||
public interface IModelValidator
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets a value indicating whether or not this validator validates that a required value
|
||||
/// has been provided for the model.
|
||||
/// </summary>
|
||||
bool IsRequired { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Validates the model value.
|
||||
/// </summary>
|
||||
/// <param name="context">The <see cref="ModelValidationContext"/>.</param>
|
||||
/// <returns>
|
||||
/// A list of <see cref="ModelValidationResult"/> indicating the results of validating the model value.
|
||||
/// </returns>
|
||||
IEnumerable<ModelValidationResult> Validate(ModelValidationContext context);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,12 +1,21 @@
|
|||
// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Microsoft.AspNet.Mvc.ModelBinding
|
||||
namespace Microsoft.AspNet.Mvc.ModelBinding.Validation
|
||||
{
|
||||
/// <summary>
|
||||
/// Provides validators for a model value.
|
||||
/// </summary>
|
||||
public interface IModelValidatorProvider
|
||||
{
|
||||
IEnumerable<IModelValidator> GetValidators(ModelMetadata metadata);
|
||||
/// <summary>
|
||||
/// Gets the validators for <see cref="ModelValidatorProviderContext.ModelMetadata"/>.
|
||||
/// </summary>
|
||||
/// <param name="context">The <see cref="ModelValidatorProviderContext"/>.</param>
|
||||
/// <remarks>
|
||||
/// Implementations should add <see cref="IModelValidator"/> instances to
|
||||
/// <see cref="ModelValidatorProviderContext.Validators"/>.
|
||||
/// </remarks>
|
||||
void GetValidators(ModelValidatorProviderContext context);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@
|
|||
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Microsoft.AspNet.Mvc.ModelBinding
|
||||
namespace Microsoft.AspNet.Mvc.ModelBinding.Validation
|
||||
{
|
||||
/// <summary>
|
||||
/// Provides an activated collection of <see cref="IModelValidatorProvider"/> instances.
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
// 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.
|
||||
|
||||
namespace Microsoft.AspNet.Mvc.ModelBinding
|
||||
namespace Microsoft.AspNet.Mvc.ModelBinding.Validation
|
||||
{
|
||||
/// <summary>
|
||||
/// Provides methods to validate an object graph.
|
||||
|
|
@ -2,9 +2,8 @@
|
|||
// 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
|
||||
namespace Microsoft.AspNet.Mvc.ModelBinding.Validation
|
||||
{
|
||||
/// <summary>
|
||||
/// Provides an activated collection of <see cref="IExcludeTypeValidationFilter"/> instances.
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@ using System.Collections.Generic;
|
|||
using System.ComponentModel.DataAnnotations;
|
||||
using Microsoft.Framework.Internal;
|
||||
|
||||
namespace Microsoft.AspNet.Mvc.ModelBinding
|
||||
namespace Microsoft.AspNet.Mvc.ModelBinding.Validation
|
||||
{
|
||||
public class MaxLengthAttributeAdapter : DataAnnotationsModelValidator<MaxLengthAttribute>
|
||||
{
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@ using System.Collections.Generic;
|
|||
using System.ComponentModel.DataAnnotations;
|
||||
using Microsoft.Framework.Internal;
|
||||
|
||||
namespace Microsoft.AspNet.Mvc.ModelBinding
|
||||
namespace Microsoft.AspNet.Mvc.ModelBinding.Validation
|
||||
{
|
||||
public class MinLengthAttributeAdapter : DataAnnotationsModelValidator<MinLengthAttribute>
|
||||
{
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@
|
|||
|
||||
using Microsoft.Framework.Internal;
|
||||
|
||||
namespace Microsoft.AspNet.Mvc.ModelBinding
|
||||
namespace Microsoft.AspNet.Mvc.ModelBinding.Validation
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents client side validation rule that determines if two values are equal.
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@
|
|||
|
||||
using Microsoft.Framework.Internal;
|
||||
|
||||
namespace Microsoft.AspNet.Mvc.ModelBinding
|
||||
namespace Microsoft.AspNet.Mvc.ModelBinding.Validation
|
||||
{
|
||||
public class ModelClientValidationMaxLengthRule : ModelClientValidationRule
|
||||
{
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@
|
|||
|
||||
using Microsoft.Framework.Internal;
|
||||
|
||||
namespace Microsoft.AspNet.Mvc.ModelBinding
|
||||
namespace Microsoft.AspNet.Mvc.ModelBinding.Validation
|
||||
{
|
||||
public class ModelClientValidationMinLengthRule : ModelClientValidationRule
|
||||
{
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@
|
|||
|
||||
using Microsoft.Framework.Internal;
|
||||
|
||||
namespace Microsoft.AspNet.Mvc.ModelBinding
|
||||
namespace Microsoft.AspNet.Mvc.ModelBinding.Validation
|
||||
{
|
||||
public class ModelClientValidationRangeRule : ModelClientValidationRule
|
||||
{
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
// 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.
|
||||
|
||||
namespace Microsoft.AspNet.Mvc.ModelBinding
|
||||
namespace Microsoft.AspNet.Mvc.ModelBinding.Validation
|
||||
{
|
||||
public class ModelClientValidationRegexRule : ModelClientValidationRule
|
||||
{
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
// 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.
|
||||
|
||||
namespace Microsoft.AspNet.Mvc.ModelBinding
|
||||
namespace Microsoft.AspNet.Mvc.ModelBinding.Validation
|
||||
{
|
||||
public class ModelClientValidationRequiredRule : ModelClientValidationRule
|
||||
{
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@ using System;
|
|||
using System.Collections.Generic;
|
||||
using Microsoft.Framework.Internal;
|
||||
|
||||
namespace Microsoft.AspNet.Mvc.ModelBinding
|
||||
namespace Microsoft.AspNet.Mvc.ModelBinding.Validation
|
||||
{
|
||||
public class ModelClientValidationRule
|
||||
{
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
// 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.
|
||||
|
||||
namespace Microsoft.AspNet.Mvc.ModelBinding
|
||||
namespace Microsoft.AspNet.Mvc.ModelBinding.Validation
|
||||
{
|
||||
public class ModelClientValidationStringLengthRule : ModelClientValidationRule
|
||||
{
|
||||
|
|
|
|||
|
|
@ -0,0 +1,49 @@
|
|||
// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Microsoft.AspNet.Mvc.ModelBinding.Validation
|
||||
{
|
||||
/// <summary>
|
||||
/// A context for <see cref="IModelValidatorProvider"/>.
|
||||
/// </summary>
|
||||
public class ModelValidatorProviderContext
|
||||
{
|
||||
/// <summary>
|
||||
/// Creates a new <see cref="ModelValidatorProviderContext"/>.
|
||||
/// </summary>
|
||||
/// <param name="modelMetadata">The <see cref="ModelBinding.ModelMetadata"/>.</param>
|
||||
public ModelValidatorProviderContext(ModelMetadata modelMetadata)
|
||||
{
|
||||
ModelMetadata = modelMetadata;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the <see cref="ModelBinding.ModelMetadata"/>.
|
||||
/// </summary>
|
||||
public ModelMetadata ModelMetadata { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the validator metadata.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// This property provides convenience access to <see cref="ModelMetadata.ValidatorMetadata"/>.
|
||||
/// </remarks>
|
||||
public IReadOnlyList<object> ValidatorMetadata
|
||||
{
|
||||
get
|
||||
{
|
||||
return ModelMetadata.ValidatorMetadata;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the list of <see cref="IModelValidator"/> instances. <see cref="IModelValidatorProvider"/> instances
|
||||
/// should add validators to this list when
|
||||
/// <see cref="IModelValidatorProvider.GetValidators(ModelValidatorProviderContext)"/>
|
||||
/// is called.
|
||||
/// </summary>
|
||||
public IList<IModelValidator> Validators { get; } = new List<IModelValidator>();
|
||||
}
|
||||
}
|
||||
|
|
@ -1,10 +1,9 @@
|
|||
// 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.Framework.Internal;
|
||||
|
||||
namespace Microsoft.AspNet.Mvc.ModelBinding
|
||||
namespace Microsoft.AspNet.Mvc.ModelBinding.Validation
|
||||
{
|
||||
public class ModelValidationContext
|
||||
{
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
// 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.
|
||||
|
||||
namespace Microsoft.AspNet.Mvc.ModelBinding
|
||||
namespace Microsoft.AspNet.Mvc.ModelBinding.Validation
|
||||
{
|
||||
public class ModelValidationResult
|
||||
{
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@ using System.Collections.Generic;
|
|||
using System.ComponentModel.DataAnnotations;
|
||||
using Microsoft.Framework.Internal;
|
||||
|
||||
namespace Microsoft.AspNet.Mvc.ModelBinding
|
||||
namespace Microsoft.AspNet.Mvc.ModelBinding.Validation
|
||||
{
|
||||
public class RangeAttributeAdapter : DataAnnotationsModelValidator<RangeAttribute>
|
||||
{
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@
|
|||
using System.Collections.Generic;
|
||||
using System.Runtime.CompilerServices;
|
||||
|
||||
namespace Microsoft.AspNet.Mvc.ModelBinding
|
||||
namespace Microsoft.AspNet.Mvc.ModelBinding.Validation
|
||||
{
|
||||
internal class ReferenceEqualityComparer : IEqualityComparer<object>
|
||||
{
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@ using System.Collections.Generic;
|
|||
using System.ComponentModel.DataAnnotations;
|
||||
using Microsoft.Framework.Internal;
|
||||
|
||||
namespace Microsoft.AspNet.Mvc.ModelBinding
|
||||
namespace Microsoft.AspNet.Mvc.ModelBinding.Validation
|
||||
{
|
||||
public class RegularExpressionAttributeAdapter : DataAnnotationsModelValidator<RegularExpressionAttribute>
|
||||
{
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@ using System.Collections.Generic;
|
|||
using System.ComponentModel.DataAnnotations;
|
||||
using Microsoft.Framework.Internal;
|
||||
|
||||
namespace Microsoft.AspNet.Mvc.ModelBinding
|
||||
namespace Microsoft.AspNet.Mvc.ModelBinding.Validation
|
||||
{
|
||||
public class RequiredAttributeAdapter : DataAnnotationsModelValidator<RequiredAttribute>
|
||||
{
|
||||
|
|
|
|||
|
|
@ -1,21 +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.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
||||
namespace Microsoft.AspNet.Mvc.ModelBinding
|
||||
{
|
||||
public class RequiredMemberModelValidator : IModelValidator
|
||||
{
|
||||
public bool IsRequired
|
||||
{
|
||||
get { return true; }
|
||||
}
|
||||
|
||||
public IEnumerable<ModelValidationResult> Validate(ModelValidationContext context)
|
||||
{
|
||||
return Enumerable.Empty<ModelValidationResult>();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -5,7 +5,7 @@ using System;
|
|||
using System.Collections.Generic;
|
||||
using System.Reflection;
|
||||
|
||||
namespace Microsoft.AspNet.Mvc.ModelBinding
|
||||
namespace Microsoft.AspNet.Mvc.ModelBinding.Validation
|
||||
{
|
||||
/// <summary>
|
||||
/// Identifies the simple types that the default model binding validation will exclude.
|
||||
|
|
@ -5,7 +5,7 @@ using System.Collections.Generic;
|
|||
using System.ComponentModel.DataAnnotations;
|
||||
using Microsoft.Framework.Internal;
|
||||
|
||||
namespace Microsoft.AspNet.Mvc.ModelBinding
|
||||
namespace Microsoft.AspNet.Mvc.ModelBinding.Validation
|
||||
{
|
||||
public class StringLengthAttributeAdapter : DataAnnotationsModelValidator<StringLengthAttribute>
|
||||
{
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@ using System.Collections.Generic;
|
|||
using System.ComponentModel.DataAnnotations;
|
||||
using System.Linq;
|
||||
|
||||
namespace Microsoft.AspNet.Mvc.ModelBinding
|
||||
namespace Microsoft.AspNet.Mvc.ModelBinding.Validation
|
||||
{
|
||||
public class ValidatableObjectAdapter : IModelValidator
|
||||
{
|
||||
|
|
|
|||
|
|
@ -8,8 +8,8 @@ using System.Text;
|
|||
using Microsoft.AspNet.Http;
|
||||
using Microsoft.AspNet.Mvc;
|
||||
using Microsoft.AspNet.Mvc.ModelBinding;
|
||||
using Microsoft.AspNet.Mvc.ModelBinding.Validation;
|
||||
using Microsoft.AspNet.Mvc.WebApiCompatShim;
|
||||
using Microsoft.Framework.DependencyInjection;
|
||||
using Microsoft.Framework.Internal;
|
||||
using Newtonsoft.Json;
|
||||
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@ using System;
|
|||
using System.Xml.Linq;
|
||||
using Microsoft.AspNet.Mvc.ModelBinding;
|
||||
using Microsoft.AspNet.Mvc.ModelBinding.Metadata;
|
||||
using Microsoft.AspNet.Mvc.ModelBinding.Validation;
|
||||
using Microsoft.AspNet.Mvc.Razor;
|
||||
using Microsoft.Framework.OptionsModel;
|
||||
using Microsoft.Net.Http.Headers;
|
||||
|
|
@ -62,11 +63,13 @@ namespace Microsoft.AspNet.Mvc
|
|||
|
||||
// Set up metadata providers
|
||||
options.ModelMetadataDetailsProviders.Add(new DefaultBindingMetadataProvider());
|
||||
options.ModelMetadataDetailsProviders.Add(new DataAnnotationsMetadataDetailsProvider());
|
||||
options.ModelMetadataDetailsProviders.Add(new DefaultValidationMetadataProvider());
|
||||
options.ModelMetadataDetailsProviders.Add(new DataAnnotationsMetadataProvider());
|
||||
options.ModelMetadataDetailsProviders.Add(new DataMemberRequiredValidationMetadataProvider());
|
||||
|
||||
// Set up validators
|
||||
options.ModelValidatorProviders.Add(new DefaultModelValidatorProvider());
|
||||
options.ModelValidatorProviders.Add(new DataAnnotationsModelValidatorProvider());
|
||||
options.ModelValidatorProviders.Add(new DataMemberModelValidatorProvider());
|
||||
|
||||
// Add types to be excluded from Validation
|
||||
options.ValidationExcludeFilters.Add(new SimpleTypesExcludeFilter());
|
||||
|
|
|
|||
|
|
@ -9,6 +9,7 @@ using Microsoft.AspNet.Mvc.Filters;
|
|||
using Microsoft.AspNet.Mvc.Internal;
|
||||
using Microsoft.AspNet.Mvc.ModelBinding;
|
||||
using Microsoft.AspNet.Mvc.ModelBinding.Metadata;
|
||||
using Microsoft.AspNet.Mvc.ModelBinding.Validation;
|
||||
using Microsoft.AspNet.Mvc.OptionDescriptors;
|
||||
using Microsoft.AspNet.Mvc.Razor;
|
||||
using Microsoft.AspNet.Mvc.Razor.Directives;
|
||||
|
|
|
|||
|
|
@ -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.Linq;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Text;
|
||||
|
|
@ -10,8 +9,8 @@ using System.Threading.Tasks;
|
|||
using Microsoft.AspNet.Http;
|
||||
using Microsoft.AspNet.Http.Core;
|
||||
using Microsoft.AspNet.Mvc.ModelBinding;
|
||||
using Microsoft.AspNet.Mvc.ModelBinding.Validation;
|
||||
using Microsoft.AspNet.Routing;
|
||||
using Microsoft.Framework.DependencyInjection;
|
||||
using Microsoft.Net.Http.Headers;
|
||||
using Moq;
|
||||
using Xunit;
|
||||
|
|
|
|||
|
|
@ -3,7 +3,6 @@
|
|||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.ObjectModel;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
|
|
@ -13,9 +12,9 @@ using Microsoft.AspNet.Http.Core;
|
|||
using Microsoft.AspNet.Mvc.Core;
|
||||
using Microsoft.AspNet.Mvc.ModelBinding;
|
||||
using Microsoft.AspNet.Mvc.ModelBinding.Metadata;
|
||||
using Microsoft.AspNet.Mvc.ModelBinding.Validation;
|
||||
using Microsoft.AspNet.Routing;
|
||||
using Microsoft.AspNet.Testing;
|
||||
using Microsoft.Framework.DependencyInjection;
|
||||
using Microsoft.Framework.OptionsModel;
|
||||
using Moq;
|
||||
using Xunit;
|
||||
|
|
|
|||
|
|
@ -12,6 +12,7 @@ using Microsoft.AspNet.Hosting;
|
|||
using Microsoft.AspNet.Http;
|
||||
using Microsoft.AspNet.Http.Core;
|
||||
using Microsoft.AspNet.Mvc.ModelBinding;
|
||||
using Microsoft.AspNet.Mvc.ModelBinding.Validation;
|
||||
using Microsoft.AspNet.Routing;
|
||||
using Microsoft.AspNet.Testing;
|
||||
using Microsoft.AspNet.WebUtilities;
|
||||
|
|
@ -1580,8 +1581,8 @@ namespace Microsoft.AspNet.Mvc.Test
|
|||
.Returns(validationResult);
|
||||
|
||||
var provider = new Mock<IModelValidatorProvider>();
|
||||
provider.Setup(v => v.GetValidators(It.IsAny<ModelMetadata>()))
|
||||
.Returns(new[] { validator1.Object });
|
||||
provider.Setup(v => v.GetValidators(It.IsAny<ModelValidatorProviderContext>()))
|
||||
.Callback<ModelValidatorProviderContext>(c => c.Validators.Add(validator1.Object));
|
||||
|
||||
var binder = new Mock<IModelBinder>();
|
||||
var controller = GetController(binder.Object, provider: null);
|
||||
|
|
@ -1613,8 +1614,8 @@ namespace Microsoft.AspNet.Mvc.Test
|
|||
.Returns(validationResult);
|
||||
|
||||
var provider = new Mock<IModelValidatorProvider>();
|
||||
provider.Setup(v => v.GetValidators(It.IsAny<ModelMetadata>()))
|
||||
.Returns(new[] { validator1.Object });
|
||||
provider.Setup(v => v.GetValidators(It.IsAny<ModelValidatorProviderContext>()))
|
||||
.Callback<ModelValidatorProviderContext>(c => c.Validators.Add(validator1.Object));
|
||||
|
||||
var binder = new Mock<IModelBinder>();
|
||||
var controller = GetController(binder.Object, provider: null);
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@ using System.Reflection;
|
|||
using Microsoft.AspNet.Http;
|
||||
using Microsoft.AspNet.Http.Core;
|
||||
using Microsoft.AspNet.Mvc.ModelBinding;
|
||||
using Microsoft.AspNet.Mvc.ModelBinding.Validation;
|
||||
using Microsoft.AspNet.Routing;
|
||||
using Microsoft.Framework.DependencyInjection;
|
||||
using Moq;
|
||||
|
|
|
|||
|
|
@ -3,9 +3,9 @@
|
|||
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Microsoft.AspNet.Mvc.ModelBinding
|
||||
namespace Microsoft.AspNet.Mvc.ModelBinding.Validation
|
||||
{
|
||||
public class MockModelValidatorProviderProvider: IModelValidatorProviderProvider
|
||||
public class MockModelValidatorProviderProvider : IModelValidatorProviderProvider
|
||||
{
|
||||
public List<IModelValidatorProvider> ModelValidatorProviders { get; } = new List<IModelValidatorProvider>();
|
||||
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using Microsoft.AspNet.Mvc.ModelBinding;
|
||||
using Microsoft.AspNet.Mvc.ModelBinding.Validation;
|
||||
using Microsoft.Framework.OptionsModel;
|
||||
using Moq;
|
||||
using Xunit;
|
||||
|
|
@ -52,9 +53,8 @@ namespace Microsoft.AspNet.Mvc.OptionDescriptors
|
|||
|
||||
public ITestService Service { get; private set; }
|
||||
|
||||
public IEnumerable<IModelValidator> GetValidators(ModelMetadata metadata)
|
||||
public void GetValidators(ModelValidatorProviderContext context)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
// 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.Mvc.ModelBinding.Validation;
|
||||
using Microsoft.AspNet.Testing;
|
||||
using Microsoft.Framework.Internal;
|
||||
using Xunit;
|
||||
|
|
@ -16,7 +16,7 @@ namespace Microsoft.AspNet.Mvc.OptionDescriptors
|
|||
{
|
||||
// Arrange
|
||||
var expected = "The type 'System.String' must derive from " +
|
||||
"'Microsoft.AspNet.Mvc.ModelBinding.IExcludeTypeValidationFilter'.";
|
||||
"'Microsoft.AspNet.Mvc.ModelBinding.Validation.IExcludeTypeValidationFilter'.";
|
||||
var type = typeof(string);
|
||||
|
||||
// Act & Assert
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using Microsoft.AspNet.Mvc.ModelBinding;
|
||||
using Microsoft.AspNet.Mvc.ModelBinding.Validation;
|
||||
using Microsoft.AspNet.Testing;
|
||||
using Xunit;
|
||||
|
||||
|
|
@ -54,9 +55,8 @@ namespace Microsoft.AspNet.Mvc.OptionDescriptors
|
|||
|
||||
private class TestModelValidatorProvider : IModelValidatorProvider
|
||||
{
|
||||
public IEnumerable<IModelValidator> GetValidators(ModelMetadata metadata)
|
||||
public void GetValidators(ModelValidatorProviderContext context)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using Microsoft.AspNet.Mvc.ModelBinding;
|
||||
using Microsoft.AspNet.Mvc.ModelBinding.Validation;
|
||||
using Microsoft.AspNet.Mvc.OptionDescriptors;
|
||||
using Moq;
|
||||
using Xunit;
|
||||
|
|
@ -52,7 +53,7 @@ namespace Microsoft.AspNet.Mvc
|
|||
// Arrange
|
||||
var provider1 = Mock.Of<IModelValidatorProvider>();
|
||||
var provider2 = Mock.Of<IModelValidatorProvider>();
|
||||
var type1 = typeof(DataMemberModelValidatorProvider);
|
||||
var type1 = typeof(DefaultModelValidatorProvider);
|
||||
var type2 = typeof(DataAnnotationsModelValidatorProvider);
|
||||
var collection = new List<ModelValidatorProviderDescriptor>();
|
||||
|
||||
|
|
@ -66,7 +67,7 @@ namespace Microsoft.AspNet.Mvc
|
|||
Assert.Equal(4, collection.Count);
|
||||
Assert.Same(provider1, collection[0].Instance);
|
||||
Assert.Same(provider2, collection[1].Instance);
|
||||
Assert.IsType<DataMemberModelValidatorProvider>(collection[2].OptionType);
|
||||
Assert.IsType<DefaultModelValidatorProvider>(collection[2].OptionType);
|
||||
Assert.IsType<DataAnnotationsModelValidatorProvider>(collection[3].OptionType);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -8,6 +8,7 @@ using System.Threading.Tasks;
|
|||
using Microsoft.AspNet.Http.Core;
|
||||
using Microsoft.AspNet.Mvc.ModelBinding;
|
||||
using Microsoft.AspNet.Mvc.ModelBinding.Metadata;
|
||||
using Microsoft.AspNet.Mvc.ModelBinding.Validation;
|
||||
using Microsoft.AspNet.Routing;
|
||||
using Moq;
|
||||
using Xunit;
|
||||
|
|
@ -416,4 +417,4 @@ namespace Microsoft.AspNet.Mvc.Core.Test
|
|||
public int IncludedExplicitly2 { get; set; }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,20 +3,18 @@
|
|||
|
||||
#if DNX451
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
using System.Linq;
|
||||
using System.Linq.Expressions;
|
||||
using System.Reflection;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.AspNet.Http;
|
||||
using Microsoft.AspNet.Mvc.ModelBinding;
|
||||
using Microsoft.AspNet.Mvc.ModelBinding.Validation;
|
||||
using Microsoft.AspNet.Testing;
|
||||
using Moq;
|
||||
using Xunit;
|
||||
|
||||
namespace Microsoft.AspNet.Mvc.Core.Test
|
||||
namespace Microsoft.AspNet.Mvc.Test
|
||||
{
|
||||
public class ModelBindingHelperTest
|
||||
{
|
||||
|
|
|
|||
|
|
@ -2,10 +2,10 @@
|
|||
// 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.Builder;
|
||||
using Microsoft.AspNet.Http.Core;
|
||||
using Microsoft.AspNet.Mvc.ModelBinding;
|
||||
using Microsoft.AspNet.Mvc.ModelBinding.Validation;
|
||||
using Microsoft.AspNet.Routing;
|
||||
using Microsoft.Framework.DependencyInjection;
|
||||
using Microsoft.Framework.Logging;
|
||||
|
|
|
|||
|
|
@ -9,6 +9,7 @@ using System.Linq;
|
|||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.AspNet.Mvc.ModelBinding;
|
||||
using Microsoft.AspNet.Mvc.ModelBinding.Validation;
|
||||
using Microsoft.AspNet.Mvc.Rendering;
|
||||
using Microsoft.AspNet.Testing;
|
||||
using Microsoft.Framework.Internal;
|
||||
|
|
|
|||
|
|
@ -10,6 +10,7 @@ using System.Threading.Tasks;
|
|||
using Microsoft.AspNet.DataProtection;
|
||||
using Microsoft.AspNet.Http.Core;
|
||||
using Microsoft.AspNet.Mvc.ModelBinding;
|
||||
using Microsoft.AspNet.Mvc.ModelBinding.Validation;
|
||||
using Microsoft.AspNet.Routing;
|
||||
using Microsoft.Framework.OptionsModel;
|
||||
using Microsoft.Framework.WebEncoders;
|
||||
|
|
|
|||
|
|
@ -6,9 +6,10 @@ using System;
|
|||
using System.Collections.Generic;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.AspNet.Http.Core;
|
||||
using Microsoft.AspNet.Mvc.ModelBinding.Validation;
|
||||
using Microsoft.Framework.DependencyInjection;
|
||||
using Moq;
|
||||
using Xunit;
|
||||
using Microsoft.Framework.DependencyInjection;
|
||||
|
||||
namespace Microsoft.AspNet.Mvc.ModelBinding.Test
|
||||
{
|
||||
|
|
|
|||
|
|
@ -7,6 +7,7 @@ using System.Collections.Generic;
|
|||
using System.ComponentModel.DataAnnotations;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.AspNet.Mvc.ModelBinding.Validation;
|
||||
using Moq;
|
||||
using Xunit;
|
||||
|
||||
|
|
@ -461,8 +462,20 @@ namespace Microsoft.AspNet.Mvc.ModelBinding.Test
|
|||
private static IModelValidatorProvider GetValidatorProvider(params IModelValidator[] validators)
|
||||
{
|
||||
var provider = new Mock<IModelValidatorProvider>();
|
||||
provider.Setup(v => v.GetValidators(It.IsAny<ModelMetadata>()))
|
||||
.Returns(validators ?? Enumerable.Empty<IModelValidator>());
|
||||
provider
|
||||
.Setup(v => v.GetValidators(It.IsAny<ModelValidatorProviderContext>()))
|
||||
.Callback<ModelValidatorProviderContext>(c =>
|
||||
{
|
||||
if (validators == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
foreach (var validator in validators)
|
||||
{
|
||||
c.Validators.Add(validator);
|
||||
}
|
||||
});
|
||||
|
||||
return provider.Object;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@ using System;
|
|||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.AspNet.Mvc.ModelBinding.Validation;
|
||||
using Moq;
|
||||
using Xunit;
|
||||
|
||||
|
|
|
|||
|
|
@ -9,6 +9,7 @@ using System.ComponentModel.DataAnnotations;
|
|||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.AspNet.Http.Core;
|
||||
using Microsoft.AspNet.Mvc.ModelBinding.Validation;
|
||||
using Microsoft.AspNet.Testing;
|
||||
using Moq;
|
||||
using Xunit;
|
||||
|
|
@ -1194,10 +1195,11 @@ namespace Microsoft.AspNet.Mvc.ModelBinding
|
|||
isModelSet: false,
|
||||
key: "foo");
|
||||
|
||||
var requiredValidator = bindingContext.OperationBindingContext
|
||||
.ValidatorProvider
|
||||
.GetValidators(propertyMetadata)
|
||||
.FirstOrDefault(v => v.IsRequired);
|
||||
var validatorProvider = bindingContext.OperationBindingContext.ValidatorProvider;
|
||||
var validatorProviderContext = new ModelValidatorProviderContext(propertyMetadata);
|
||||
validatorProvider.GetValidators(validatorProviderContext);
|
||||
|
||||
var requiredValidator = validatorProviderContext.Validators.FirstOrDefault(v => v.IsRequired);
|
||||
|
||||
var testableBinder = new TestableMutableObjectModelBinder();
|
||||
|
||||
|
|
@ -1327,11 +1329,11 @@ namespace Microsoft.AspNet.Mvc.ModelBinding
|
|||
key: "foo",
|
||||
isModelSet: true);
|
||||
|
||||
var validatorProvider = bindingContext.OperationBindingContext.ValidatorProvider;
|
||||
var validatorProviderContext = new ModelValidatorProviderContext(propertyMetadata);
|
||||
validatorProvider.GetValidators(validatorProviderContext);
|
||||
|
||||
var requiredValidator = bindingContext.OperationBindingContext
|
||||
.ValidatorProvider
|
||||
.GetValidators(propertyMetadata)
|
||||
.FirstOrDefault(v => v.IsRequired);
|
||||
var requiredValidator = validatorProviderContext.Validators.FirstOrDefault(v => v.IsRequired);
|
||||
|
||||
var testableBinder = new TestableMutableObjectModelBinder();
|
||||
|
||||
|
|
@ -1526,12 +1528,6 @@ namespace Microsoft.AspNet.Mvc.ModelBinding
|
|||
|
||||
private static ModelBindingContext CreateContext(ModelMetadata metadata, object model)
|
||||
{
|
||||
var providers = new IModelValidatorProvider[]
|
||||
{
|
||||
new DataAnnotationsModelValidatorProvider(),
|
||||
new DataMemberModelValidatorProvider()
|
||||
};
|
||||
|
||||
return new ModelBindingContext
|
||||
{
|
||||
Model = model,
|
||||
|
|
@ -1541,17 +1537,18 @@ namespace Microsoft.AspNet.Mvc.ModelBinding
|
|||
OperationBindingContext = new OperationBindingContext
|
||||
{
|
||||
MetadataProvider = TestModelMetadataProvider.CreateDefaultProvider(),
|
||||
ValidatorProvider = new CompositeModelValidatorProvider(providers)
|
||||
ValidatorProvider = TestModelValidatorProvider.CreateDefaultProvider(),
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
private static IModelValidator GetRequiredValidator(ModelBindingContext bindingContext, ModelMetadata propertyMetadata)
|
||||
{
|
||||
return bindingContext.OperationBindingContext
|
||||
.ValidatorProvider
|
||||
.GetValidators(propertyMetadata)
|
||||
.FirstOrDefault(v => v.IsRequired);
|
||||
var validatorProvider = bindingContext.OperationBindingContext.ValidatorProvider;
|
||||
var validatorProviderContext = new ModelValidatorProviderContext(propertyMetadata);
|
||||
validatorProvider.GetValidators(validatorProviderContext);
|
||||
|
||||
return validatorProviderContext.Validators.FirstOrDefault(v => v.IsRequired);
|
||||
}
|
||||
|
||||
private static ModelMetadata GetMetadataForCanUpdateProperty(string propertyName)
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@ using Xunit;
|
|||
|
||||
namespace Microsoft.AspNet.Mvc.ModelBinding.Metadata
|
||||
{
|
||||
public class DataAnnotationsMetadataDetailsProviderTest
|
||||
public class DataAnnotationsMetadataProviderTest
|
||||
{
|
||||
// Includes attributes with a 'simple' effect on display details.
|
||||
public static TheoryData<object, Func<DisplayMetadata, object>, object> DisplayDetailsData
|
||||
|
|
@ -52,7 +52,7 @@ namespace Microsoft.AspNet.Mvc.ModelBinding.Metadata
|
|||
object expected)
|
||||
{
|
||||
// Arrange
|
||||
var provider = new DataAnnotationsMetadataDetailsProvider();
|
||||
var provider = new DataAnnotationsMetadataProvider();
|
||||
|
||||
var key = ModelMetadataIdentity.ForType(typeof(string));
|
||||
var context = new DisplayMetadataProviderContext(key, new object[] { attribute });
|
||||
|
|
@ -69,7 +69,7 @@ namespace Microsoft.AspNet.Mvc.ModelBinding.Metadata
|
|||
public void GetDisplayDetails_FindsDisplayFormat_FromDataType()
|
||||
{
|
||||
// Arrange
|
||||
var provider = new DataAnnotationsMetadataDetailsProvider();
|
||||
var provider = new DataAnnotationsMetadataProvider();
|
||||
|
||||
var dataType = new DataTypeAttribute(DataType.Currency);
|
||||
var displayFormat = dataType.DisplayFormat; // Non-null for DataType.Currency.
|
||||
|
|
@ -89,7 +89,7 @@ namespace Microsoft.AspNet.Mvc.ModelBinding.Metadata
|
|||
public void GetDisplayDetails_FindsDisplayFormat_OverridingDataType()
|
||||
{
|
||||
// Arrange
|
||||
var provider = new DataAnnotationsMetadataDetailsProvider();
|
||||
var provider = new DataAnnotationsMetadataProvider();
|
||||
|
||||
var dataType = new DataTypeAttribute(DataType.Time); // Has a non-null DisplayFormat.
|
||||
var displayFormat = new DisplayFormatAttribute() // But these values override the values from DataType
|
||||
|
|
@ -112,7 +112,7 @@ namespace Microsoft.AspNet.Mvc.ModelBinding.Metadata
|
|||
public void GetDisplayDetails_EditableAttribute_SetsReadOnly()
|
||||
{
|
||||
// Arrange
|
||||
var provider = new DataAnnotationsMetadataDetailsProvider();
|
||||
var provider = new DataAnnotationsMetadataProvider();
|
||||
|
||||
var editable = new EditableAttribute(allowEdit: false);
|
||||
|
||||
|
|
@ -131,7 +131,7 @@ namespace Microsoft.AspNet.Mvc.ModelBinding.Metadata
|
|||
public void GetDisplayDetails_RequiredAttribute_SetsRequired()
|
||||
{
|
||||
// Arrange
|
||||
var provider = new DataAnnotationsMetadataDetailsProvider();
|
||||
var provider = new DataAnnotationsMetadataProvider();
|
||||
|
||||
var required = new RequiredAttribute();
|
||||
|
||||
|
|
@ -151,7 +151,7 @@ namespace Microsoft.AspNet.Mvc.ModelBinding.Metadata
|
|||
public void GetDisplayDetails_DisplayAttribute_NameFromResources()
|
||||
{
|
||||
// Arrange
|
||||
var provider = new DataAnnotationsMetadataDetailsProvider();
|
||||
var provider = new DataAnnotationsMetadataProvider();
|
||||
|
||||
var display = new DisplayAttribute()
|
||||
{
|
||||
|
|
@ -175,7 +175,7 @@ namespace Microsoft.AspNet.Mvc.ModelBinding.Metadata
|
|||
public void GetDisplayDetails_DisplayAttribute_DescriptionFromResources()
|
||||
{
|
||||
// Arrange
|
||||
var provider = new DataAnnotationsMetadataDetailsProvider();
|
||||
var provider = new DataAnnotationsMetadataProvider();
|
||||
|
||||
var display = new DisplayAttribute()
|
||||
{
|
||||
|
|
@ -0,0 +1,96 @@
|
|||
// 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.Runtime.Serialization;
|
||||
using Xunit;
|
||||
|
||||
namespace Microsoft.AspNet.Mvc.ModelBinding.Metadata
|
||||
{
|
||||
public class DataMemberBindingMetadataProviderTest
|
||||
{
|
||||
[Fact]
|
||||
public void ClassWithoutAttributes_NotRequired()
|
||||
{
|
||||
// Arrange
|
||||
var metadataProvider = TestModelMetadataProvider.CreateDefaultProvider();
|
||||
|
||||
// Act
|
||||
var metadata = metadataProvider.GetMetadataForProperty(
|
||||
typeof(ClassWithoutAttributes),
|
||||
"TheProperty");
|
||||
|
||||
// Assert
|
||||
Assert.False(metadata.IsRequired);
|
||||
}
|
||||
|
||||
private class ClassWithoutAttributes
|
||||
{
|
||||
public string TheProperty { get; set; }
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ClassWithDataMemberIsRequiredTrue_Validator()
|
||||
{
|
||||
// Arrange
|
||||
var metadataProvider = TestModelMetadataProvider.CreateDefaultProvider();
|
||||
|
||||
// Act
|
||||
var metadata = metadataProvider.GetMetadataForProperty(
|
||||
typeof(ClassWithDataMemberIsRequiredTrue),
|
||||
"TheProperty");
|
||||
|
||||
// Assert
|
||||
Assert.True(metadata.IsRequired);
|
||||
}
|
||||
|
||||
[DataContract]
|
||||
private class ClassWithDataMemberIsRequiredTrue
|
||||
{
|
||||
[DataMember(IsRequired = true)]
|
||||
public string TheProperty { get; set; }
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ClassWithDataMemberIsRequiredFalse_NoValidator()
|
||||
{
|
||||
// Arrange
|
||||
var metadataProvider = TestModelMetadataProvider.CreateDefaultProvider();
|
||||
|
||||
// Act
|
||||
var metadata = metadataProvider.GetMetadataForProperty(
|
||||
typeof(ClassWithDataMemberIsRequiredFalse),
|
||||
"TheProperty");
|
||||
|
||||
// Assert
|
||||
Assert.False(metadata.IsRequired);
|
||||
}
|
||||
|
||||
[DataContract]
|
||||
private class ClassWithDataMemberIsRequiredFalse
|
||||
{
|
||||
[DataMember(IsRequired = false)]
|
||||
public int TheProperty { get; set; }
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ClassWithDataMemberIsRequiredTrueWithoutDataContract_NoValidator()
|
||||
{
|
||||
// Arrange
|
||||
var metadataProvider = TestModelMetadataProvider.CreateDefaultProvider();
|
||||
|
||||
// Act
|
||||
var metadata = metadataProvider.GetMetadataForProperty(
|
||||
typeof(ClassWithDataMemberIsRequiredTrueWithoutDataContract),
|
||||
"TheProperty");
|
||||
|
||||
// Assert
|
||||
Assert.False(metadata.IsRequired);
|
||||
}
|
||||
|
||||
private class ClassWithDataMemberIsRequiredTrueWithoutDataContract
|
||||
{
|
||||
[DataMember(IsRequired = true)]
|
||||
public int TheProperty { get; set; }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -110,6 +110,20 @@ namespace Microsoft.AspNet.Mvc.ModelBinding.Metadata
|
|||
Assert.Equal("OnPropertyType", Assert.IsType<ModelAttribute>(attributes[1]).Value);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void GetMetadataForProperties_ExcludesHiddenProperties()
|
||||
{
|
||||
// Arrange
|
||||
var provider = CreateProvider();
|
||||
|
||||
// Act
|
||||
var metadata = provider.GetMetadataForProperties(typeof(DerivedModelWithHiding));
|
||||
|
||||
// Assert
|
||||
var propertyMetadata = Assert.Single(metadata);
|
||||
Assert.Equal(typeof(string), propertyMetadata.ModelType);
|
||||
}
|
||||
|
||||
private static DefaultModelMetadataProvider CreateProvider()
|
||||
{
|
||||
return new DefaultModelMetadataProvider(new EmptyCompositeMetadataDetailsProvider());
|
||||
|
|
@ -149,5 +163,15 @@ namespace Microsoft.AspNet.Mvc.ModelBinding.Metadata
|
|||
private void GetMetadataForParameterTestMethod([Model("OnParameter")] ModelType parameter)
|
||||
{
|
||||
}
|
||||
|
||||
private class BaseModelWithHiding
|
||||
{
|
||||
public int Property { get; set; }
|
||||
}
|
||||
|
||||
private class DerivedModelWithHiding : BaseModelWithHiding
|
||||
{
|
||||
public new string Property { get; set; }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -701,7 +701,7 @@ namespace Microsoft.AspNet.Mvc.ModelBinding.Metadata
|
|||
: base(new DefaultCompositeMetadataDetailsProvider(new IMetadataDetailsProvider[]
|
||||
{
|
||||
new DefaultBindingMetadataProvider(),
|
||||
new DataAnnotationsMetadataDetailsProvider(),
|
||||
new DataAnnotationsMetadataProvider(),
|
||||
}))
|
||||
{
|
||||
_attributes = attributes;
|
||||
|
|
|
|||
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue