我有一个自定义验证属性,用于检查两个属性是否具有相同的值(如密码和重新键入密码):
[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。任何人都可以帮助我理解为什么会这样吗?
答案 0 :(得分:13)
因为object value
的{{1}}参数不是整个模型,而只是IsValid()
。
它需要是一个影响整个模型对象的属性,而不仅仅是属性。
虽然我建议你使用string RetypePassword
。
PropertiesMustMatchAttribute
该属性实际上不是ASP.NET MVC2框架的一部分,而是在默认的MVC 2项目模板中定义。
[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; }
//...
}
另一方面,MVC 3有一个CompareAttribute
,可以完全按照您的意愿行事。
[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 );
}
}
答案 1 :(得分:0)
我不确定为什么您的代码不起作用,但通过GetType()
您可以获得预期的结果:
var property = value.GetType().GetProperty(CompareProperty);
var comparePropertyValue = property.GetValue(value, null).ToString();
答案 2 :(得分:0)
根据http://msdn.microsoft.com/en-us/library/ybh0y4fd.aspx,TypeDescroptor.GetProperties“返回指定组件的属性集合。”它还接着说:
组件的属性可能与类的属性不同, 因为如果组件位于该站点,该站点可以添加或删除属性。
所以在我看来,这不是用于获取类属性的正确方法。我认为@ Pieter的方法更像是你真正想要的。