众所周知,在使用DataAnnotations数据验证的时候,特别是针对同一个InputDto的多个属性进行对比的时候,例如起始日期不能大于结束日期,我们需要在Attribute中知道当前InputDto对象的类型和对象值,以便进行两个属性的对比。
做到以上操作,我们需要使用ValidationAttribute.IsValid(object value, ValidationContext validationContext)方法,其中ValidationContext对象会提供当前InputDto的类型和参数值。
如果我们要实现大于或等于的特性验证,代码如下:
//大于或等于的特性验证 public class GreaterOrEqualAttribute : ValidationAttribute { //需要被对比的属性名称 public string PropertyName { get;} public GreaterOrEqualAttribute(string propertyName) { PropertyName = propertyName?.Trim()??""; } protected override ValidationResult IsValid(object value, ValidationContext validationContext) { if(PropertyName.IsNullOrEmpty()) return new ValidationResult($"{nameof(GreaterOrEqualAttribute)}.{nameof(PropertyName)}参数不能为空值"); //获取PropertyName的属性值 var propertyInfo = validationContext.ObjectType.GetProperty(PropertyName); var propertyValue = propertyInfo?.GetValue(validationContext.ObjectInstance, null); //如果给定对比的值为null,则返回成功 if(propertyValue==null) return ValidationResult.Success; var thisTypeCode = Convert.GetTypeCode(value); var thatTypeCode = Convert.GetTypeCode(propertyValue); if(thisTypeCode!=thatTypeCode) return new ValidationResult($"{validationContext.ObjectType.Name}.{PropertyName}与{validationContext.ObjectType.Name}.{validationContext.DisplayName}的类型不匹配"); dynamic thisValue = Convert.ChangeType(value, thisTypeCode); dynamic thatValue = Convert.ChangeType(propertyValue, thatTypeCode); //如果当前值大于或等于给定值,则返回成功 if(thisValue>=thatValue) return ValidationResult.Success; return new ValidationResult(ErrorMessage.IsNullOrEmpty()? $"{validationContext.ObjectType.Name}.{PropertyName}必须大于或等于{validationContext.ObjectType.Name}.{validationContext.DisplayName}":ErrorMessage); } }
其中validationContext.ObjectType就是InputDto对象的类型,validationContext.ObjectInstance是InputDto对象的实例,有了这两个参数,我们可以在数据验证中尽情的操作。
接下来我们定义一个InputDto类型来测试一下,验证起始时间和结束时间。代码如下:
public class InputDto { //起始时间 public DateTime? BeginDate { get; set; } = DateTime.Now; //结束时间 [GreaterOrEqual(nameof(BeginDate))] public DateTime? EndDate { get; set; } = DateTime.Now; }
测试结果如下: