I'm using jquery unobtrusive validation in a new MVC4 solution. My problem is that on my login page when I click the submit button the page is still posted even though my required fields are empty.
I have another page where I have the same setup and that one doesn't post.
This is my login page:
<div id="loginForm">
@Html.SiteLogo()
@using (Html.BeginForm(new { ReturnUrl = ViewBag.ReturnUrl })) {
@Html.AntiForgeryToken()
@Html.ValidationSummary(true)
<div id="loginForm-container" class="spacer-below">
<fieldset>
<legend>Log in Form</legend>
<div class="input-control text" data-role="input-control">
@Html.TextBoxFor(m => m.UserName, new { placeholder="Please enter your username"})
@Html.ValidationMessageFor(m => m.UserName)
</div>
<div class="input-control password" data-role="input-control">
@Html.PasswordFor(m => m.Password, new { placeholder="Please enter your password"})
@Html.ValidationMessageFor(m => m.Password)
</div>
<div class="input-control checkbox" data-role="input-control">
<label>
@Html.CheckBoxFor(m => m.RememberMe)
<span class="check"></span> Remember me
</label>
</div>
<div class="input-control">
<input type="submit" class="primary small" value="Log in" />
</div>
</fieldset>
</div>
<div class="forgotPassword">@Html.ActionLink("Forgotten password?", "ForgotPassword")</div>
<span>@Html.Partial("_CustomerSupport")</span>
}
</div>
And the viewmodel for this page:
public class LoginModel
{
[Required]
[Display(Name = "User name")]
public string UserName { get; set; }
[Required]
[DataType(DataType.Password)]
[Display(Name = "Password")]
public string Password { get; set; }
[Display(Name = "Remember me")]
public bool RememberMe { get; set; }
}
And this the HTMl for a page that does work i.e. does not post if the input is empty
<div id="resetPasswordForm">
@Html.SiteLogo()
<h4>Reset Password</h4>
@using (Html.BeginForm(new {ReturnUrl = ViewBag.ReturnUrl}))
{
@Html.AntiForgeryToken()
@Html.ValidationSummary(true)
@Html.HiddenFor(vm => vm.Authentication.Token)
@Html.ValidationMessageFor(vm => vm.Authentication.Token)
<div id="resetPasswordForm-container" class="spacer-below">
<fieldset>
<legend>Reset password form</legend>
<div class="input-control text" data-role="input-control">
@Html.TextBoxFor(vm => vm.Authentication.EmailAddress, new { placeholder="Please enter your email address"})
@Html.ValidationMessageFor(vm => vm.Authentication.EmailAddress)
</div>
<div class="input-control password" data-role="input-control">
@Html.PasswordFor(vm => vm.NewPassword, new { placeholder="Please enter a new password"})
@Html.ValidationMessageFor(vm => vm.NewPassword)
</div>
<div class="input-control text" data-role="input-control">
@Html.PasswordFor(vm => vm.ConfirmPassword, new { placeholder="Please enter the password again"})
@Html.ValidationMessageFor(vm => vm.ConfirmPassword)
</div>
<div class="input-control">
<input type="submit" class="primary medium" value="Reset Password" />
</div>
</fieldset>
</div>
<span>@Html.Partial("_CustomerSupport")</span>
}
</div>
And my viewmodel for this page:
public class ResetPasswordViewModel
{
public ResetPasswordViewModel()
{
Authentication = new ResetPasswordConfirmViewModel();
}
public ResetPasswordConfirmViewModel Authentication { get; set; }
[Required]
[StringLength(100, ErrorMessage = "The {0} must be at least {2} characters long.", MinimumLength = 6)]
[DataType(DataType.Password)]
[Display(Name = "New password")]
public string NewPassword { get; set; }
[DataType(DataType.Password)]
[Display(Name = "Confirm new password")]
[Compare("NewPassword", ErrorMessage = "The new passwords do not match, please enter again.")]
public string ConfirmPassword { get; set; }
}
My view references the appropriate scripts as checked when I view the source:
<script src="/Scripts/jquery.validate.js"></script>
<script src="/Scripts/jquery.validate.unobtrusive.js"></script>
I should also mention that I'm following the guide from:
http://nickstips.wordpress.com/2011/08/18/asp-net-mvc-displaying-client-and-server-side-validation-using-qtip-tooltips/
In order to try and get hover like validation. This works perfectly except on the Login form. After further investigation it appears that the code is error'ing out in the onError() method change due to possibly there being no validation on this field (I do not require validation on the remember me as it's optional).
var replace = $.parseJSON(container.attr("data-valmsg-replace")) !== false;
I'm guessing as my input is not required for validation it doesn't have the data-valmsg-replace attribute and hence this line is causing the javascript to fail and so the post goes through?