在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 > )
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中的属性进行验证的更多相关文章
- CompareValues标签对Model中的属性进行验证
在Asp.Net MVC中实现CompareValues标签对Model中的属性进行验证 在Asp.Net MVC中可以用继承ValidationAttribute的方式,自定制实现Model两个 ...
- 在Asp.Net MVC中实现RequiredIf标签对Model中的属性进行验证
在Asp.Net MVC中可以用继承ValidationAttribute的方式,自定制实现RequiredIf标签对Model中的属性进行验证 具体场景为:某一属性是否允许为null的验证,要根据另 ...
- 在.Net MVC中自定义ValidationAttribute标签对Model中的属性做验证
写一个继承与ValidationAttribute类的自定义的验证方法 MVC中传递数据时,大多数都会用Model承载数据,并且在传到控制器后,对Model进行一系列的验证. 我平时经常使用的判断方法 ...
- Asp.net mvc + .net ef database first 或 model first 时如何添加验证特性
今天有个同事问到,在使用Entity Framework 的Database frist或model first时,怎么在model上添加验证的特性? 因为此时的Model是是VS 工具怎么生成的,直 ...
- 返璞归真 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 ...
- mvc中动态给一个Model类的属性设置验证
原文:mvc中动态给一个Model类的属性设置验证 在mvc中有自带的验证机制,比如如果某个字段的类型是数字或者日期,那么用户在输入汉字或者英文字符时,那么编译器会自动验证并提示用户格式不正确,不过这 ...
- 总结ASP.NET MVC Web Application中将数据显示到View中的几种方式
当我们用ASP.NET MVC开发Web应用程序的时候,我们都是将需要呈现的数据通过"Controllers"传输到"View"当中,怎么去实现,下面我介绍一下 ...
- Asp.Net MVC 从客户端<a href="http://www....")中检测到有潜在危险的 Request.Form 值
Asp.Net MVC应用程序, Framework4.0: 则需要在webconfig文件的 <system.web> 配置节中加上 <httpRuntime requestVal ...
- asp.net mvc 3.0 知识点整理 ----- (2).Controller中几种Action返回类型对比
通过学习,我们可以发现,在Controller中提供了很多不同的Action返回类型.那么具体他们是有什么作用呢?它们的用法和区别是什么呢?通过资料书上的介绍和网上资料的查询,这里就来给大家列举和大致 ...
随机推荐
- Python操作PDF与Tiff文件
1.PDF文件的合并与拆分 pypdf http://www.douban.com/note/455252403/ http://www.redicecn.com/html/Python/201301 ...
- [Linux]centOS7-1-1503-x86_64下安装VM-TOOLS
1.安装Perl. 2.如果提示 The path "" is not a valid path to the 3.10.0-229.el7.x86_64 kernel heade ...
- ffmpeg-20160512-git-bin
ESC 退出 0 进度条开关 1 屏幕原始大小 2 屏幕1/2大小 3 屏幕1/3大小 4 屏幕1/4大小 S 下一帧 [ -2秒 ] +2秒 ; -1秒 ' +1秒 下一个帧 -> -5秒 f ...
- SAP 工厂日生产计划待排维护
*&---------------------------------------------------------------------* *& Report ZPPR0024 ...
- 【转】TextView长按复制实现方法小结
有这么一个需求,用户在浏览文本信息时希望长按信息就能弹出复制的选项方便保存或者在别的页面使用这些信息.类似的, 就像长按WebView或者EditText的内容就自动弹出复制选项. 这里面主要是2个特 ...
- uva 401.Palindromes
题目链接:https://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem ...
- 【Git】笔记1
学习廖雪峰Git教程的笔记 Git是什么: Git是目前世界上最先进的分布式版本控制系统 Git与Github的关系:github是一个用git做版本控制的项目托管平台,它为开源项目免费提供Git存储 ...
- IOS- 内存管理机制
iOS平台内存常见问题 作为iOS平台的开发者,是否曾经为内存问题而苦恼过?内存莫名的持续增长,程序莫名的crash,难以发现 的内存泄漏,这些都是iOS平台内存相关的常见问题:本文将会详细介绍iOS ...
- printf 打印 unit32_t
今天在网上找了老半天终于找到了:printf 打印 uint32_t 类型 uint32_t domainId; printf("\ndomainId=========%lu", ...
- springmvc注解配置
<?xml version="1.0" encoding="UTF-8" ?> <beans xmlns="http://www.s ...