在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:
                        )
                            return null;
                        break;
                    case CompareValues.LessThan:
                        )
                            return null;
                        break;
                    case CompareValues.GreatThanOrEqualTo:
                        )
                            return null;
                        break;
                    case CompareValues.LessThanOrEqualTo:
                        )
                            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:
                        ) compareResult = null;
                        break;
                    case CompareCriteria.LessThan:
                        ) compareResult = null;
                        break;
                    case CompareCriteria.GreatThanOrEqualTo:
                        ) compareResult = null;
                        break;
                    case CompareCriteria.LessThanOrEqualTo:
                        ) compareResult = null;
                        break;
                }
            }

            return compareResult;
        }
    }

    public enum CompareCriteria
    {
        EqualTo,
        NotEqualTo,
        GreaterThan,
        LessThan,
        GreatThanOrEqualTo,
        LessThanOrEqualTo
    }

在Asp.Net MVC中实现CompareValues标签对Model中的属性进行验证的更多相关文章

  1. CompareValues标签对Model中的属性进行验证

    在Asp.Net MVC中实现CompareValues标签对Model中的属性进行验证   在Asp.Net MVC中可以用继承ValidationAttribute的方式,自定制实现Model两个 ...

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

    在Asp.Net MVC中可以用继承ValidationAttribute的方式,自定制实现RequiredIf标签对Model中的属性进行验证 具体场景为:某一属性是否允许为null的验证,要根据另 ...

  3. 在.Net MVC中自定义ValidationAttribute标签对Model中的属性做验证

    写一个继承与ValidationAttribute类的自定义的验证方法 MVC中传递数据时,大多数都会用Model承载数据,并且在传到控制器后,对Model进行一系列的验证. 我平时经常使用的判断方法 ...

  4. Asp.net mvc + .net ef database first 或 model first 时如何添加验证特性

    今天有个同事问到,在使用Entity Framework 的Database frist或model first时,怎么在model上添加验证的特性? 因为此时的Model是是VS 工具怎么生成的,直 ...

  5. 返璞归真 asp.net mvc (8) - asp.net mvc 3.0 新特性之 Model

    原文:返璞归真 asp.net mvc (8) - asp.net mvc 3.0 新特性之 Model [索引页][源码下载] 返璞归真 asp.net mvc (8) - asp.net mvc ...

  6. mvc中动态给一个Model类的属性设置验证

    原文:mvc中动态给一个Model类的属性设置验证 在mvc中有自带的验证机制,比如如果某个字段的类型是数字或者日期,那么用户在输入汉字或者英文字符时,那么编译器会自动验证并提示用户格式不正确,不过这 ...

  7. 总结ASP.NET MVC Web Application中将数据显示到View中的几种方式

    当我们用ASP.NET MVC开发Web应用程序的时候,我们都是将需要呈现的数据通过"Controllers"传输到"View"当中,怎么去实现,下面我介绍一下 ...

  8. Asp.Net MVC 从客户端&lt;a href=&quot;http://www....&quot;)中检测到有潜在危险的 Request.Form 值

    Asp.Net MVC应用程序, Framework4.0: 则需要在webconfig文件的 <system.web> 配置节中加上 <httpRuntime requestVal ...

  9. asp.net mvc 3.0 知识点整理 ----- (2).Controller中几种Action返回类型对比

    通过学习,我们可以发现,在Controller中提供了很多不同的Action返回类型.那么具体他们是有什么作用呢?它们的用法和区别是什么呢?通过资料书上的介绍和网上资料的查询,这里就来给大家列举和大致 ...

随机推荐

  1. Mysql字符转义

    在字符串中,某些序列具有特殊含义.这些序列均用反斜线('\')开始,即所谓的转义字符.MySQL识别下面的转义序列: \0 ASCII 0(NUL)字符. \' 单引号('''). \" 双 ...

  2. 【C#公共帮助类】JsonHelper 操作帮助类, 以后再也不用满地找Json了,拿来直接用

     四个主要操作类:JsonConverter .JsonHelper .JsonSplit .AjaxResult 一.JsonConverter: 自定义查询对象转换动态类.object动态类转换j ...

  3. 团队交流合作简单解决方案:TeamViewer远程控制&amp;会议演示 + HyperCam屏幕录制(免费)

    一. 教程摘要 做开发,团队合作是少不了的.而在合作中,有一部分是花在交流讨论上,其中包括初期的任务分配,成员的进度汇报,以及资源和心得分享等.该教程介绍了两个免费的软件,搭配起来,适合人数不超过25 ...

  4. bzoj 3170 manhattan距离

    首先将坐标系顺时针旋转45度,得到一个新的坐标系,这个坐标系 对应的坐标的manhattan距离就是原图中的距离,然后快排,利用前缀和 数组O(N)求所有的答案,然后找最小值就行了,总时间O(Nlog ...

  5. 粗谈Android中的对齐

    在谈这个之前先啰嗦几个概念. 基线:书写英语单词时为了规范书写会设有四条线,从上至下第三条就是基线.基线对齐主要是为了两个控件中显示的英文单词的基线对齐,如下所示: Start:在看API的时候经常会 ...

  6. 修改sublime 侧边栏 颜色 等

    通过 Package Control 安装 PackageResourceViewer  插件 安装成功后 快捷键 ctrl+shift+p  输入 PackageResourceViewer  找到 ...

  7. (转载)php循环检测目录是否存在并创建(循环创建目录)

    (转载)http://www.jb51.net/article/25917.htm php循环检测目录是否存在并创建,需要的朋友可以参考下. 循环创建目录方法 这个会生成image.gif目录 代码如 ...

  8. Array.prototype.map()

    mdn上解释的特别详细 概述 map() 方法返回一个由原数组中的每个元素调用一个指定方法后的返回值组成的新数组. 语法 array.map(callback[, thisArg]) 参数 callb ...

  9. ORA-00214: controlfile &#39;/u01/app/oracle/oradata/[sid]/control01.ctl&#39; version inconsistent with file &#39;/u01/app/oracle/oradata/[sid]/control03.ctl&#39;

    Sample error: SQL> startupORACLE instance started. Total System Global Area 285212672 bytesFixed ...

  10. openlayers4 入门开发系列之批量叠加 zip 压缩 SHP 图层篇(附源码下载)

    前言 openlayers4 官网的 api 文档介绍地址 openlayers4 api,里面详细的介绍 openlayers4 各个类的介绍,还有就是在线例子:openlayers4 官网在线例子 ...