Hus*_*man 17 c# validation asp.net-core
有没有办法在ASP.NET Core中创建自定义属性,以验证一个日期属性是否小于模型中的其他日期属性ValidationAttribute.
让我说我有这个:
public class MyViewModel
{
[Required]
[CompareDates]
public DateTime StartDate { get; set; }
[Required]
public DateTime EndDate { get; set; } = DateTime.Parse("3000-01-01");
}
Run Code Online (Sandbox Code Playgroud)
我想尝试使用这样的东西:
public class CompareDates : ValidationAttribute
{
public CompareDates()
: base("") { }
public override bool IsValid(object value)
{
return base.IsValid(value);
}
}
Run Code Online (Sandbox Code Playgroud)
我发现其他SO帖子建议使用另一个库,但我更喜欢坚持ValidationAttribute,如果这是可行的.
Ale*_*ore 35
您可以为比较两个属性创建自定义验证属性.这是服务器端验证:
public class MyViewModel
{
[DateLessThan("End", ErrorMessage = "Not valid")]
public DateTime Begin { get; set; }
public DateTime End { get; set; }
}
public class DateLessThanAttribute : ValidationAttribute
{
private readonly string _comparisonProperty;
public DateLessThanAttribute(string comparisonProperty)
{
_comparisonProperty = comparisonProperty;
}
protected override ValidationResult IsValid(object value, ValidationContext validationContext)
{
ErrorMessage = ErrorMessageString;
var currentValue = (DateTime)value;
var property = validationContext.ObjectType.GetProperty(_comparisonProperty);
if (property == null)
throw new ArgumentException("Property with this name not found");
var comparisonValue = (DateTime)property.GetValue(validationContext.ObjectInstance);
if (currentValue > comparisonValue)
return new ValidationResult(ErrorMessage);
return ValidationResult.Success;
}
}
Run Code Online (Sandbox Code Playgroud)
更新:如果您需要对此属性进行客户端验证,则需要实现一个IClientModelValidator接口:
public class DateLessThanAttribute : ValidationAttribute, IClientModelValidator
{
...
public void AddValidation(ClientModelValidationContext context)
{
var error = FormatErrorMessage(context.ModelMetadata.GetDisplayName());
context.Attributes.Add("data-val", "true");
context.Attributes.Add("data-val-error", error);
}
}
Run Code Online (Sandbox Code Playgroud)
该AddValidation方法将为您的输入添加属性context.Attributes.
你可以在这里阅读更多IClientModelValidator
Cur*_*dev 13
作为一种可能的选择自我验证:
您只需要IValidatableObject使用方法实现一个接口Validate,您可以在其中放置验证代码.
public class MyViewModel : IValidatableObject
{
[Required]
public DateTime StartDate { get; set; }
[Required]
public DateTime EndDate { get; set; } = DateTime.Parse("3000-01-01");
public IEnumerable<ValidationResult> Validate(ValidationContext validationContext)
{
int result = DateTime.Compare(StartDate , EndDate);
if (result < 0)
{
yield return new ValidationResult("start date must be less than the end date!", new [] { "ConfirmEmail" });
}
}
}
Run Code Online (Sandbox Code Playgroud)
基于 Jaime 的回答和 Jeffrey 关于需要单个属性的小于、小于或等于、等于、大于、大于或等于的评论。
下面的代码将使用单个属性处理所有条件。
public enum ComparisonType
{
LessThan,
LessThanOrEqualTo,
EqualTo,
GreaterThan,
GreaterThanOrEqualTo
}
[AttributeUsage(AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Parameter)]
public class ComparisonAttribute : ValidationAttribute
{
private readonly string _comparisonProperty;
private readonly ComparisonType _comparisonType;
public ComparisonAttribute(string comparisonProperty, ComparisonType comparisonType)
{
_comparisonProperty = comparisonProperty;
_comparisonType = comparisonType;
}
protected override ValidationResult IsValid(object value, ValidationContext validationContext)
{
ErrorMessage = ErrorMessageString;
if (value.GetType() == typeof(IComparable))
{
throw new ArgumentException("value has not implemented IComparable interface");
}
var currentValue = (IComparable) value;
var property = validationContext.ObjectType.GetProperty(_comparisonProperty);
if (property == null)
{
throw new ArgumentException("Comparison property with this name not found");
}
var comparisonValue = property.GetValue(validationContext.ObjectInstance);
if (comparisonValue.GetType() == typeof(IComparable))
{
throw new ArgumentException("Comparison property has not implemented IComparable interface");
}
if (!ReferenceEquals(value.GetType(), comparisonValue.GetType()))
{
throw new ArgumentException("The properties types must be the same");
}
bool compareToResult;
switch (_comparisonType)
{
case ComparisonType.LessThan:
compareToResult = currentValue.CompareTo((IComparable) comparisonValue) >= 0;
break;
case ComparisonType.LessThanOrEqualTo:
compareToResult = currentValue.CompareTo((IComparable) comparisonValue) > 0;
break;
case ComparisonType.EqualTo:
compareToResult = currentValue.CompareTo((IComparable) comparisonValue) != 0;
break;
case ComparisonType.GreaterThan:
compareToResult = currentValue.CompareTo((IComparable) comparisonValue) <= 0;
break;
case ComparisonType.GreaterThanOrEqualTo:
compareToResult = currentValue.CompareTo((IComparable) comparisonValue) < 0;
break;
default:
throw new ArgumentOutOfRangeException();
}
return compareToResult ? new ValidationResult(ErrorMessage) : ValidationResult.Success;
}
}
Run Code Online (Sandbox Code Playgroud)
在预订上下文中,示例如下:
public DateTime CheckInDate { get; set; }
[Comparison("CheckInDate", ComparisonType.EqualTo, ErrorMessage = "CheckOutDate must be equal to CheckInDate")]
public DateTime CheckOutDate { get; set; }
Run Code Online (Sandbox Code Playgroud)
根据 Alexander Gore 的回复,我建议进行更好的通用验证(并且它与 .Net core 兼容)。当您想要使用 GreatherThan 或 LessThan 逻辑(无论是什么类型)比较属性时,您可以验证它们是否已实现该IComparable接口。如果两个属性都有效,您可以使用该CompareTo实现。DateTime此规则也适用于和 数字类型
少于
[AttributeUsage(AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Parameter)]
public class LessThanAttribute : ValidationAttribute
{
private readonly string _comparisonProperty;
public LessThanAttribute(string comparisonProperty)
{
_comparisonProperty = comparisonProperty;
}
protected override ValidationResult IsValid(object value, ValidationContext validationContext)
{
ErrorMessage = ErrorMessageString;
if (value.GetType() == typeof(IComparable))
{
throw new ArgumentException("value has not implemented IComparable interface");
}
var currentValue = (IComparable)value;
var property = validationContext.ObjectType.GetProperty(_comparisonProperty);
if (property == null)
{
throw new ArgumentException("Comparison property with this name not found");
}
var comparisonValue = property.GetValue(validationContext.ObjectInstance);
if (comparisonValue.GetType() == typeof(IComparable))
{
throw new ArgumentException("Comparison property has not implemented IComparable interface");
}
if (!ReferenceEquals(value.GetType(), comparisonValue.GetType()))
{
throw new ArgumentException("The properties types must be the same");
}
if (currentValue.CompareTo((IComparable)comparisonValue) >= 0)
{
return new ValidationResult(ErrorMessage);
}
return ValidationResult.Success;
}
}
Run Code Online (Sandbox Code Playgroud)
比...更棒
[AttributeUsage(AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Parameter)]
public class GreaterThanAttribute : ValidationAttribute
{
private readonly string _comparisonProperty;
public GreaterThanAttribute(string comparisonProperty)
{
_comparisonProperty = comparisonProperty;
}
protected override ValidationResult IsValid(object value, ValidationContext validationContext)
{
ErrorMessage = ErrorMessageString;
if (value.GetType() == typeof(IComparable))
{
throw new ArgumentException("value has not implemented IComparable interface");
}
var currentValue = (IComparable)value;
var property = validationContext.ObjectType.GetProperty(_comparisonProperty);
if (property == null)
{
throw new ArgumentException("Comparison property with this name not found");
}
var comparisonValue = property.GetValue(validationContext.ObjectInstance);
if (comparisonValue.GetType() == typeof(IComparable))
{
throw new ArgumentException("Comparison property has not implemented IComparable interface");
}
if (!ReferenceEquals(value.GetType(), comparisonValue.GetType()))
{
throw new ArgumentException("The properties types must be the same");
}
if (currentValue.CompareTo((IComparable)comparisonValue) < 0)
{
return new ValidationResult(ErrorMessage);
}
return ValidationResult.Success;
}
}
Run Code Online (Sandbox Code Playgroud)
在预订上下文中,示例如下:
public DateTime CheckInDate { get; set; }
[GreaterThan("CheckInDate", ErrorMessage = "CheckOutDate must be greater than CheckInDate")]
public DateTime CheckOutDate { get; set; }
Run Code Online (Sandbox Code Playgroud)
我创建了一个包含 ASP.NET Core 中最常见的自定义验证的库。该库还具有所有服务器端自定义验证的客户端验证。该库通过单个属性解决了 OP 的问题,如下所示:
\n\n// If you want the StartDate to be smaller than the EndDate:\n[CompareTo(nameof(EndDate), ComparisionType.SmallerThan)] \npublic DateTime StartDate { get; set; }\nRun Code Online (Sandbox Code Playgroud)\n\n以下是该库的 GitHub 链接:AspNetCore.CustomValidation
\n\n目前,该库包含以下验证属性:
\n\n1. FileAttribute - 验证文件类型、文件最大大小、文件最小大小;
\n\n2. MaxAgeAttribute - 根据 DateTime 类型的出生日期值验证最大年龄;
\n\n3. MinAgeAttribute - 根据 DateTime 类型的出生日期值验证所需的最低年龄;
\n\n4. MaxDateAttribute - 设置日期时间字段的最大值验证;
\n\n5. MinDateAttribute - 设置日期时间字段的最小值验证;
\n\n6. CompareToAttibute \xe2\x80\x93 将一个属性值与另一个属性值进行比较;
\n\n7. TinyMceRequiredAttribute - 在在线文本编辑器(如 TinyMCE、CkEditor 等)上强制执行必需的验证属性。
\n| 归档时间: |
|
| 查看次数: |
16023 次 |
| 最近记录: |