[转载]ASP.Net MVC探索之路 – Model的比较验证 – Catcher In The Rye – 博客园.
WebForm有一个比较验证服务器控件CompareValidator ,可以比较两个控件的值大小或一个控件与某一个具体值的大小。可以进行string,int,double,DateTime,decimal这些数据类 型的==、!=、>、<、>=、<=比较。在ASP.NET MVC 2.0中,我们已经可以使用基于DataAnnotations的校验方式,对Model的值进行空校验(Required)、范围校验(Range)、 字符串长度校验(StringLengthAttribute)等。在ASP.NET MVC 3中,我们还可以使用CompareAttribute进行简单的相等(==)校验,但仅此而已,其他校验就没有了。
这里我们定义一个类似WebForms验证服务器控件CompareValidator的Attribule。
首先定义一个枚举表示我们要比较的数据类型:
{
String,Integer,Double,Date,Currency/*Decimal*/
}
再定义一个枚举表示比较方式:
{
Equal, NotEqual,GreaterThan,GreaterThanEqual,LessThan,LessThanEqual
}
然后当然就是主角CompareAttribute:
public class CompareAttribute : ValidationAttribute
{
public string SourceProperty { get; private set; }
public string OriginalProperty { get; private set; }
public ValidationCompareOperator Operator { get; private set; }
public ValidationDataType Type{ get; private set; } private const string _defaultErrorMessage = “‘{0}’ 与 ‘{1}’ 进行 {2} 比较失败“; public CompareAttribute(string sourceProperty, string originalProperty
, ValidationCompareOperator op, ValidationDataType type)
: base(_defaultErrorMessage)
{
SourceProperty = sourceProperty;
OriginalProperty = originalProperty;
Operator = op;
Type = type;
} public override string FormatErrorMessage(string name)
{
return String.Format(CultureInfo.CurrentUICulture, ErrorMessageString,
SourceProperty, OriginalProperty, Operator.ToString());
} public override bool IsValid(object value)
{
PropertyDescriptorCollection properties = TypeDescriptor.GetProperties(value);
object sourceProperty = properties.Find(SourceProperty, true /* ignoreCase */)
.GetValue(value);
object originalProperty = properties.Find(OriginalProperty, true /* ignoreCase */)
.GetValue(value); return compare(sourceProperty,originalProperty);
} private bool compare(object sourceProperty, object originalProperty)
{
int num = 0;
switch (this.Type)
{
case ValidationDataType.String:
num = string.Compare((string)sourceProperty
, (string)originalProperty, false, CultureInfo.CurrentCulture);
break; case ValidationDataType.Integer:
num = ((int)sourceProperty).CompareTo(originalProperty);
break; case ValidationDataType.Double:
num = ((double)sourceProperty).CompareTo(originalProperty);
break; case ValidationDataType.Date:
num = ((DateTime)sourceProperty).CompareTo(originalProperty);
break; case ValidationDataType.Currency:
num = ((decimal)sourceProperty).CompareTo(originalProperty);
break;
}
switch (this.Operator)
{
case ValidationCompareOperator.Equal:
return (num == 0); case ValidationCompareOperator.NotEqual:
return (num != 0); case ValidationCompareOperator.GreaterThan:
return (num > 0); case ValidationCompareOperator.GreaterThanEqual:
return (num >= 0); case ValidationCompareOperator.LessThan:
return (num < 0); case ValidationCompareOperator.LessThanEqual:
return (num <= 0);
}
return true;
}
}
在Model中就可以这样使用了,以下校验两次输入的密码是否一致:
,ValidationDataType.String, ErrorMessage = “请确认两次输入的密码一致“)]
public class UserInputEdit
{
[DisplayName(“登录密码“)]
public string Password { get; set; }
[DisplayName(
“确认密码“)]public string PasswordConfirm { get; set; }
}
如果果要Model中有两个时间,开始时间和结束时间,要求结束时间必须大于开始时间:
, ValidationDataType.Date, ErrorMessage = “结束时间必须大于开始时间“)]
public class UserInputEdit
{
[DisplayName(“开始时间“)]
public DateTime TimeStart { get; set; }
[DisplayName(
“结束时间“)]public DateTime TimeEnd { get; set; }
}
{
[DisplayName(“登录密码“)]
public string Password { get; set; }
[DisplayName(
“确认密码“)][Compare(“Password“, ErrorMessage = “请确认两次输入的密码一致“)]
public string PasswordConfirm { get; set; }
}
在 我们自定义的CompareAttribute中,必须将Attribute应用于class上。如果您想像ASP.NET MVC 3中,将标记写在属性,很遗憾不行。因为ValidationResult IsValid(…)的方法在.Net 4.0才有,MVC 3也才有相应的支持。当然也可以修改我们自定义的CompareAttribute,但请注意以下代码我没测试过:
, AllowMultiple = true)]
public class CompareAttribute : ValidationAttribute
{
public string OriginalProperty { get; private set; }
public ValidationCompareOperator Operator { get; private set; }
public ValidationDataType Type{ get; private set; } private const string _defaultErrorMessage = “‘{0}’ 与 ‘{1}’ 进行 {2} 比较失败“; public CompareAttribute(string originalProperty
, ValidationCompareOperator op, ValidationDataType type)
: base(_defaultErrorMessage)
{
OriginalProperty = originalProperty;
Operator = op;
Type = type;
} public override string FormatErrorMessage(string name)
{
return String.Format(CultureInfo.CurrentUICulture, ErrorMessageString,
name, OriginalProperty, Operator.ToString());
} protected override ValidationResult IsValid(object value
, ValidationContext validationContext)
{
PropertyInfo originalProperty = validationContext.ObjectType
.GetProperty(this.OriginalProperty);
object originalValue = originalProperty.GetValue(validationContext.ObjectInstance, null); if(!compare(value, originalValue))
return new ValidationResult(this.FormatErrorMessage(validationContext
.DisplayName)); return null;
} private bool compare(object sourceProperty, object originalProperty)
{
int num = 0;
switch (this.Type)
{
case ValidationDataType.String:
num = string.Compare((string)sourceProperty
, (string)originalProperty, false, CultureInfo.CurrentCulture);
break; case ValidationDataType.Integer:
num = ((int)sourceProperty).CompareTo(originalProperty);
break; case ValidationDataType.Double:
num = ((double)sourceProperty).CompareTo(originalProperty);
break; case ValidationDataType.Date:
num = ((DateTime)sourceProperty).CompareTo(originalProperty);
break; case ValidationDataType.Currency:
num = ((decimal)sourceProperty).CompareTo(originalProperty);
break;
}
switch (this.Operator)
{
case ValidationCompareOperator.Equal:
return (num == 0); case ValidationCompareOperator.NotEqual:
return (num != 0); case ValidationCompareOperator.GreaterThan:
return (num > 0); case ValidationCompareOperator.GreaterThanEqual:
return (num >= 0); case ValidationCompareOperator.LessThan:
return (num < 0); case ValidationCompareOperator.LessThanEqual:
return (num <= 0);
}
return true;
}
}