[英]Custom Validation in MVC2 clarification - Following an example of scott gu's
[英]Custom Validation Attribute MVC2
我有一个自定义验证属性,它检查两个属性是否具有相同的值(如密码和重新键入密码):
[AttributeUsage(AttributeTargets.Property | AttributeTargets.Field, AllowMultiple = false)]
public class EqualToPropertyAttribute : ValidationAttribute
{
public string CompareProperty { get; set; }
public EqualToPropertyAttribute(string compareProperty)
{
CompareProperty = compareProperty;
ErrorMessage = string.Format(Messages.EqualToError, compareProperty);
}
public override bool IsValid(object value)
{
if (value == null)
{
return true;
}
PropertyDescriptorCollection properties = TypeDescriptor.GetProperties(value);
var property = properties.Find(CompareProperty, true);
var comparePropertyValue = property.GetValue(value).ToString();
return comparePropertyValue == value.ToString();
}
}
我有一个视图模型类,其中包含注册表单的所有字段,如下所示:
public class SignUpViewModel
{
[Required]
[StringLength(100)]
public string Username { get; set; }
[Required]
[Password]
public string Password { get; set; }
[Required]
[DisplayText("RetypePassword")]
[EqualToProperty("Password")]
public string RetypePassword { get; set; }
[Required]
[StringLength(50)]
[DisplayText("FirstName")]
public string FirstName { get; set; }
[Required]
[StringLength(100)]
[DisplayText("LastName")]
public string LastName { get; set; }
[Required]
[DisplayText("SecurityQuestion")]
public int SecurityQuestionID { get; set; }
public IEnumerable<SelectListItem> SecurityQuestions { get; set; }
[Required]
[StringLength(50)]
public string Answer { get; set; }
}
以下是我的控制器代码:
public virtual ActionResult Index()
{
var signUpViewModel = new SignUpViewModel();
signUpViewModel.SecurityQuestions = new SelectList(questionRepository.GetAll(),"SecurityQuestionID", "Question");
return View(signUpViewModel);
}
[HttpPost]
public virtual ActionResult Index(SignUpViewModel viewModel)
{
// Code to save values to database
}
当我输入表单值并点击提交代码行时,尝试获取属性描述符var property = properties.Find(CompareProperty,true); 返回null。 任何人都可以帮助我理解为什么会这样吗?
因为IsValid()
的object value
参数不是整个模型,而只是你的string RetypePassword
。
它需要是一个影响整个模型对象的属性,而不仅仅是属性。
虽然我建议你使用PropertiesMustMatchAttribute
。
[PropertiesMustMatch("Password", "RetypePassword",
ErrorMessage = "The password and confirmation password do not match.")]
public class SignUpViewModel
{
[Required]
[StringLength(100)]
public string Username { get; set; }
[Required]
[Password]
public string Password { get; set; }
[Required]
[DisplayText("RetypePassword")]
public string RetypePassword { get; set; }
//...
}
该属性实际上不是ASP.NET MVC2框架的一部分,而是在默认的MVC 2项目模板中定义。
[AttributeUsage( AttributeTargets.Class, AllowMultiple = true, Inherited = true )]
public sealed class PropertiesMustMatchAttribute : ValidationAttribute {
private const string _defaultErrorMessage = "'{0}' and '{1}' do not match.";
private readonly object _typeId = new object();
public PropertiesMustMatchAttribute( string originalProperty, string confirmProperty )
: base( _defaultErrorMessage ) {
OriginalProperty = originalProperty;
ConfirmProperty = confirmProperty;
}
public string ConfirmProperty { get; private set; }
public string OriginalProperty { get; private set; }
public override object TypeId {
get {
return _typeId;
}
}
public override string FormatErrorMessage( string name ) {
return String.Format( CultureInfo.CurrentUICulture, ErrorMessageString,
OriginalProperty, ConfirmProperty );
}
public override bool IsValid( object value ) {
PropertyDescriptorCollection properties = TypeDescriptor.GetProperties( value );
object originalValue = properties.Find( OriginalProperty, true /* ignoreCase */).GetValue( value );
object confirmValue = properties.Find( ConfirmProperty, true /* ignoreCase */).GetValue( value );
return Object.Equals( originalValue, confirmValue );
}
}
另外,MVC 3有一个CompareAttribute
,可以完全满足您的需求。
public class SignUpViewModel
{
[Required]
[StringLength(100)]
public string Username { get; set; }
[Required]
[Password]
public string Password { get; set; }
[Required]
[DisplayText("RetypePassword")]
[Compare("Password")] // the RetypePassword property must match the Password field in order to be valid.
public string RetypePassword { get; set; }
// ...
}
我不确定为什么你的代码不起作用,但通过GetType()
你可以得到预期的结果:
var property = value.GetType().GetProperty(CompareProperty);
var comparePropertyValue = property.GetValue(value, null).ToString();
根据http://msdn.microsoft.com/en-us/library/ybh0y4fd.aspx,TypeDescroptor.GetProperties “返回指定组件的属性集合。” 它还接着说:
组件的属性可能与类的属性不同,因为如果组件所在的位置,站点可以添加或删除属性。
因此在我看来,这不是用于获取类属性的正确方法。 我认为@ Pieter的方法更像是你真正想要的。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.