mvc模型和viewmodel?

时间:2011-06-28 17:48:35

标签: c# asp.net-mvc entity-framework data-annotations

所以, 我有一个“用户”模型,有很多字段,但以下是有关的:


public int Id {get;set;}
public string Username { get; set; }
public string Pwd { get; set; }

我有一个视图模型验证我在不同控制器上使用的密码:

public class ConfirmPassword : IValidatableObject
{
    [Required]
    public string Password { get; set; }
    [Required(ErrorMessage="Confirm Password field is required.")]
    public string ConfirmPwd { get; set; }

    public IEnumerable<ValidationResult> Validate(ValidationContext validationContext)
    {
        string regex1 = @"^.{8,10}$";                   // 8 - 10 characters

        Match requirement1 = Regex.Match(Password, regex1);

        if (Password != ConfirmPwd)
            yield return new ValidationResult("Password and Confirm Password is not identical.");

        if (!requirement1.Success)
            yield return new ValidationResult("Password must be between 8 and 10 characters.");


    }
}

有没有办法可以将视图模型连接到我的模型实体?或者只是复制粘贴代码我唯一的选择?我不能复制粘贴,因为代码需要有一个IValidateObject,这会弄乱整个用户实体,因为有大量的后台审计发生..我只需要在编辑/创建配置文件时验证密码。

编辑: 很抱歉如果每个人都感到困惑。基本上,我在确认密码上需要多次验证,这些验证密码无法通过数据注释处理,而是确认密码视图模型。我希望将此验证应用于用户模型,但不在其中添加“ConfirmPassword”字段。因为我不需要数据库上的另一个字段。我的问题是,当视图POST和密码字段不符合要求时,我如何强制从确认密码中获取验证?

namespace
{
    public class User 
    {
public int Id {get;set;}
public string Username { get; set; }
public string Pwd { get; set; }

    }
}


namespace
{
    public class ConfirmPassword : IValidatableObject
    {
        [Required]
        public string Password { get; set; }
        [Required(ErrorMessage="Confirm Password field is required.")]
        public string ConfirmPwd { get; set; }

        public IEnumerable<ValidationResult> Validate(ValidationContext validationContext)
        {
            string regex1 = @"^.{8,10}$";                   // 8 - 10 characters
            string regex2 = @"(?:.*?[A-Z]){1}";             // 1 uppercase
            string regex3 = "";             // 1 lowercase
            string regex4 = "";                // 1 numeric

            Match requirement1 = Regex.Match(Password, regex1);
            Match requirement2 = Regex.Match(Password, regex2);
            Match requirement3 = Regex.Match(Password, regex3);
            Match requirement4 = Regex.Match(Password, regex4);

            if (Password != ConfirmPwd)
                yield return new ValidationResult("Password and Confirm Password is not identical.");

            if (!requirement1.Success)
                yield return new ValidationResult("Password must be between 8 and 10 characters.");

            if (!requirement2.Success)
                yield return new ValidationResult("Password must contain at least 1 uppercase letter.");

            if (!requirement3.Success)
                yield return new ValidationResult("Password must contain at least 1 lowercase letter.");

            if (!requirement4.Success)
                yield return new ValidationResult("Password must contain at least 1 numeric character.");

        }
    }
} 

5 个答案:

答案 0 :(得分:1)

您可以在视图模型中使用装饰器模式来执行您喜欢的操作。您还可以使用System.ComponentModel.DataAnnotations命名空间属性为您执行所有验证。

public class ConfirmPassword 
{
    User model;

    [Required]
    public string Username 
    { 
        get { return this.model.Username; } 
        set { this.model.Username = value; } 
    }
    [Required]
    [DataType(DataType.Password)]
    public string Password 
    { 
        get { return this.model.Pwd; } 
        set { this.model.Pwd = value; } 
    }

    [Required(ErrorMessage = "Confirm Password field is required.")]
    [Compare("NewPassword", 
       ErrorMessage = "The new password and confirmation password do not match.")]
    [RegularExpression(@"^.{8,10}$")]
    [DataType(DataType.Password)]
    public string ConfirmPwd { get; set; }

    public ConfirmPassword()
    {
        this.model = new User();
    }

    public ConfirmPassword(User model)
    {
        this.model = model;
    }

}

答案 1 :(得分:1)

好的,我对连接视图模型到模型实体的意思仍然有点不确定...我想你现在想要检查实际用户的密码是否与传递给视图模型的密码相匹配。

我个人不会在视图模型本身中这样做,而是在控制器中,如果密码不正确,则会添加ModelState.AddError。

如果您使用客户端验证,则可以在服务器或客户端进行正常的输入验证,但是您无法检查密码客户端,因此必须转到服务器。

public LoginViewModel()
{
  [Required]
  public string LoginId {get; set;}

  [DataType(DataType.Password)]
  public string Password {get; set;}

  [DataType(DataType.Password)]
  public string ConfirmPassword {get; set;}

 // this validation is not db related and can be done client side...
 public IEnumerable<ValidationResult> Validate(ValidationContext validationContext)
    {
        string regex1 = @"^.{8,10}$";                   // 8 - 10 characters

        Match requirement1 = Regex.Match(Password, regex1);

        if (Password != ConfirmPwd)
            yield return new ValidationResult("Password and Confirm Password is not identical.");

        if (!requirement1.Success)
            yield return new ValidationResult("Password must be between 8 and 10 characters.");


    }

}

[HttpGet]
public ActionResult Login()
{
   var model = new LoginViewModel();

   return View("Login",model);
}

[HttpPost]
public ActionResult Login(LoginViewModel model)
{

   var user = GetUserFromRepositoryByUsername(model.username);

   if(user != null)
    {
      if(user.password == model.Password)
      {
        RedirectToAction("YouLoggedInYay!");
      }
    }

    // if we made it this far, the user didn't exist or the password was wrong.
    // Highlight the username field red and add a validation error message.
    ModelState.AddError("Username","Your credentials were invalid punk!");

   return View("Login",model);
}

答案 2 :(得分:0)

我会在您的ViewModel中包含userId或将其添加到URL上,以便控制器可以将其取出。

验证密码组合后,您可以使用Id检索相关用户并使用新密码进行更新。您可以在新密码后期操作中执行此操作。

您可能希望与旧密码btw匹配。

答案 3 :(得分:0)

据我所知,您的UI验证和逻辑验证不应混淆。即使它是相同的东西,也值得在逻辑中再做一次。基本上,实体对象不负责进行验证。可能是某些服务层类为实体执行此操作。而且你可能会在那时抛出异常。所以它在UI和逻辑中以完全不同的方式处理。

答案 4 :(得分:0)

“我只需要在编辑/创建配置文件时验证密码”

在ViewModel上使用与IsValid结合的数据注释来检查故障。至于将模型映射到视图模型,只需使用装饰器模式。

使用System.ComponentModel.DataAnnotations(它们甚至可以使用正则表达式验证器) 根据策略验证密码后,将其转换为MD5哈希并存储该密码,而不是密码值 如果所有其他方法都失败了,那么创建单独的UserValidation类并在View Model和Model之间共享逻辑就没有错。他们都用相同的方法来确定有效性(减少代码)。