ASP.NET MVC’s HTML helpers are fast and efficient for rendering elements using your model. One of these is the HTML.PasswordFor<> method, which has a little gotcha that many people get caught out with.
The HTML.PasswordFor<> method will render a password input to mask keystrokes on the browser but will not populate the value using the model. For most scenarios this is fine however there are occasions this functionality can be counter productive.
For example, a logged in user may be given the opportunity to update their password. A suitable implementation of this would include three fields in the process.
- Current Password
- New Password
- Confirm New Password
All these fields will be keystroke masked password fields. When the post to your action occurs the model will be validated to ensure the following restrictions are met
- Current Password is supplied and is correct
- New password is supplied and is within acceptable criteria
- Confirm New Password matches New Password exactly
Any of these criteria can fail, at which point the action will return its view with suitable validation errors. The problem exists at this point as the password field will not be repopulated with the last entered value, instead being reset to blank. Fortunately the solution, although not instantly obvious, is very easy. Simply populate the value manually using Html.PasswordFor’s htmlAttributes parameter and your model.
Html.PasswordFor(x => x.CurrentPassword, new { value = Model.CurrentPassword })
The user can now continue to enter their details from the point that validation failed.
Important Note. Do not pass your original domain model to the view model if you are going to use this method. If you do, the password will always be pre-populated. The view model should have it’s own properties to handle the three password entries and be empty by default.