mvc模型和viewmodel?

发布于 2024-11-17 14:07:18 字数 3065 浏览 2 评论 0原文

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


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.");

        }
    }
} 

so,
i have a "User" model that has a lot of fields but following are the impt ones:


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

and i have a view model that validates the password that i use on a different controller:

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.");


    }
}

is there a way where i can connect the view model to my model entity? or just copy paste the codes my only option? I can't do copy paste since the code needs to have a IValidateObject which will mess up the whole User entity as there's a ton of background auditing happeneing.. I just need to validate the passwords whenever a profile is edited / created.

EDIT:
so sorry if everybody got confused. basically, i have multiple validations that i need on the confirm passwords that can't be handled by dataannotations, ergo the confirmpassword viewmodel. this validation i want to be applied onto the User model but without adding the "ConfirmPassword" field into it. as i dont need another field on the database. My question is how do i force the validations i have from the confirmapassword to trigger whenever the view POSTs and the password field does not meet its requirements?

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.");

        }
    }
} 

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

何以畏孤独 2024-11-24 14:07:18

您可以在视图模型中使用装饰器模式来做您喜欢的事情。您还可以使用 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;
    }

}

You can use the decorator patter in your view model to do what you like. You can also use the System.ComponentModel.DataAnnotations namespace attributes to do all your validation for you.

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;
    }

}
来世叙缘 2024-11-24 14:07:18

好吧,我仍然对将视图模型连接到模型实体的含义有点不确定......我认为您现在想要的是检查实际用户的密码是否与传递到视图模型的密码匹配。

我个人不会在视图模型本身中执行此操作,而是在控制器中执行此操作,并且如果密码不正确,则会添加 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);
}

Ok, I am still a little iffy on what you mean by connect view model to model entity... I think what you want is to now check if the password from the actual user matches the password passed in to the view model.

I personally would not do this in the view model itself, but rather in the controller and would add a ModelState.AddError if the password was incorrect.

The normal input validation can happen on the server or client side if you are using client side validation, but you can't check the password client side, so it will have to go to the server.

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);
}
玻璃人 2024-11-24 14:07:18

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

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

顺便说一句,您可能想与旧密码匹配。

I would include a userId in your ViewModel or add it on the URL so the controller can pick it up.

After validating the password combo you use the Id to retrieve the relevant User and update it with the new password. You can just do this within your new password post action.

You may want to match with the old password btw.

北风几吹夏 2024-11-24 14:07:18

我认为,您的 UI 验证和逻辑验证不应该混淆。即使是同一件事,也值得在逻辑中重新做一遍。基本上,实体对象不负责进行验证。它可能是为实体执行此操作的某个服务层类。此时您可能会抛出异常。因此 UI 和逻辑中的处理方式完全不同。

From what I believe, your UI validations and Logic validations should not be mixed up. It is worth doing in over again in the Logic even if it is the same thing. Basically, it is not the responsibility of the Entity object to carry the validations. It might be some service layer class that does it for the Entity. And you can probably throw an exception at that point.So it is handled in completely different ways in the UI and the Logic.

攒一口袋星星 2024-11-24 14:07:18

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

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

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

"I just need to validate the passwords whenever a profile is edited / created"

Use data annotations combined with IsValid on the ViewModel to check for failures. As far as mapping a Model to a View Model just use a decorator pattern.

Use System.ComponentModel.DataAnnotations (they even have a regular expression validator you can use)
Once passwords are verified against a policy, convert them to an MD5 hash and store that, not the password value
If all else fails there is nothing wrong with creating a separate UserValidation Class and share logic between the View Model and Model e.g. they both call the same methods to determine validity (reducing code).

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文