Reviving MinLength and MaxLength attribute adapters
This commit is contained in:
parent
b0c7dc9220
commit
2ba8780ee0
|
|
@ -84,7 +84,11 @@
|
||||||
<Compile Include="Validation\IModelValidator.cs" />
|
<Compile Include="Validation\IModelValidator.cs" />
|
||||||
<Compile Include="Validation\IModelValidatorProvider.cs" />
|
<Compile Include="Validation\IModelValidatorProvider.cs" />
|
||||||
<Compile Include="Validation\InvalidModelValidatorProvider.cs" />
|
<Compile Include="Validation\InvalidModelValidatorProvider.cs" />
|
||||||
|
<Compile Include="Validation\MaxLengthAttributeAdapter.cs" />
|
||||||
|
<Compile Include="Validation\MinLengthAttributeAdapter.cs" />
|
||||||
<Compile Include="Validation\ModelClientValidationEqualToRule.cs" />
|
<Compile Include="Validation\ModelClientValidationEqualToRule.cs" />
|
||||||
|
<Compile Include="Validation\ModelClientValidationMaxLengthRule.cs" />
|
||||||
|
<Compile Include="Validation\ModelClientValidationMinLengthRule.cs" />
|
||||||
<Compile Include="Validation\ModelClientValidationRegexRule.cs" />
|
<Compile Include="Validation\ModelClientValidationRegexRule.cs" />
|
||||||
<Compile Include="Validation\ModelClientValidationRule.cs" />
|
<Compile Include="Validation\ModelClientValidationRule.cs" />
|
||||||
<Compile Include="Validation\ModelValidatedEventArgs.cs" />
|
<Compile Include="Validation\ModelValidatedEventArgs.cs" />
|
||||||
|
|
|
||||||
|
|
@ -19,7 +19,7 @@ namespace Microsoft.AspNet.Mvc.ModelBinding
|
||||||
public class DataAnnotationsModelValidatorProvider : AssociatedValidatorProvider
|
public class DataAnnotationsModelValidatorProvider : AssociatedValidatorProvider
|
||||||
{
|
{
|
||||||
// A factory for validators based on ValidationAttribute.
|
// A factory for validators based on ValidationAttribute.
|
||||||
private delegate IModelValidator DataAnnotationsModelValidationFactory(ValidationAttribute attribute);
|
internal delegate IModelValidator DataAnnotationsModelValidationFactory(ValidationAttribute attribute);
|
||||||
|
|
||||||
// A factory for validators based on IValidatableObject
|
// A factory for validators based on IValidatableObject
|
||||||
private delegate IModelValidator DataAnnotationsValidatableObjectAdapterFactory();
|
private delegate IModelValidator DataAnnotationsValidatableObjectAdapterFactory();
|
||||||
|
|
@ -36,6 +36,11 @@ namespace Microsoft.AspNet.Mvc.ModelBinding
|
||||||
private static readonly DataAnnotationsValidatableObjectAdapterFactory _defaultValidatableFactory =
|
private static readonly DataAnnotationsValidatableObjectAdapterFactory _defaultValidatableFactory =
|
||||||
() => new ValidatableObjectAdapter();
|
() => new ValidatableObjectAdapter();
|
||||||
|
|
||||||
|
internal Dictionary<Type, DataAnnotationsModelValidationFactory> AttributeFactories
|
||||||
|
{
|
||||||
|
get { return _attributeFactories; }
|
||||||
|
}
|
||||||
|
|
||||||
private static bool AddImplicitRequiredAttributeForValueTypes
|
private static bool AddImplicitRequiredAttributeForValueTypes
|
||||||
{
|
{
|
||||||
get { return _addImplicitRequiredAttributeForValueTypes; }
|
get { return _addImplicitRequiredAttributeForValueTypes; }
|
||||||
|
|
@ -72,6 +77,15 @@ namespace Microsoft.AspNet.Mvc.ModelBinding
|
||||||
AddValidationAttributeAdapter(dict, typeof(RegularExpressionAttribute),
|
AddValidationAttributeAdapter(dict, typeof(RegularExpressionAttribute),
|
||||||
(attribute) => new RegularExpressionAttributeAdapter((RegularExpressionAttribute)attribute));
|
(attribute) => new RegularExpressionAttributeAdapter((RegularExpressionAttribute)attribute));
|
||||||
|
|
||||||
|
AddValidationAttributeAdapter(dict, typeof(MaxLengthAttribute),
|
||||||
|
(attribute) => new MaxLengthAttributeAdapter((MaxLengthAttribute)attribute));
|
||||||
|
|
||||||
|
AddValidationAttributeAdapter(dict, typeof(MinLengthAttribute),
|
||||||
|
(attribute) => new MinLengthAttributeAdapter((MinLengthAttribute)attribute));
|
||||||
|
|
||||||
|
AddValidationAttributeAdapter(dict, typeof(CompareAttribute),
|
||||||
|
(attribute) => new CompareAttributeAdapter((CompareAttribute)attribute));
|
||||||
|
|
||||||
AddDataTypeAttributeAdapter(dict, typeof(UrlAttribute), "url");
|
AddDataTypeAttributeAdapter(dict, typeof(UrlAttribute), "url");
|
||||||
|
|
||||||
return dict;
|
return dict;
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,20 @@
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.ComponentModel.DataAnnotations;
|
||||||
|
|
||||||
|
namespace Microsoft.AspNet.Mvc.ModelBinding
|
||||||
|
{
|
||||||
|
public class MaxLengthAttributeAdapter : DataAnnotationsModelValidator<MaxLengthAttribute>
|
||||||
|
{
|
||||||
|
public MaxLengthAttributeAdapter(MaxLengthAttribute attribute)
|
||||||
|
: base(attribute)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public override IEnumerable<ModelClientValidationRule> GetClientValidationRules(
|
||||||
|
[NotNull] ClientModelValidationContext context)
|
||||||
|
{
|
||||||
|
var message = GetErrorMessage(context.ModelMetadata);
|
||||||
|
return new[] { new ModelClientValidationMaxLengthRule(message, Attribute.Length) };
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,20 @@
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.ComponentModel.DataAnnotations;
|
||||||
|
|
||||||
|
namespace Microsoft.AspNet.Mvc.ModelBinding
|
||||||
|
{
|
||||||
|
public class MinLengthAttributeAdapter : DataAnnotationsModelValidator<MinLengthAttribute>
|
||||||
|
{
|
||||||
|
public MinLengthAttributeAdapter(MinLengthAttribute attribute)
|
||||||
|
: base(attribute)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public override IEnumerable<ModelClientValidationRule> GetClientValidationRules(
|
||||||
|
[NotNull] ClientModelValidationContext context)
|
||||||
|
{
|
||||||
|
var message = GetErrorMessage(context.ModelMetadata);
|
||||||
|
return new[] { new ModelClientValidationMinLengthRule(message, Attribute.Length) };
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,14 @@
|
||||||
|
namespace Microsoft.AspNet.Mvc.ModelBinding
|
||||||
|
{
|
||||||
|
public class ModelClientValidationMaxLengthRule : ModelClientValidationRule
|
||||||
|
{
|
||||||
|
private const string MaxLengthValidationType = "maxlength";
|
||||||
|
private const string MaxLengthValidationParameter = "max";
|
||||||
|
|
||||||
|
public ModelClientValidationMaxLengthRule([NotNull] string errorMessage, int maximumLength)
|
||||||
|
: base(MaxLengthValidationType, errorMessage)
|
||||||
|
{
|
||||||
|
ValidationParameters[MaxLengthValidationParameter] = maximumLength;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,14 @@
|
||||||
|
namespace Microsoft.AspNet.Mvc.ModelBinding
|
||||||
|
{
|
||||||
|
public class ModelClientValidationMinLengthRule : ModelClientValidationRule
|
||||||
|
{
|
||||||
|
private const string MinLengthValidationType = "minlength";
|
||||||
|
private const string MinLengthValidationParameter = "min";
|
||||||
|
|
||||||
|
public ModelClientValidationMinLengthRule([NotNull] string errorMessage, int minimumLength)
|
||||||
|
: base(MinLengthValidationType, errorMessage)
|
||||||
|
{
|
||||||
|
ValidationParameters[MinLengthValidationParameter] = minimumLength;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -1,4 +1,5 @@
|
||||||
using System.Collections.Generic;
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
using System.ComponentModel.DataAnnotations;
|
using System.ComponentModel.DataAnnotations;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
#if NET45
|
#if NET45
|
||||||
|
|
@ -12,6 +13,51 @@ namespace Microsoft.AspNet.Mvc.ModelBinding
|
||||||
{
|
{
|
||||||
private readonly DataAnnotationsModelMetadataProvider _metadataProvider = new DataAnnotationsModelMetadataProvider();
|
private readonly DataAnnotationsModelMetadataProvider _metadataProvider = new DataAnnotationsModelMetadataProvider();
|
||||||
|
|
||||||
|
public static IEnumerable<object[]> KnownAdapterTypeData
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
yield return new object[] { typeof(RegularExpressionAttribute),
|
||||||
|
new RegularExpressionAttribute("abc"),
|
||||||
|
typeof(RegularExpressionAttributeAdapter), null };
|
||||||
|
|
||||||
|
yield return new object[] { typeof(MaxLengthAttribute),
|
||||||
|
new MaxLengthAttribute(),
|
||||||
|
typeof(MaxLengthAttributeAdapter), null };
|
||||||
|
|
||||||
|
yield return new object[] { typeof(MinLengthAttribute),
|
||||||
|
new MinLengthAttribute(1),
|
||||||
|
typeof(MinLengthAttributeAdapter), null };
|
||||||
|
|
||||||
|
yield return new object[] { typeof(UrlAttribute),
|
||||||
|
new UrlAttribute(),
|
||||||
|
typeof(DataTypeAttributeAdapter), "url" };
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[Theory]
|
||||||
|
[MemberData("KnownAdapterTypeData")]
|
||||||
|
public void AdapterForKnownTypeRegistered(Type attributeType,
|
||||||
|
ValidationAttribute validationAttr,
|
||||||
|
Type expectedAdapterType,
|
||||||
|
string expectedRuleName)
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var adapters = new DataAnnotationsModelValidatorProvider().AttributeFactories;
|
||||||
|
var adapterFactory = adapters.Single(kvp => kvp.Key == attributeType).Value;
|
||||||
|
|
||||||
|
// Act
|
||||||
|
var adapter = adapterFactory(validationAttr);
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
Assert.IsType(expectedAdapterType, adapter);
|
||||||
|
if (expectedRuleName != null)
|
||||||
|
{
|
||||||
|
var dataTypeAdapter = Assert.IsType<DataTypeAttributeAdapter>(adapter);
|
||||||
|
Assert.Equal(expectedRuleName, dataTypeAdapter.RuleName);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
public void UnknownValidationAttributeGetsDefaultAdapter()
|
public void UnknownValidationAttributeGetsDefaultAdapter()
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,55 @@
|
||||||
|
using System.ComponentModel.DataAnnotations;
|
||||||
|
using Microsoft.AspNet.Testing;
|
||||||
|
using Xunit;
|
||||||
|
|
||||||
|
namespace Microsoft.AspNet.Mvc.ModelBinding
|
||||||
|
{
|
||||||
|
public class MaxLengthAttributeAdapterTest
|
||||||
|
{
|
||||||
|
[Fact]
|
||||||
|
[ReplaceCulture]
|
||||||
|
public void ClientRulesWithMaxLengthAttribute()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var provider = new DataAnnotationsModelMetadataProvider();
|
||||||
|
var metadata = provider.GetMetadataForProperty(() => null, typeof(string), "Length");
|
||||||
|
var attribute = new MaxLengthAttribute(10);
|
||||||
|
var adapter = new MaxLengthAttributeAdapter(attribute);
|
||||||
|
var context = new ClientModelValidationContext(metadata, provider);
|
||||||
|
|
||||||
|
// Act
|
||||||
|
var rules = adapter.GetClientValidationRules(context);
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
var rule = Assert.Single(rules);
|
||||||
|
Assert.Equal("maxlength", rule.ValidationType);
|
||||||
|
Assert.Equal(1, rule.ValidationParameters.Count);
|
||||||
|
Assert.Equal(10, rule.ValidationParameters["max"]);
|
||||||
|
Assert.Equal("The field Length must be a string or array type with a maximum length of '10'.", rule.ErrorMessage);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
[ReplaceCulture]
|
||||||
|
public void ClientRulesWithMaxLengthAttributeAndCustomMessage()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var propertyName = "Length";
|
||||||
|
var message = "{0} must be at most {1}";
|
||||||
|
var provider = new DataAnnotationsModelMetadataProvider();
|
||||||
|
var metadata = provider.GetMetadataForProperty(() => null, typeof(string), propertyName);
|
||||||
|
var attribute = new MaxLengthAttribute(5) { ErrorMessage = message };
|
||||||
|
var adapter = new MaxLengthAttributeAdapter(attribute);
|
||||||
|
var context = new ClientModelValidationContext(metadata, provider);
|
||||||
|
|
||||||
|
// Act
|
||||||
|
var rules = adapter.GetClientValidationRules(context);
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
var rule = Assert.Single(rules);
|
||||||
|
Assert.Equal("maxlength", rule.ValidationType);
|
||||||
|
Assert.Equal(1, rule.ValidationParameters.Count);
|
||||||
|
Assert.Equal(5, rule.ValidationParameters["max"]);
|
||||||
|
Assert.Equal("Length must be at most 5", rule.ErrorMessage);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,55 @@
|
||||||
|
using System.ComponentModel.DataAnnotations;
|
||||||
|
using Microsoft.AspNet.Testing;
|
||||||
|
using Xunit;
|
||||||
|
|
||||||
|
namespace Microsoft.AspNet.Mvc.ModelBinding
|
||||||
|
{
|
||||||
|
public class MinLengthAttributeAdapterTest
|
||||||
|
{
|
||||||
|
[Fact]
|
||||||
|
[ReplaceCulture]
|
||||||
|
public void ClientRulesWithMinLengthAttribute()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var provider = new DataAnnotationsModelMetadataProvider();
|
||||||
|
var metadata = provider.GetMetadataForProperty(() => null, typeof(string), "Length");
|
||||||
|
var attribute = new MinLengthAttribute(6);
|
||||||
|
var adapter = new MinLengthAttributeAdapter(attribute);
|
||||||
|
var context = new ClientModelValidationContext(metadata, provider);
|
||||||
|
|
||||||
|
// Act
|
||||||
|
var rules = adapter.GetClientValidationRules(context);
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
var rule = Assert.Single(rules);
|
||||||
|
Assert.Equal("minlength", rule.ValidationType);
|
||||||
|
Assert.Equal(1, rule.ValidationParameters.Count);
|
||||||
|
Assert.Equal(6, rule.ValidationParameters["min"]);
|
||||||
|
Assert.Equal("The field Length must be a string or array type with a minimum length of '6'.", rule.ErrorMessage);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
[ReplaceCulture]
|
||||||
|
public void ClientRulesWithMinLengthAttributeAndCustomMessage()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var propertyName = "Length";
|
||||||
|
var message = "Array must have at least {1} items.";
|
||||||
|
var provider = new DataAnnotationsModelMetadataProvider();
|
||||||
|
var metadata = provider.GetMetadataForProperty(() => null, typeof(string), propertyName);
|
||||||
|
var attribute = new MinLengthAttribute(2) { ErrorMessage = message };
|
||||||
|
var adapter = new MinLengthAttributeAdapter(attribute);
|
||||||
|
var context = new ClientModelValidationContext(metadata, provider);
|
||||||
|
|
||||||
|
// Act
|
||||||
|
var rules = adapter.GetClientValidationRules(context);
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
var rule = Assert.Single(rules);
|
||||||
|
Assert.Equal("minlength", rule.ValidationType);
|
||||||
|
Assert.Equal(1, rule.ValidationParameters.Count);
|
||||||
|
Assert.Equal(2, rule.ValidationParameters["min"]);
|
||||||
|
Assert.Equal("Array must have at least 2 items.", rule.ErrorMessage);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
Reference in New Issue