zoukankan      html  css  js  c++  java
  • 在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/ 

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

    代码如下:

        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
  • 相关阅读:
    Eclipse-将svn上的项目转化成相应的项目
    Maven-在eclipse创建maven项目
    Html-Css-div标签嵌套浮动div标签时无法撑开外部div的解决
    Html-Css-a标签的使用
    Jquery-获取父级元素parent
    Jquery-获取子元素children,find
    Jquery-获取同级标签prev,prevAll,next,nextAll
    Jquery-处理iframe的高度自适应
    Html-Css-iframe的自适应高度方案
    Html-Css-iframe的使用
  • 原文地址:https://www.cnblogs.com/mingmingruyuedlut/p/3530983.html
Copyright © 2011-2022 走看看