0

My problem is similar to this question but I'm still having problem with validation both server- and client-side. I want to perform a compare on two properties, set in different models.

My models are as follows:

public class User{
  public string Password { get; set; }
}

public class UserRegisterViewModel {
    public User User{ get; set; }

    //This is suggested in linked question - as Compare can only work with local property
    public string Password 
    {
        get{return this.User.Password;}
    }

    [DataType(DataType.Password)]
    [Compare("Password", ErrorMessage = "Passwords must match")]
    [Required(ErrorMessage = "Confirm password is required")]
    [DisplayName("Confirm Password")]
    public string CPassword { get; set; }
}

My Controller action is:

[HttpPost]
[AllowAnonymous]
[ValidateAntiForgeryToken]
public ActionResult Register(UserRegisterViewModel model)
{
    if (ModelState.IsValid) //This conditions is false
    {
    }
    return View(); 
}

It redirects to again register page with the validation error saying Password must match. Can someone please help ? I have checked this question it helped a bit, but not completely.

If I change the model structure like below, than I get an error saying: Could not find a property named User.Password:

public class UserRegisterViewModel {
    public User User{ get; set; }

    [DataType(DataType.Password)]
    [Compare("User.Password", ErrorMessage = "Passwords must match")]
    [Required(ErrorMessage = "Confirm password is required")]
    [DisplayName("Confirm Password")]
    public string CPassword { get; set; }
}

EDIT

My cshtml page code is like below.

<p>
    @Html.LabelFor(model => model.User.Password)
    @Html.PasswordFor(model => model.User.Password, new { @class = "wd189 inputtext" })
    @Html.ValidationMessageFor(model => model.User.Password)
</p>
<p>
    @Html.LabelFor(model => model.CPassword)
    @Html.PasswordFor(model => model.CPassword, new { @class = "wd189 inputtext" })
    @Html.ValidationMessageFor(model => model.CPassword)
</p>
Community
  • 1
  • 1
Ani Shroff
  • 1,155
  • 8
  • 10
  • Could you post the code of your View and the `HttpGet` of your `Register` action result? – Aage Nov 09 '13 at 18:45
  • @bump added code of View, how do I get httpget ? sorry being noob but I am new to this. – Ani Shroff Nov 09 '13 at 19:10
  • But the way you organized your UserRegisterViewModel (with [Compare("User.Password", ErrorMessage = "Passwords must match")] is exact problem from the link you've provided (another question). That's why some additional property "Password" was introduced there additionally. – Agat Nov 09 '13 at 19:12
  • So If I do that I get different error saying password does not match on server side, updated question with error but in both cases it works on client side. – Ani Shroff Nov 09 '13 at 19:17
  • Actually, I've just tried exactly the same code (the first block), and it works greatly on server side. The model validates correctly. (As for the password). – Agat Nov 09 '13 at 19:23
  • Can you please confirm it works client side as well and if possible can u upload somewhere on github or any site and send me link here, I would be obliged. – Ani Shroff Nov 09 '13 at 19:24
  • @Ani Shroff Sorry, a bit more investigations. Have posted working for me code as an answer. – Agat Nov 09 '13 at 19:53

3 Answers3

1

This worked for me (for both: client and server sides).

public class UserRegisterViewModel
{
    private User _user;

    public User User
    {
        get { return _user = (_user ?? new User()); }
    }

    public string Password
    {
        get { return User.Password; }
        set { User.Password = value; }
    }

    [DataType(DataType.Password)]
    [System.Web.Mvc.Compare("Password", ErrorMessage = "Passwords must match")]
    [Required(ErrorMessage = "Confirm password is required")]
    [DisplayName("Confirm Password")]
    public string CPassword { get; set; }
}

EDIT:

and obviously, the view must be as follows:

<p>
    @Html.LabelFor(model => model.Password)
    @Html.PasswordFor(model => model.Password, new { @class = "wd189 inputtext" })
    @Html.ValidationMessageFor(model => model.Password)
</p>
<p>
    @Html.LabelFor(model => model.CPassword)
    @Html.PasswordFor(model => model.CPassword, new { @class = "wd189 inputtext" })
    @Html.ValidationMessageFor(model => model.CPassword)
</p>  
Agat
  • 4,577
  • 2
  • 34
  • 62
-1

In your Register View, You need to reference the password of the user model, not the password of UserRegisterViewModel model. Like below:

@model  UserRegisterViewModel

@Html.LabelFor(model => model.User.Password)
@Html.EditorFor(model => model.User.Password)
@Html.ValidationMessageFor(model => model.User.Password)

@Html.LabelFor(model => model.CPassword)
@Html.EditorFor(model => model.CPassword)
@Html.ValidationMessageFor(model => model.CPassword)

public class User
{
    [DataType(DataType.Password)]
    public string Password { get; set; }
}

public class UserRegisterViewModel
{
    public User User { get; set; }
    public string Password{get { return this.User.Password; }}

    [DataType(DataType.Password)]
    [Compare("Password", ErrorMessage = "Passwords must match")]
    [Required(ErrorMessage = "Confirm password is required")]
    [DisplayName("Confirm Password")]
    public string CPassword { get; set; }
}
Lin
  • 15,078
  • 4
  • 47
  • 49
  • I just updated the answer, comment out [DisplayName("Confirm Password")], try it again. – Lin Nov 09 '13 at 19:13
  • That should not be the case as it is just for display purpose, or am I missing something ? – Ani Shroff Nov 09 '13 at 19:19
  • I tried your code, if your view code is the same as mine, the only difference is I added "[DataType(DataType.Password)]" for the password in User model. – Lin Nov 09 '13 at 19:26
-1

could you please check this article? I think that it will help you.

Example:

public class RegisterModelValidator : AbstractValidator<RegisterModel>
{
    public RegisterModelValidator()
    {
        RuleFor(x => x.UserName)
            .NotNull();
        RuleFor(x => x.ConfirmPassword)
            .Equal(x => x.User.Password);
    }
}

And another one arcticle also can solve the issue.

Pavel Nasovich
  • 223
  • 1
  • 7