Removed use of LINQ and added some optimizations in ValidationVisitor
This commit is contained in:
parent
bebd3dc9a0
commit
f7a211c095
|
|
@ -10,12 +10,6 @@ namespace Microsoft.AspNet.Mvc.ModelBinding.Validation
|
|||
/// </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>
|
||||
|
|
|
|||
|
|
@ -22,7 +22,7 @@ namespace Microsoft.AspNet.Mvc.ModelBinding.Validation
|
|||
/// <summary>
|
||||
/// Gets the <see cref="ModelBinding.ModelMetadata"/>.
|
||||
/// </summary>
|
||||
public ModelMetadata ModelMetadata { get; }
|
||||
public ModelMetadata ModelMetadata { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the validator metadata.
|
||||
|
|
|
|||
|
|
@ -3,7 +3,6 @@
|
|||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Runtime.CompilerServices;
|
||||
|
||||
namespace Microsoft.AspNet.Mvc.ModelBinding.Validation
|
||||
|
|
@ -23,6 +22,7 @@ namespace Microsoft.AspNet.Mvc.ModelBinding.Validation
|
|||
private string _key;
|
||||
private object _model;
|
||||
private ModelMetadata _metadata;
|
||||
private ModelValidatorProviderContext _context;
|
||||
private IValidationStrategy _strategy;
|
||||
|
||||
private HashSet<object> _currentPath;
|
||||
|
|
@ -94,7 +94,7 @@ namespace Microsoft.AspNet.Mvc.ModelBinding.Validation
|
|||
var state = _modelState.GetValidationState(_key);
|
||||
if (state == ModelValidationState.Unvalidated)
|
||||
{
|
||||
var validators = GetValidators(_metadata);
|
||||
var validators = GetValidators();
|
||||
|
||||
var count = validators.Count;
|
||||
if (count > 0)
|
||||
|
|
@ -255,11 +255,23 @@ namespace Microsoft.AspNet.Mvc.ModelBinding.Validation
|
|||
return isValid;
|
||||
}
|
||||
|
||||
private IList<IModelValidator> GetValidators(ModelMetadata metadata)
|
||||
private IList<IModelValidator> GetValidators()
|
||||
{
|
||||
var context = new ModelValidatorProviderContext(metadata);
|
||||
_validatorProvider.GetValidators(context);
|
||||
return context.Validators.OrderBy(v => v, ValidatorOrderComparer.Instance).ToList();
|
||||
if (_context == null)
|
||||
{
|
||||
_context = new ModelValidatorProviderContext(_metadata);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Reusing the context so we don't allocate a new context and list
|
||||
// for every property that gets validated.
|
||||
_context.ModelMetadata = _metadata;
|
||||
_context.Validators.Clear();
|
||||
}
|
||||
|
||||
_validatorProvider.GetValidators(_context);
|
||||
|
||||
return _context.Validators;
|
||||
}
|
||||
|
||||
private void SuppressValidation(string key)
|
||||
|
|
@ -348,19 +360,5 @@ namespace Microsoft.AspNet.Mvc.ModelBinding.Validation
|
|||
_visitor._currentPath.Remove(_newModel);
|
||||
}
|
||||
}
|
||||
|
||||
// Sorts validators based on whether or not they are 'required'. We want to run
|
||||
// 'required' validators first so that we get the best possible error message.
|
||||
private class ValidatorOrderComparer : IComparer<IModelValidator>
|
||||
{
|
||||
public static readonly ValidatorOrderComparer Instance = new ValidatorOrderComparer();
|
||||
|
||||
public int Compare(IModelValidator x, IModelValidator y)
|
||||
{
|
||||
var xScore = x.IsRequired ? 0 : 1;
|
||||
var yScore = y.IsRequired ? 0 : 1;
|
||||
return xScore.CompareTo(yScore);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -26,11 +26,6 @@ namespace Microsoft.AspNet.Mvc.ModelBinding.Validation
|
|||
|
||||
public ValidationAttribute Attribute { get; }
|
||||
|
||||
public bool IsRequired
|
||||
{
|
||||
get { return Attribute is RequiredAttribute; }
|
||||
}
|
||||
|
||||
public IEnumerable<ModelValidationResult> Validate(ModelValidationContext validationContext)
|
||||
{
|
||||
var metadata = validationContext.Metadata;
|
||||
|
|
|
|||
|
|
@ -1,9 +1,7 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System;
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using Microsoft.Extensions.Localization;
|
||||
using Microsoft.Extensions.OptionsModel;
|
||||
|
|
@ -43,9 +41,26 @@ namespace Microsoft.AspNet.Mvc.ModelBinding.Validation
|
|||
_stringLocalizerFactory);
|
||||
}
|
||||
|
||||
foreach (var attribute in context.ValidatorMetadata.OfType<ValidationAttribute>())
|
||||
for (var i = 0; i < context.ValidatorMetadata.Count; i++)
|
||||
{
|
||||
context.Validators.Add(new DataAnnotationsModelValidator(attribute, stringLocalizer));
|
||||
var attribute = context.ValidatorMetadata[i] as ValidationAttribute;
|
||||
if (attribute == null)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
var validator = new DataAnnotationsModelValidator(attribute, stringLocalizer);
|
||||
|
||||
// Inserts validators based on whether or not they are 'required'. We want to run
|
||||
// 'required' validators first so that we get the best possible error message.
|
||||
if (attribute is RequiredAttribute)
|
||||
{
|
||||
context.Validators.Insert(0, validator);
|
||||
}
|
||||
else
|
||||
{
|
||||
context.Validators.Add(validator);
|
||||
}
|
||||
}
|
||||
|
||||
// Produce a validator if the type supports IValidatableObject
|
||||
|
|
|
|||
|
|
@ -11,11 +11,6 @@ namespace Microsoft.AspNet.Mvc.ModelBinding.Validation
|
|||
{
|
||||
public class ValidatableObjectAdapter : IModelValidator
|
||||
{
|
||||
public bool IsRequired
|
||||
{
|
||||
get { return false; }
|
||||
}
|
||||
|
||||
public IEnumerable<ModelValidationResult> Validate(ModelValidationContext context)
|
||||
{
|
||||
var model = context.Model;
|
||||
|
|
|
|||
|
|
@ -70,14 +70,6 @@ namespace Microsoft.AspNet.Mvc.ModelBinding.Metadata
|
|||
|
||||
private class TestModelValidationAttribute : Attribute, IModelValidator
|
||||
{
|
||||
public bool IsRequired
|
||||
{
|
||||
get
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
}
|
||||
|
||||
public IEnumerable<ModelValidationResult> Validate(ModelValidationContext context)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
|
|
@ -94,14 +86,6 @@ namespace Microsoft.AspNet.Mvc.ModelBinding.Metadata
|
|||
|
||||
private class TestValidationAttribute : Attribute, IModelValidator, IClientModelValidator
|
||||
{
|
||||
public bool IsRequired
|
||||
{
|
||||
get
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
}
|
||||
|
||||
public IEnumerable<ModelClientValidationRule> GetClientValidationRules(ClientModelValidationContext context)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
|
|
|
|||
|
|
@ -171,14 +171,6 @@ namespace Microsoft.AspNet.Mvc.ModelBinding.Validation
|
|||
{
|
||||
public string Tag { get; set; }
|
||||
|
||||
public bool IsRequired
|
||||
{
|
||||
get
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
}
|
||||
|
||||
public IEnumerable<ModelValidationResult> Validate(ModelValidationContext context)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
|
|
|
|||
|
|
@ -38,6 +38,27 @@ namespace Microsoft.AspNet.Mvc.ModelBinding.Validation
|
|||
}
|
||||
#endif
|
||||
|
||||
[Fact]
|
||||
public void GetValidators_InsertsRequiredValidatorsFirst()
|
||||
{
|
||||
var provider = new DataAnnotationsModelValidatorProvider(
|
||||
new TestOptionsManager<MvcDataAnnotationsLocalizationOptions>(),
|
||||
stringLocalizerFactory: null);
|
||||
var metadata = _metadataProvider.GetMetadataForProperty(
|
||||
typeof(ClassWithProperty),
|
||||
"PropertyWithMultipleValidationAttributes");
|
||||
|
||||
var providerContext = new ModelValidatorProviderContext(metadata);
|
||||
|
||||
// Act
|
||||
provider.GetValidators(providerContext);
|
||||
|
||||
// Assert
|
||||
Assert.Equal(4, providerContext.Validators.Count);
|
||||
Assert.IsAssignableFrom<RequiredAttribute>(((DataAnnotationsModelValidator)providerContext.Validators[0]).Attribute);
|
||||
Assert.IsAssignableFrom<RequiredAttribute>(((DataAnnotationsModelValidator)providerContext.Validators[1]).Attribute);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void UnknownValidationAttributeGetsDefaultAdapter()
|
||||
{
|
||||
|
|
@ -130,5 +151,30 @@ namespace Microsoft.AspNet.Mvc.ModelBinding.Validation
|
|||
|
||||
public int WithoutAttribute { get; set; }
|
||||
}
|
||||
|
||||
private class ClassWithProperty
|
||||
{
|
||||
[CustomNonRequiredAttribute1]
|
||||
[CustomNonRequiredAttribute2]
|
||||
[CustomRequiredAttribute1]
|
||||
[CustomRequiredAttribute2]
|
||||
public string PropertyWithMultipleValidationAttributes { get; set; }
|
||||
}
|
||||
|
||||
public class CustomRequiredAttribute1 : RequiredAttribute
|
||||
{
|
||||
}
|
||||
|
||||
public class CustomRequiredAttribute2 : RequiredAttribute
|
||||
{
|
||||
}
|
||||
|
||||
public class CustomNonRequiredAttribute1 : ValidationAttribute
|
||||
{
|
||||
}
|
||||
|
||||
public class CustomNonRequiredAttribute2 : ValidationAttribute
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -294,17 +294,6 @@ namespace Microsoft.AspNet.Mvc.ModelBinding.Validation
|
|||
}
|
||||
#endif
|
||||
|
||||
[Fact]
|
||||
public void IsRequiredTests()
|
||||
{
|
||||
// Arrange & Act & Assert
|
||||
Assert.False(new DataAnnotationsModelValidator(new RangeAttribute(10, 20), stringLocalizer: null)
|
||||
.IsRequired);
|
||||
Assert.True(new DataAnnotationsModelValidator(new RequiredAttribute(), stringLocalizer: null).IsRequired);
|
||||
Assert.True(new DataAnnotationsModelValidator(new DerivedRequiredAttribute(), stringLocalizer: null)
|
||||
.IsRequired);
|
||||
}
|
||||
|
||||
private class DerivedRequiredAttribute : RequiredAttribute
|
||||
{
|
||||
}
|
||||
|
|
|
|||
|
|
@ -218,14 +218,6 @@ namespace Microsoft.AspNet.Mvc.ModelBinding.Validation
|
|||
{
|
||||
public string Tag { get; set; }
|
||||
|
||||
public bool IsRequired
|
||||
{
|
||||
get
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
}
|
||||
|
||||
public IEnumerable<ModelValidationResult> Validate(ModelValidationContext context)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
|
|
|
|||
Loading…
Reference in New Issue