Table of contents
The purpose of this article is to demonstrate on how to integrate Password Strength Indicator using jQuery and XML plug-in with ASP.NET MVC 3 Razor. In this tutorial, we will include the plug-in into the Register Account and Change Password views.
Shown below is the content of the sample application. In Visual Studio 2010
- Create a new project
- Get the latest version of the plug-in and copy the jquery.password-strength.js into the Scripts folder
- Copy the XML folder into the project root or place it into Content folder
- Create the PasswordSetting class under the Models folder
- The files that we’re going to modify are AccountController.cs, AccountModels.cs, Register.cshtml and ChangePassword.cshtml
- Please note that the absolute link to the XML file in the jquery.password-strength.js is hardcoded to localhost. Make sure you modify it accordingly before deploy it to production.
Figure 1
In the RegisterModel class, remove the StringLength attribute from the Password property because the length will be checked by the plug-in. If we leave it there, it will display both the error message and the password strength indicator bar until we hit the six characters.
Listing 1
public class RegisterModel
{
[Required]
[DataType(DataType.Password)]
[Display(Name = "Password")]
public string Password { get; set; }
}
In this version, we will use LINQ to read the XML file. The GetPasswordRegex() method in this controller is responsible to retrieve the password information from the XML file and store it in the PasswordSetting object. Then it will use the information to put together the password strength regular expression. For this demo, the path to the XML file is hardcoded, you can place the path to the XML file in the web.config.
Listing 2
internal string GetPasswordRegex()
{
XDocument xmlDoc = XDocument.Load(Request.MapPath("~/xml/PasswordPolicy.xml"));
var passwordSetting = (from p in xmlDoc.Descendants("Password")
select new PasswordSetting
{
Duration = int.Parse(p.Element("duration").Value),
MinLength = int.Parse(p.Element("minLength").Value),
MaxLength = int.Parse(p.Element("maxLength").Value),
NumsLength = int.Parse(p.Element("numsLength").Value),
SpecialLength = int.Parse(p.Element("specialLength").Value),
UpperLength = int.Parse(p.Element("upperLength").Value),
SpecialChars = p.Element("specialChars").Value
}).First();
StringBuilder sbPasswordRegx = new StringBuilder(string.Empty);
sbPasswordRegx.Append(@"(?=^.{" + passwordSetting.MinLength + "," + passwordSetting.MaxLength + "}$)");
sbPasswordRegx.Append(@"(?=(?:.*?\d){" + passwordSetting.NumsLength + "})");
sbPasswordRegx.Append(@"(?=.*[a-z])");
sbPasswordRegx.Append(@"(?=(?:.*?[A-Z]){" + passwordSetting.UpperLength + "})");
sbPasswordRegx.Append(@"(?=(?:.*?[" + passwordSetting.SpecialChars + "]){" + passwordSetting.SpecialLength + "})");
sbPasswordRegx.Append(@"(?!.*\s)[0-9a-zA-Z" + passwordSetting.SpecialChars + "]*$");
return sbPasswordRegx.ToString();
}
Add the code in Listing 3 to the beginning of the Register method. During testing with JavaScript disabled, I found that the error "System.ArgumentNullException: Value cannot be null. Parameter name: input" will occur when the Password input is empty. In order to avoid that, make sure the Password input is not empty before calling the Regex.IsMatch method. If the password does not meet the policy, display “Password does not meet policy!” error message on the screen.
Listing 3
if (!string.IsNullOrEmpty(model.Password))
{
if (!Regex.IsMatch(model.Password, GetPasswordRegex()))
{
ModelState.AddModelError("Password", "Password does not meet policy!");
}
}
Include a reference to the jquery.password-strength.js plug-in on the page and add the script in listing 6 to the bottom of the view. Add a password policy link under the password textbox and set it ID to "passwordPolicy". Refer to listing 4.
Listing 4
@Html.ActionLink("Password policy","", null, new { id = "passwordPolicy" })
Initially, the only codes under the button submit click function was in listing 5. For some reason, the client side validation for the whole form was not working on button submit click. Which does make sense because the plug-in should return false if user click on the submit button without any input in the password textbox. But the same set of code works fine on the ASP.NET application. The work around is to manually invoke the jQuery valid() function to checks whether all the form elements are valid before checking if the password meet requirement.
Listing 5
$("[id='btnSubmit']").click(function () {
return myPlugin.metReq(); });
Listing 6
<script type="text/javascript">
$(document).ready(function () {
var myPlugin = $("input[id='Password']").password_strength();
$("[id='btnSubmit']").click(function () {
var $form = $( if ($form.valid()) {
return myPlugin.metReq(); //return true or false
}
});
$("[id='passwordPolicy']").click(function (event) {
var width = 350, height = 300, left = (screen.width / 2) - (width / 2),
top = (screen.height / 2) - (height / 2);
window.open("http://localhost:1234/xml/PasswordPolicy.xml", event.preventDefault();
return false;
});
});
</script>
The plug-in also implemented in the change password view in this sample. Again, I would recommend using absolute URL to your XML file and download the demo and explore it in order to grasp the full concept of it because I might miss some important information in this article. I hope someone will find this information useful and make your programming job easier. If you find any bugs or disagree with the contents or want to help improve this article, please drop me a line and I'll work with you to correct it. Please send me an email if you want to help improve this article.
07/29/2012 – First Release (v01.00.00)
09/13/2012 – Added demo project using ASP.NET MVC2 (v01.01.00)
http://stackoverflow.com/questions/5127813/call-mvc-3-client-side-validation-manually-for-ajax-posts
http://mvc.ysatech.com/Account/Register
http://download.ysatech.com/MvcPasswordStrength.zip