在Asp.Net MVC中实现CompareValues标签对Model中的属性进行验证

在Asp.Net MVC中可以用继承ValidationAttribute的方式,自定制实现Model两个中两个属性值的比较验证

具体应用场景为:要对两个属性值的大小进行验证

代码如下所示:

    /// <summary>

    /// Specifies that the field must compare favourably with the named field, if objects to check are not of the same type

    /// false will be return

    /// </summary>

    public class CompareValuesAttribute : ValidationAttribute

    {

        /// <summary>

        /// The other property to compare to

        /// </summary>

        public string OtherProperty { get; set; }



        public CompareValues Criteria { get; set; }



        /// <summary>

        /// Creates the attribute

        /// </summary>

        /// <param name="otherProperty">The other property to compare to</param>

        public CompareValuesAttribute(string otherProperty, CompareValues criteria)

        {

            if (otherProperty == null)

                throw new ArgumentNullException("otherProperty");



            OtherProperty = otherProperty;

            Criteria = criteria;

        }



        /// <summary>

        /// Determines whether the specified value of the object is valid.  For this to be the case, the objects must be of the same type

        /// and satisfy the comparison criteria. Null values will return false in all cases except when both

        /// objects are null.  The objects will need to implement IComparable for the GreaterThan,LessThan,GreatThanOrEqualTo and LessThanOrEqualTo instances

        /// </summary>

        /// <param name="value">The value of the object to validate</param>

        /// <param name="validationContext">The validation context</param>

        /// <returns>A validation result if the object is invalid, null if the object is valid</returns>

        protected override ValidationResult IsValid(object value, ValidationContext validationContext)

        {

            // the the other property

            var property = validationContext.ObjectType.GetProperty(OtherProperty);



            // check it is not null

            if (property == null)

                return new ValidationResult(String.Format("Unknown property: {0}.", OtherProperty));



            // check types

            var memberName = validationContext.ObjectType.GetProperties().Where(p => p.GetCustomAttributes(false).OfType<DisplayAttribute>().Any(a => a.Name == validationContext.DisplayName)).Select(p => p.Name).FirstOrDefault();

            if (memberName == null)

            {

                memberName = validationContext.DisplayName;

            }

            if (validationContext.ObjectType.GetProperty(memberName).PropertyType != property.PropertyType)

                return new ValidationResult(String.Format("The types of {0} and {1} must be the same.", memberName, OtherProperty));



            // get the other value

            var other = property.GetValue(validationContext.ObjectInstance, null);



            // equals to comparison,

            if (Criteria == CompareValues.EqualTo)

            {

                if (Object.Equals(value, other))

                    return null;

            }

            else if (Criteria == CompareValues.NotEqualTo)

            {

                if (!Object.Equals(value, other))

                    return null;

            }

            else

            {

                // check that both objects are IComparables

                if (!(value is IComparable) || !(other is IComparable))

                    return new ValidationResult(String.Format("{0} and {1} must both implement IComparable", validationContext.DisplayName, OtherProperty));



                // compare the objects

                var result = Comparer.Default.Compare(value, other);



                switch (Criteria)

                {

                    case CompareValues.GreaterThan:

                        if (result > 0)

                            return null;

                        break;

                    case CompareValues.LessThan:

                        if (result < 0)

                            return null;

                        break;

                    case CompareValues.GreatThanOrEqualTo:

                        if (result >= 0)

                            return null;

                        break;

                    case CompareValues.LessThanOrEqualTo:

                        if (result <= 0)

                            return null;

                        break;

                }

            }



            // got this far must mean the items don't meet the comparison criteria

            return new ValidationResult(ErrorMessage);

        }

    }



    /// <summary>

    /// Indicates a comparison criteria used by the CompareValues attribute

    /// </summary>

    public enum CompareValues

    {

        EqualTo,

        NotEqualTo,

        GreaterThan,

        LessThan,

        GreatThanOrEqualTo,

        LessThanOrEqualTo

    }

 

应用的时候直接在指定的属性上添加此CompareValuesAttribute标签即可

【注:第一个参数是要与之比较的属性名,第二个参数表示两个属性值之间的大小关系,第三个参数表示错误提示信息】

public class EricSunModel

{

    [Display(Name = "Ready Time")]

    public string ReadyTime { get; set; }



    [CompareValues("ReadyTime", CompareValues.GreaterThan, ErrorMessage = "Close time must be later than ready time")]

    [Display(Name = "Close Time")]

    public string CloseTime { get; set; }



}

 

更多细节可以参考如下链接:

http://cncrrnt.com/blog/index.php/2011/01/custom-validationattribute-for-comparing-properties/ 

 

这里提供一个我自己的增强版本,可以添加另外一个依赖条件。

代码如下:

 

