2015-10-27 65 views
0

我正在尝试使用MVC模式注册新用户并将数据保存到实体框架中;事情是,我想如下(代码写在模型)比较输入的密码和散列密码,验证错误C#MVC

[Required(ErrorMessage = "Enter Password!")] 
[StringLength(100, ErrorMessage = "The {0} must be at least {2} characters long.", MinimumLength = 6)] 
[DataType(DataType.Password)] 
public string tPassword { get; set; } 

[DataType(DataType.Password)] 
[Compare("tPassword", ErrorMessage = "The password and confirmation password does not match.")] 
public string Confirmpassword { get; set; } 

下一个步骤是散列密码,并将其保存比较输入的密码(我创建了一个名为Security的新类以下的方法,以及其它方法来验证密码),以下是代码:

public static void HashAndSavePassword(string password, RegisterTable usr) 
{ 
    var v = new Rfc2898DeriveBytes(password, 16, 3987); 
    usr.tPassword = Convert.ToBase64String(v.GetBytes(25), Base64FormattingOptions.None); 
    usr.Salt = Convert.ToBase64String(v.Salt, Base64FormattingOptions.None); 
} 

然后,在我用以下来调用负责密码散列的方法,然后保存用户数据到实体框架控制器:

public ActionResult Register(RegisterTable user) 
{ 
    if (ModelState.IsValid) 
    { 
     // To check if username already exist 
     var searchUserName = db.RegisterTables.Where(x => x.tUserName.Equals(user.tUserName)).FirstOrDefault(); 

     if (searchUserName == null) 
     { 
      Security.HashAndSavePassword(user.tPassword, user); 

      db.RegisterTables.Add(user); 
      db.SaveChanges(); 
      ModelState.Clear(); 
      return RedirectToAction("Login"); 
     } 
     else ModelState.AddModelError("", "User is already Registred.");    
    } 

    return View(user); 
} 

问题是,当我运行代码,我收到以下错误:

enter image description here

但代码将正常工作,如果我删除这一行:

[Compare("tPassword", ErrorMessage = "The password and confirmation password does not match.")] 

谁能解释对我来说为什么会发生这种情况以及如何解决这个问题?

回答

1

你ValidateOnSaveEnabled设置为true你的DbContext

context.Configuration.ValidateOnSaveEnabled = true; 

这意味着您的验证将被执行两次。首先由模型联编程序(由MVC完成) - 这不会抛出错误,因为两个密码都是相同的。但是,在你的HashAndSavePassword中,你有明文形式的ConfirmPassword和散列形式的tPassword。因此,当您调用保存时,EF会引发错误。

您可以:

  1. 关闭EF模型验证通过ValidateOnSaveEnabled设置为false。
  2. 在HashAndSavePassword函数中还有hash ConfirmPassword属性(这是黑客)
  3. 在动作中使用不同的模型,然后转换为EF中使用的模型。 (这被称为)

你DB模型

public class RegisterTable 
{ 
    public int Id { get; set; } 
    public string tPassword { get; set; } 
    public string tUserName { get; set; } 
    public string Salt { get; set; } 

    ... 
} 

你的视图模型:

public class RegisterModel 
{ 
    // put username validation rules here 
    public string UserName { get; set; } 

    [Required(ErrorMessage = "Enter Password!")] 
    [StringLength(100, ErrorMessage = "The {0} must be at least {2} characters long.", MinimumLength = 6)] 
    [DataType(DataType.Password)] 
    public string Password { get; set; } 

    [DataType(DataType.Password)] 
    [Compare("Password", ErrorMessage = "The password and confirmation password does not match.")] 
    public string Confirmpassword { get; set; } 

    ... 

    public RegisterTable Map() 
    { 
     var v = new Rfc2898DeriveBytes(this.Password, 16, 3987); 
     return new RegisterTable() 
     { 

      Salt = Convert.ToBase64String(v.Salt, Base64FormattingOptions.None), 
      tPassword = Convert.ToBase64String(v.GetBytes(25), Base64FormattingOptions.None), 
      tUserName = this.UserName 
     }; 
    } 
} 

你的动作

public ActionResult Register(RegisterModel user) 
{ 
    if (ModelState.IsValid) 
    { 
     // To check if username already exist 
     var searchUserName = db.RegisterTables.Where(x => x.tUserName.Equals(user.UserName)).FirstOrDefault(); 

     if (searchUserName == null) 
     { 
      var dbUser = user.Map(); 

      db.RegisterTables.Add(user); 
      db.SaveChanges(); 
      ModelState.Clear(); 
      return RedirectToAction("Login"); 
     } 
     else ModelState.AddModelError("", "User is already Registred."); 
    } 

    return View(user); 
} 
+0

谢谢,它的工作,但我不明白第三点,你是什么意思将模型转换为EF模型,你可以提供一些更多的信息或一个很好的教程解释它?再次感谢 – moji

+0

现在您在注册操作中使用RegisterTable类作为参数。这通常不是一个好主意,因为您的数据库模型将具有与注册表不同的属性集。例如:不需要在数据库模型上有ConfirmPassword字段,因为您不需要将其存储在数据库中。并且您的数据库模型将具有不应该暴露给视图的属性(例如IsDeleted,DateModified等)。因此,最好有模型来描述你的视图表单,验证该模型,然后将其转换为不同的数据库或服务模型。 – longchiwen

+0

我得到了你的观点,谢谢......但我仍然不知道如何转换为DB .. – moji