Best practice to validate Current Password for Change Password in ViewModel with .Net MVC 3?
My ViewModel:
public class EditViewModel
{
[Required]
public string CurrentPassword { get; set; }
public string NewPassword { get; set; }
[Compare("NewPassword")]
public string ConfirmNewPassword { get; set; }
}
I'm trying to validate CurrentPassword field. I thought about creating a Custom Validato开发者_StackOverflowr Attribute that connect to my database(for retrieve current password) for use with DataAnnotations.
There is a better idea?
Update:
I know I can doing this validation in my controller, but I'm trying to avoid this validation logic in my controller. Just for beauty of my code/architecture.
I have not seen a better solution than create a Custom Validator for use with DataAnnotations, what do you think?
Why not just make a call to Membership.ChangePassword
? If it fails then you can add an error to the ModelState:
[Authorize]
[HttpPost]
public ActionResult ChangePassword(ChangePasswordModel model)
{
if (ModelState.IsValid)
{
// ChangePassword will throw an exception rather
// than return false in certain failure scenarios.
bool changePasswordSucceeded;
try
{
MembershipUser currentUser = Membership.GetUser(User.Identity.Name, true /* userIsOnline */);
changePasswordSucceeded = currentUser.ChangePassword(model.OldPassword, model.NewPassword);
}
catch (Exception)
{
changePasswordSucceeded = false;
}
if (changePasswordSucceeded)
{
return RedirectToAction("ChangePasswordSuccess");
}
else
{
ModelState.AddModelError("", "The current password is incorrect or the new password is invalid.");
}
}
// If we got this far, something failed, redisplay form
return View(model);
}
This is all done in the default Internet project template by the way. Unless you are wanting client side validation I'm not sure what the purpose of checking to see if their password is correct, then calling Change Password. It would just be an extra call to the database which seems unnecessary.
You can use the [Remote] Annotation.
It will make an ajax call to a method in a certain controller. There you can access the database or do some other validations.
[Remote("CheckPassword","YourController", ErrorMessage = "Wrong currentpassword")]
[Required]
public string CurrentPassword { get; set; }
public ActionResult CheckPassword(String Password)
{
if (YourRepository.CheckIfPassIsCorrect(Password))
{
return Json(false, JsonRequestBehavior.AllowGet);
}
else
{
return Json(true, JsonRequestBehavior.AllowGet);
}
}
Another solution
When you submit to your controller. Do something like this:
if(!YourRepository.CheckIfPassIsCorrect(YourViewModel.CurrentPassword)
{
ModelState.AddModelError("CurrentPassword", "Your current password isn't correct");
//Return to your view
}
My solution is building a Custom Validation to use with DataAnnotations, here's the code:
public class CurrentPasswordAttribute : ValidationAttribute
{
AuthenticationService authenticationService = new AuthenticationService();
public override bool IsValid(object value)
{
string strValue = value as string;
if (!string.IsNullOrEmpty(strValue))
{
return authenticationService.ValidateUser(HttpContext.Current.User.Identity.Name, strValue);
}
return false;
}
public override string FormatErrorMessage(string name)
{
return String.Format(CultureInfo.CurrentCulture, base.ErrorMessageString, name);
}
}
And in my ViewModel:
public class EditViewModel
{
[CurrentPassword]
public string CurrentPassword { get; set; }
public string NewPassword { get; set; }
[Compare("NewPassword")]
public string ConfirmNewPassword { get; set; }
}
Thanks.
精彩评论