在Asp.Net MVC中可以用继承ValidationAttribute的方式,自定制实现Model两个中两个属性值的比较验证
具体应用场景为:要对两个属性值的大小进行验证
代码如下所示:
////// 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 /// public class CompareValuesAttribute : ValidationAttribute { ////// The other property to compare to /// public string OtherProperty { get; set; } public CompareValues Criteria { get; set; } ////// Creates the attribute /// /// The other property to compare to public CompareValuesAttribute(string otherProperty, CompareValues criteria) { if (otherProperty == null) throw new ArgumentNullException("otherProperty"); OtherProperty = otherProperty; Criteria = criteria; } ////// 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 /// /// The value of the object to validate /// The validation context ///A validation result if the object is invalid, null if the object is valid 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().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); } } /// /// Indicates a comparison criteria used by the CompareValues attribute /// 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; }}
更多细节可以参考如下链接:
这里提供一个我自己的增强版本,可以添加另外一个依赖条件。
代码如下:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
![](https://images.cnblogs.com/OutliningIndicators/ExpandedBlockStart.gif)
public class CompareValuesAttribute : ValidationAttribute { ////// The other property to compare to /// public string OtherProperty { get; set; } public CompareCriteria Criteria { get; set; } ////// The other dependent rule /// public string RulePropertyName { get; set; } public CompareCriteria RuleCriteria { get; set; } public object RulePropertyValue { get; set; } public bool CustomErrorMessage { get; set; } ////// Compare values with other property based on other rules or not /// /// other property. /// criteria /// rule property name. (if don't based on other rules, please input null) /// rule criteria. (if don't based on other rules, please input null) /// rule property value. (if don't based on other rules, please input null) /// custom error message. (if don't need customize error message format, please input null) 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; } ////// Compare values with other property /// /// /// /// 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().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 }