在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 > )
return null;
break;
case CompareValues.LessThan:
if (result < )
return null;
break;
case CompareValues.GreatThanOrEqualTo:
if (result >= )
return null;
break;
case CompareValues.LessThanOrEqualTo:
if (result <= )
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 > ) compareResult = null;
break;
case CompareCriteria.LessThan:
if (result < ) compareResult = null;
break;
case CompareCriteria.GreatThanOrEqualTo:
if (result >= ) compareResult = null;
break;
case CompareCriteria.LessThanOrEqualTo:
if (result <= ) 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 从客户端<a href="http://www....")中检测到有潜在危险的 Request.Form 值

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

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

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

随机推荐

  1. Unity3d 检查哪些prefab引用了某个UIAtlas

    适用情景:策划在用NGUI制作UI prefab时经常会使用一些临时的Atlas,然后再想改就不知道都哪些使用了.现在想修改下使用临时资源的GameObject 使用方式,先选中某个prefab或者某 ...

  2. winrt获取文件MD5码

    //小文件 public static string ComputeMD5(byte[] bytes) { var alg = HashAlgorithmProvider.OpenAlgorithm( ...

  3. JavaScript高级程序设计学习笔记--函数表达式

    关于函数声明,它的一个重要特征就是函数声明提升,意思是在执行代码之间会读取函数声明,意思是在执行代码之前会先读取函数声明.这就意味着可以把函数声明放在调用它的语句 后面. sayHi(); funct ...

  4. 使用charles 抓取手机上的操作

    Charles上的设置要截取iPhone上的网络请求,我们首先需要将Charles的代理功能打开.在Charles的菜单栏上选择“Proxy”->“Proxy Settings”,填入代理端口8 ...

  5. 关于Hibernate的关联映射

    何为关联映射 由于数据库的表与表之间存在的管理关系,可以分为一对一,一对多和多对多关联,一般情况下,在数据库设计中是通过表的外键来建立各种关系的,在Hibernate中则把数据库表与表之间的关系数据映 ...

  6. chaper3_exerise_UVa455_周期串

    #include<iostream> #include<cstring> #include<stdio.h> using namespace std; ; int ...

  7. cookie的设置、获取以及删除

    首先介绍一下cookie的基本信息: cookie是以域为单位的,它必须放在服务器的的环境下,但是cookie的容量小,只有4kb,并且也不安全,还有入股cookie的名字相同,会修改或者覆盖原来的值 ...

  8. 对于类的双重调用的demo

    代码如下: package cao.com.duixiang; public class TestCCircle { public static void main(String[] args) { ...

  9. phpcms 标签

    都说pc标签{pc:content参数名="参数值"参数名="参数值"参数名="参数值"} 但是 参数名对应的具体参数值有那些,菜鸟就不知道 ...

  10. Memcached驱动(C#)

    using Memcached.ClientLibrary; using System; using System.Collections.Generic; using System.IO; usin ...