7

I'm just getting started with ASP.NET MVC 2, and playing around with Validation.

Let's say I have 2 properties:

  • Password1
  • Password2

And I want to require that they are both filled in, and require that both are the same before the model is valid.

I have a simple class called "NewUser".

How would I implement that? I've read about ValidationAttribute, and understand that. But I don't see how I would use that to implement a validation that compares two or more properties against eathother.

Thanks in advance!

Problem with below solution:

When this is applied to an application, and the ModelBinder runs the validation of the Model, then there is a problem:

If a Property-level ValidationAttribute contains an error, then the Class-level ValidationAttribute's are NOT validated. I have not found a solution to this problem as of yet.

If you have a solution to this problem please share your experience. Thanks alot!

1 Answer 1

6

The default ASP.NET MVC 2 template of Visual Studio includes the exact validation attribute you need. Pasted from AccountModels.cs file :

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

How to use :

[PropertiesMustMatch("Password", "ConfirmPassword", 
    ErrorMessage = "The password and confirmation password do not match.")]
class NewUser {
    [Required]
    [DataType(DataType.Password)]
    [DisplayName("Password")]
    public string Password { get; set; }
    [Required]
    [DataType(DataType.Password)]
    [DisplayName("Confirm password")]
    public string ConfirmPassword { get; set; }
}
Sign up to request clarification or add additional context in comments.

3 Comments

The only problem I can see with this is, when two properties of the Model (class in this case), aren't equal, it doesn't denote the specific Properties as containing errors, like it does for [Required] and <%=Html.ValidationMessageFor(m => m.Password1) %>
@CodeMonkey, I see. Though I'm not sure if there's an elegant solution to make it work the other way, using model binding. After all, this is technically a class-level validation. If you must add the errors to the properties instead, then maybe checking the two values in the controller after the binding would be the quickest solution (though not the most elegant).
In the MVC 2 version the Html.ValidationSummary helper method can now display Model-Level only errors

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.