1

Hi I thought this was a simple one.

To reduce the problem for the sake of clarity I have a three properties in my view model, user name, password and confirm password.

Obviously we want to make sure the passwords match but I also want to make sure that they do not match the username.

There are lots of hacks out there for previous version of MVC but I can't believe there is not a more subtle way of dealing with this obvious comparison in MVC5

    [Required]
    [DataType(DataType.Text)]
    [Display(Name = "User name")]
    public string UserName { get; set; }

    [Required]
    [StringLength(100, ErrorMessage = "The {0} must be at least {2} characters long.", MinimumLength = 6)]
    [DataType(DataType.Password)]
    [Display(Name = "Password")]
    [NotEqualTo("UserName", ErrorMessage = "The password can not be the same as the User name.")]
    public string Password { get; set; }

    [Required]
    [DataType(DataType.Password)]
    [Display(Name = "Confirm password")]
    [Compare("Password", ErrorMessage = "The password and confirmation password do not match.")]
    public string ConfirmPassword { get; set; }
JasonLCook
  • 13
  • 2
  • So what's the problem? Go ahead and implement this attribute, shouldn't take the whole day – Vsevolod Goloviznin Dec 12 '14 at 19:06
  • You can also check for the RemoteValidation, as example: http://stackoverflow.com/questions/10163683/remote-validation-mvc-3-0-multiple-fields-validation – Rafael Merlin Dec 12 '14 at 19:17
  • It's not a problem Vsevolod it was a question, can it be done in a more subtle way. – JasonLCook Dec 15 '14 at 09:38
  • Instead of adding third party dependencies and mixing up attribute & fluent validation, I would have chosen to implement your approach in the question for consistency. – mcy Jul 18 '18 at 13:28

1 Answers1

3

I'm a big fan of using the FluentValidation library when dealing with any non-standard validations. It even contains a NotEqual() method for doing exactly what you're talking about.

public class RegisterViewModelValidator: AbstractValidator<RegisterViewModel>  
{
    public RegisterViewModelValidator()
    {
        RuleFor(m => m.Password).NotEqual(m => m.UserName).WithMessage("Password Cannot Match Username");
    }
}

You may want to go a step further and change it not allow the password to CONTAIN the username.

RuleFor(m => m.Password).Must((vm, pwd) => !pwd.Contains(vm.UserName)).WithMessage("Password Cannot Match Username");

While you can mix FluentValidation and the standard attributes as well, MVC will get mad if they both apply the same validation (for example, including the [Required] attribute and also adding the NotEmpty() rule in Fluent will throw an error).

jerone
  • 16,206
  • 4
  • 39
  • 57
zaparker
  • 485
  • 3
  • 14