Reputation: 267
I am trying to make a form to register new user and save data into Entity Framework using MVC pattern; the thing is that I am trying to compare the entered password as following (code is written in the the model)
[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; }
The next step is to hash the password and save it (I created a new class called Security with the following method, and other methods to verify the password), following is the code:
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);
}
Then in the controller I used following to call the method that is responsible of password hashing and then save user data into Entity Framework:
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);
}
The problem is that I am getting the following error when I run the code:
But the code will work normally if I delete this line:
[Compare("tPassword", ErrorMessage = "The password and confirmation password does not match.")]
Can anyone explain to me why this is happening and how to solve this problem?
Upvotes: 1
Views: 2890
Reputation: 822
You have ValidateOnSaveEnabled set to true on your DbContext
context.Configuration.ValidateOnSaveEnabled = true;
This means that your validation will be executed twice. First by the model binder (done by MVC) - this will not throw error, because both passwords are same. But then in your HashAndSavePassword you have ConfirmPassword in plain text and tPassword in hash form. So EF will throw error when you call save.
You can:
Your DB model
public class RegisterTable
{
public int Id { get; set; }
public string tPassword { get; set; }
public string tUserName { get; set; }
public string Salt { get; set; }
...
}
Your view model:
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
};
}
}
Your action
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);
}
Upvotes: 1