在Asp.Net MVC中实现CompareValues标签对Model中的属性进行验证
    public class CompareValuesAttribute : ValidationAttribute

    {

        /// <summary>

        /// The other property to compare to

        /// </summary>

        public string OtherProperty { get; set; }

        public CompareCriteria Criteria { get; set; }



        /// <summary>

        /// The other dependent rule

        /// </summary>

        public string RulePropertyName { get; set; }

        public CompareCriteria RuleCriteria { get; set; }

        public object RulePropertyValue { get; set; }



        public bool CustomErrorMessage { get; set; }



        /// <summary>

        /// Compare values with other property based on other rules or not 

        /// </summary>

        /// <param name="otherProperty">other property.</param>

        /// <param name="criteria">criteria</param>

        /// <param name="rulePropertyName">rule property name. (if don't based on other rules, please input null)</param>

        /// <param name="ruleCriteria">rule criteria. (if don't based on other rules, please input null)</param>

        /// <param name="rulePropertyValue">rule property value. (if don't based on other rules, please input null)</param>

        /// <param name="customErrorMessage">custom error message. (if don't need customize error message format, please input null)</param>

        public CompareValuesAttribute(string otherProperty, CompareCriteria criteria, string rulePropertyName, CompareCriteria ruleCriteria, object rulePropertyValue, bool customErrorMessage)

        {

            OtherProperty = otherProperty;

            Criteria = criteria;

            RulePropertyName = rulePropertyName;

            RuleCriteria = ruleCriteria;

            RulePropertyValue = rulePropertyValue;

            CustomErrorMessage = customErrorMessage;

        }



        /// <summary>

        ///  Compare values with other property

        /// </summary>

        /// <param name="otherProperty"></param>

        /// <param name="criteria"></param>

        /// <param name="customErrorMessage"></param>

        public CompareValuesAttribute(string otherProperty, CompareCriteria criteria, bool customErrorMessage)

        {

            OtherProperty = otherProperty;

            Criteria = criteria;

            RulePropertyName = null;

            CustomErrorMessage = customErrorMessage;

        }



        protected override ValidationResult IsValid(object value, ValidationContext validationContext)

        {

            if (ValidateDependentRule(validationContext) == null)   //validate dependent rule successful

            {

                if (OtherProperty == null)

                {

                    return new ValidationResult(String.Format("Orther property is null."));

                }



                // the the other property

                var property = validationContext.ObjectType.GetProperty(OtherProperty);



                // check it is not null

                if (property == null)

                {

                    return new ValidationResult(String.Format("Unknown property: {0}.", OtherProperty));

                }



                // check types

                var memberName = validationContext.ObjectType.GetProperties().Where(p => p.GetCustomAttributes(false).OfType<DisplayAttribute>().Any(a => a.Name == validationContext.DisplayName)).Select(p => p.Name).FirstOrDefault();

                if (memberName == null)

                {

                    memberName = validationContext.DisplayName;

                }

                if (validationContext.ObjectType.GetProperty(memberName).PropertyType != property.PropertyType)

                {

                    return new ValidationResult(String.Format("The types of {0} and {1} must be the same.", memberName, OtherProperty));

                }



                // get the other value

                var other = property.GetValue(validationContext.ObjectInstance, null);



                if (CompareValues(value, other, Criteria, validationContext) == null)

                {

                    return null;

                }

                else

                {

                    // got this far must mean the items don't meet the comparison criteria

                    if (CustomErrorMessage)

                    {

                        return new ValidationResult(string.Format(ErrorMessage, other));

                    }

                    else

                    {

                        return new ValidationResult(ErrorMessage);

                    }

                }

            }

            else

            {

                return null;    //dependent rule isn't exist or validate dependent rule failed

            }

        }



        private ValidationResult ValidateDependentRule(ValidationContext validationContext)

        {

            ValidationResult validateRuleResult = null;



            // has dependent rule

            if (RulePropertyName != null)

            {

                var rulePropertyName = validationContext.ObjectType.GetProperty(RulePropertyName);

                if (rulePropertyName == null)

                    return new ValidationResult(String.Format("Unknown rule property name: {0}.", RulePropertyName));



                var rulePropertyRealValue = rulePropertyName.GetValue(validationContext.ObjectInstance, null);



                validateRuleResult = CompareValues(rulePropertyRealValue, RulePropertyValue, RuleCriteria, validationContext);

            }



            return validateRuleResult;

        }



        private ValidationResult CompareValues(object targetValue, object otherValue, CompareCriteria compareCriteria, ValidationContext validationContext)

        {

            ValidationResult compareResult = new ValidationResult("Compare Values Failed.");



            // equals to comparison,

            if (compareCriteria == CompareCriteria.EqualTo)

            {

                if (Object.Equals(targetValue, otherValue)) compareResult = null;

            }

            else if (compareCriteria == CompareCriteria.NotEqualTo)

            {

                if (!Object.Equals(targetValue, otherValue)) compareResult = null;

            }

            else

            {

                // check that both objects are IComparables

                if (!(targetValue is IComparable) || !(otherValue is IComparable))

                    compareResult = new ValidationResult(String.Format("{0} and {1} must both implement IComparable", validationContext.DisplayName, OtherProperty));



                // compare the objects

                var result = Comparer.Default.Compare(targetValue, otherValue);



                switch (compareCriteria)

                {

                    case CompareCriteria.GreaterThan:

                        if (result > 0) compareResult = null;

                        break;

                    case CompareCriteria.LessThan:

                        if (result < 0) compareResult = null;

                        break;

                    case CompareCriteria.GreatThanOrEqualTo:

                        if (result >= 0) compareResult = null;

                        break;

                    case CompareCriteria.LessThanOrEqualTo:

                        if (result <= 0) compareResult = null;

                        break;

                }

            }



            return compareResult;

        }

    }



    public enum CompareCriteria

    {

        EqualTo,

        NotEqualTo,

        GreaterThan,

        LessThan,

        GreatThanOrEqualTo,

        LessThanOrEqualTo

    }
View Code

 

你可能感兴趣的:(asp.net)