ASP MVC: Custom Validation Attribute

36,736

Solution 1

Sorry to disappoint you but handling such a simple case like yours using Data Annotations could be a pain. You may take a look at this post.

Solution 2

According to this link http://devtrends.co.uk/blog/the-complete-guide-to-validation-in-asp.net-mvc-3-part-1 there is an special validation attribute now in MVC3:

public class RegisterModel
{
    // skipped

    [Required]
    [ValidatePasswordLength]
    [DataType(DataType.Password)]
    [Display(Name = "Password")]
    public string Password { get; set; }                       

    [DataType(DataType.Password)]
    [Display(Name = "Confirm password")]
    [Compare("Password", ErrorMessage = "The password and confirmation do not match.")]
    public string ConfirmPassword { get; set; }
}

CompareAttribute is a new, very useful validator that is not actually part of System.ComponentModel.DataAnnotations, but has been added to the System.Web.Mvc DLL by the team. Whilst not particularly well named (the only comparison it makes is to check for equality, so perhaps EqualTo would be more obvious), it is easy to see from the usage that this validator checks that the value of one property equals the value of another property. You can see from the code, that the attribute takes in a string property which is the name of the other property that you are comparing. The classic usage of this type of validator is what we are using it for here: password confirmation.

Solution 3

FoolProof http://foolproof.codeplex.com/ seems to be the best solution.

public class SignUpViewModel
{
    [Required]
    public string Password { get; set; }

    [EqualTo("Password", ErrorMessage="Passwords do not match.")]
    public string RetypePassword { get; set; }
}

It is better than suggested PropertiesMustMatchAttribute as it adds the validation error for the "RetypePassword' instead of the global model level as PropertiesMustMatchAttribute does.

Solution 4

I don't know why this is made out to be such a big deal, just do this:

[AttributeUsage(AttributeTargets.Property, AllowMultiple = true, Inherited = false)]
public class ComparePassword: ValidationAttribute
{
    public ComparePassword() 
        : base("Passwords must match.") { }

    protected override ValidationResult IsValid (object value, ValidationContext validationContext)
    {
        if (value == null) return new ValidationResult("A password is required.");

        // Make sure you change YourRegistrationModel to whatever  the actual name is
        if ((validationContext.ObjectType.Name != "YourRegistrationModel") 
             return new ValidationResult("This attribute is being used incorrectly.");
        if (((YourRegistrationModel)validationContext.ObjectInstance).ConfirmPassword != value.ToString())
            return new ValidationResult("Passwords must match.");

        return ValidationResult.Success;
    }
}

Now all you need to do is add [ComparePassword] to your password property, nothing to pass... simple and fairly clean

Share:
36,736
Admin
Author by

Admin

Updated on October 08, 2020

Comments

  • Admin
    Admin over 3 years

    I'm trying to write my own Custom Validation attribute but I'm having some problems.

    The attribute I'm trying to write is that when a user logs in, the password will be compared against the confirmation password.

    namespace Data.Attributes
    {
    public class ComparePassword : ValidationAttribute
    {
        public string PasswordToCompareWith { get; set; }
    
        public override bool IsValid(object value)
        {
            if (PasswordToCompareWith == (string)value)
            {
                return true;
            }
           return false;
        }
    }
    

    Now my problem is when i'm trying to set the attribute like this in the model file:

     [Required]
        [ComparePassword(PasswordToCompareWith=ConfirmPassword)]
        public string Password { get; set; }
    
    
        [Required]
        public string ConfirmPassword { get; set; }
       }
    

    I get the following error:

    Error 1 An object reference is required for the non-static field, method, or property 'Project.Data.Models.GebruikerRegistreerModel.ConfirmPassword.get'

    It seems that VS is not accepting the confirmpassword in the PasswordToCompareWith=ConfirmPassword part.

    What am I doing wrong?