众所周知,在使用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;
    }

测试结果如下:

 

 posted on 2018-10-25 17:05  F风  阅读(605)  评论(0编辑  收藏  举报