I'm laying out a view that compares two password strings. The two properties in one of my models are pretty straightforward:
[Required]
[RegularExpression(@"(\S)+", ErrorMessage = "White space is not allowed")]
[StringLength(20, MinimumLength = 6)]
[DataType(DataType.Password)]
[Display(Name = "New Password")]
public string NewPassword { get; set; }
[Required]
[DataType(DataType.Password)]
[RegularExpression(@"(\S)+", ErrorMessage = "White space is not allowed")]
[StringLength(20, MinimumLength = 6)]
[Display(Name = "Confirm Password")]
[Compare("NewPassword", ErrorMessage = "The new password and confirmation password do not match.")]
public string ConfirmPassword { get; set; }
Here's my view code:
<table class="fieldset center" width="400">
<tbody>
<tr>
<th width="150">
@Html.LabelFor(m => m.NewPassword)
</th>
<td>
@Html.PasswordFor(m => m.NewPassword, new { @class = "itext3" })
<br /><br />@Html.ValidationMessageFor(m => m.NewPassword)
</td>
</tr>
<tr>
<th width="150">
@Html.LabelFor(m => m.ConfirmPassword)
</th>
<td>
@Html.PasswordFor(m => m.ConfirmPassword, new { @class = "itext3" })
<br /><br />@Html.ValidationMessageFor(m => m.ConfirmPassword)
</td>
</tr>
</tbody>
</table>
All of the attributes fire their client-side validation messages when tested, except for the CompareAttribute on ConfirmPassword which is not firing until I hit the server. However, in my controller the ModelState.IsValid = false.
I compared what I'm doing to the default MVC application which is working correctly. Any suggestions for troubleshooting and fixing this?
I'm using MVC 3 RTM.
There is a BUG in jquery.validate.unobtrusive.js (and jquery.validate.unobtrusive.min.js, the minified version). The client-side validation emitted as a result of the [Compare] attribute will ONLY work if the compare-to field is the FIRST field on the form. To fix this bug, locate this line in jquery.validate.unobtrusive.js:
element = $(options.form).find(":input[name=" + fullOtherName + "]")[0];
which results in this equivalent:
element = $(options.form).find(":input[name=MyExample.Control]")[0];
Unfortunately that's not the right syntax for find(), and causes it to reference the first input control on the form.
Change that line to:
element = $(options.form).find(":input[name='" + fullOtherName + "']")[0];
which results in this equivalent:
element = $(options.form).find(":input[name='MyExample.Control]'")[0];
Which is the correct syntax, and correctly matches the input control with the specified name.
Locate the same code block in jquery.validate.unobtrusive.min.js, which looks like this:
f=a(b.form).find(":input[name="+d+"]")[0];
and change it to:
f=a(b.form).find(":input[name='"+d+"']")[0];
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With