使用.Net MVC 3在ViewModel中验证当前密码以更改密码的最佳做法?
我的ViewModel:使用.Net MVC 3在ViewModel中验证当前密码以更改密码的最佳做法?,.net,asp.net-mvc,asp.net-mvc-3,data-annotations,.net,Asp.net Mvc,Asp.net Mvc 3,Data Annotations,我的ViewModel: public class EditViewModel { [Required] public string CurrentPassword { get; set; } public string NewPassword { get; set; } [Compare("NewPassword")] public string ConfirmNewPassword { get; set; } } public class Edi
public class EditViewModel
{
[Required]
public string CurrentPassword { get; set; }
public string NewPassword { get; set; }
[Compare("NewPassword")]
public string ConfirmNewPassword { get; set; }
}
public class EditViewModel
{
[CurrentPassword]
public string CurrentPassword { get; set; }
public string NewPassword { get; set; }
[Compare("NewPassword")]
public string ConfirmNewPassword { get; set; }
}
我正在尝试验证CurrentPassword字段。我考虑创建一个自定义验证器属性,该属性连接到我的数据库(用于检索当前密码),以便与DataAnnotation一起使用
有更好的主意吗
更新:
我知道我可以在我的控制器中进行验证,但我试图在我的控制器中避免这种验证逻辑。只是为了我的代码/架构之美 我还没有见过比创建一个用于DataAnnotation的自定义验证器更好的解决方案,您认为呢?您可以使用 [远程]注释。 它将对某个控制器中的方法进行ajax调用。在那里,您可以访问数据库或执行一些其他验证
[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);
}
}
另一种解决方案
当您提交给控制器时。
这样做:
if(!YourRepository.CheckIfPassIsCorrect(YourViewModel.CurrentPassword)
{
ModelState.AddModelError("CurrentPassword", "Your current password isn't correct");
//Return to your view
}
为什么不直接打电话给
会员。更改密码
?如果失败,则可以向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);
}
顺便说一下,这都是在默认的Internet项目模板中完成的。除非您需要客户端验证,否则我不确定检查密码是否正确,然后调用ChangePassword的目的是什么。这只是对数据库的额外调用,似乎不必要。我的解决方案是构建一个自定义验证,用于DataAnnotation,下面是代码:
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);
}
}
在我的ViewModel中:
public class EditViewModel
{
[Required]
public string CurrentPassword { get; set; }
public string NewPassword { get; set; }
[Compare("NewPassword")]
public string ConfirmNewPassword { get; set; }
}
public class EditViewModel
{
[CurrentPassword]
public string CurrentPassword { get; set; }
public string NewPassword { get; set; }
[Compare("NewPassword")]
public string ConfirmNewPassword { get; set; }
}
谢谢。我不想为此使用Javascript。我不知道RemoteAttribute。伟大的为什么要将密码验证为电子邮件地址?添加了另一个解决方案,哈哈,电子邮件内容是一个打字错误,因为我从我的一个型号复制了远程注释;)我来编辑it@Kevin我试图在控制器中避免这种验证逻辑。只是为了我的代码/体系结构的美观。我想定制一个验证器是一个不错的选择,然后我试图在我的控制器中避免这种验证逻辑。只是为了我的代码/体系结构的美观。@Acaz,然后重构此解决方案,以便在服务中进行所有操作?@Tomas是的,使用带有数据批注的自定义验证器。根据您的编辑,如果您不想在控制器中进行验证,您想在哪里进行验证?如果您想在客户端执行此操作,则必须将密码(或某种形式的密码)发送到客户端。。。这是我建议你避免的一种做法。任何能让你的船漂浮的东西——但我个人不同意这一点。属性不应调用到服务中。@RPM1984您建议什么解决方案?它属于控制器。你说你不想这样做是为了“我的代码/架构之美”。但控制器的任务是处理模型,并更新视图。调用外部服务当然不是自定义属性作业。首先,它使单元测试变得非常困难。基本上,@Kevin Cloet的第二个答案是正确的。我很想知道这是如何影响您的体系结构的?因此,如果您的控制器太“胖”,那么就将代码抽象到服务中。比精简控制器更大的最佳实践是分离关注点。同一类中的属性和服务不是分离的。“查看密码是否正确”是一个域/身份验证问题,它不是真正的输入验证,这就是属性的用途。因此,我建议将“fat代码”放在服务中,并让控制器调用该代码。@RPM1984是的,我同意你的意见,但当前密码是一个我仅在视图中看到的字段,而不存在于域中。因此,输入验证是当前密码中唯一进行验证的地方,不是吗?