如何更新格式与定义模型不同的密码?我收到 DbEntityValidationException

How do I update a password that's in a different format from the defined model? I'm getting DbEntityValidationException

问题

我到处搜索,但还没有找到正确的答案。

我的代码

我有一个允许用户注册帐户的功能。它看起来像这样:

[HttpPost]
public ActionResult Register([Bind(Include="Username,Password,EmailAddress")] UserModel user)
{
    if (TryUpdateModel(user))
    {
        // Set password to a different format than Model's designated Regex
        user.Password = e.Encrypt(user.Password);

        context.Entry(user).State = EntityState.Added;
        context.SaveChanges();
        return RedirectToAction("Login", "Account");
    }
    return View();
}

在我的 UserModel.cs 文件中,我有以下约束:

    [Required]
    [DataType(DataType.Password)]
    [StringLength(16, MinimumLength = 8, ErrorMessage = "Must be between 8 and 16 characters.")]
    [RegularExpression("^(?=.*[0-9])(?=.*[!@#$%^&*])[a-zA-Z0-9!@#$%^&*]", ErrorMessage = ErrorMessage_PasswordRegex)]
    public string Password { get; set; }

同样,散列密码的格式完全不同。因此,我无法更新它,因为它会抛出 DbEntityValidationException。这个[RegularExpression()]是针对用户密码的格式。我需要能够绕过或暂停密码的 Regex 约束。

我做了什么来补救这个问题

我删除了 [RegularExpression()] 要求,并将 [StringLength()] 提高到 70,这是我的密码哈希的长度。

但是,我不想让用户输入 70 个字符的文本。这似乎是一种廉价的 hack,我觉得应该有更好的方法来做到这一点。有什么想法吗?

这是一个例子:

我们对用户输入的要求与我们的数据库要求不同。我们可能需要更多的用户输入,我们将以编程方式对其进行处理。

EF 模型

public class UserModel()
{
    [Key]
    public string Id { get; set; }

    public string Name { get; set; }

    [Required, StringLength(70)]
    public string Password { get; set; }
}

下面是我们用来捕获用户输入的class

public class UserViewModel()
{
    [Required]
    public string Name { get; set; }

    [Required]
    [RegularExpression("^(?=.*[0-9])(?=.*[!@#$%^&*])[a-zA-Z0-9!@#$%^&*]", ErrorMessage = ErrorMessage_PasswordRegex)]
    public string Password { get; set; }

    [Required]
    public string ConfirmPassword { get; set; }
}

现在我们转换和映射值。

用户将不知道 Id 使用什么,数据库不需要 ConfirmPassword。我们还可以将用户最初输入的内容转换为密码。

[HttpPost]
public ActionResult Register(UserViewModel model)
{
    if ((ModelState.IsValid) &&
        (model.Password == model.ConfirmPassword))
    {
        // map to EF model
        var user = new UserModel
        {
            Name = model.Name,
            Password = e.encrypt(model.Password)  // transform, encrypt, whatever
        };

        db.Users.Add(user);  // use EF model to persist
        ...

        return RedirectToAction("Login", "Account");
    }
    return(model);
}