Custom Validation Attribute MVC2

狂风中的少年 提交于 2019-11-30 13:40:20

Because the object value parameter of IsValid() is not the entire model, but just your string RetypePassword.

It would need to be an attribute that affects the whole model object, and not just a property.

Although I would suggest you to use the 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; }

   //...
}

Edit

That attribute is actually not part of the ASP.NET MVC2 framework, but defined in the default MVC 2 project template.

[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 );
    }
}

On a side note, MVC 3 has a CompareAttribute that does exactly what you want.

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; }

    // ...
}

I'm not sure why your code doesn't work, but through GetType() you can get the expected result:

var property = value.GetType().GetProperty(CompareProperty);
var comparePropertyValue = property.GetValue(value, null).ToString();

According to http://msdn.microsoft.com/en-us/library/ybh0y4fd.aspx the TypeDescroptor.GetProperties "Returns the collection of properties for a specified component." it also goes on to say:

The properties for a component can differ from the properties of a class, because the site can add or remove properties if the component is sited.

So it appears to me that this isn't really the right method to be using to get the properties of a class. I think @Pieter's method is more what you're really looking for.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!