您的位置:首页 > 编程语言 > ASP

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

2014-02-21 18:31 656 查看
在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
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