C# mvc模型和viewmodel?
所以, 我有一个“用户”模型,它有很多字段,但以下是重要的字段:C# mvc模型和viewmodel?,c#,asp.net-mvc,entity-framework,data-annotations,C#,Asp.net Mvc,Entity Framework,Data Annotations,所以, 我有一个“用户”模型,它有很多字段,但以下是重要的字段: 我有一个视图模型,用于验证我在不同控制器上使用的密码: public class ConfirmPassword : IValidatableObject { [Required] public string Password { get; set; } [Required(ErrorMessage="Confirm Password field is required.")] public st
我有一个视图模型,用于验证我在不同控制器上使用的密码:
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.");
}
}
public类确认密码:IValidatableObject
{
[必需]
公共字符串密码{get;set;}
[必需(ErrorMessage=“确认密码字段是必需的。”)]
公共字符串ConfirmPwd{get;set;}
公共IEnumerable验证(ValidationContext ValidationContext)
{
字符串regex1=@“^.{8,10}$”;//8-10个字符
Match requirement1=Regex.Match(密码,regex1);
如果(密码!=ConfirmPwd)
返回新的ValidationResult(“密码和确认密码不相同”);
如果(!要求1.成功)
返回新的ValidationResult(“密码必须介于8到10个字符之间”);
}
}
是否有一种方法可以将视图模型连接到模型实体?还是复制粘贴代码是我唯一的选择?我不能做复制粘贴,因为代码需要一个IValidateObject,它会搞乱整个用户实体,因为有大量的后台审计发生。。我只需要在编辑/创建配置文件时验证密码
编辑:
如果大家都搞糊涂了,我很抱歉。基本上,我需要对确认密码进行多个验证,这些验证无法由dataannotations处理,因此需要confirmpassword视图模型。我希望将此验证应用于用户模型,但不在其中添加“ConfirmPassword”字段。因为我不需要数据库中的其他字段。我的问题是,当视图发布且密码字段不满足其要求时,如何强制从confirmapassword触发验证
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.");
}
}
}
名称空间
{
公共类用户
{
公共int Id{get;set;}
公共字符串用户名{get;set;}
公共字符串Pwd{get;set;}
}
}
名称空间
{
公共类ConfirmPassword:IValidatableObject
{
[必需]
公共字符串密码{get;set;}
[必需(ErrorMessage=“确认密码字段是必需的。”)]
公共字符串ConfirmPwd{get;set;}
公共IEnumerable验证(ValidationContext ValidationContext)
{
字符串regex1=@“^.{8,10}$”;//8-10个字符
字符串regex2=@“(?:.*[A-Z]){1}”;//1大写
字符串regex3=“;//1小写
字符串regex4=“”;//1个数字
Match requirement1=Regex.Match(密码,regex1);
Match requirement2=Regex.Match(密码,regex2);
Match requirement3=Regex.Match(密码,regex3);
匹配要求4=Regex.Match(密码,regex4);
如果(密码!=ConfirmPwd)
返回新的ValidationResult(“密码和确认密码不相同”);
如果(!要求1.成功)
返回新的ValidationResult(“密码必须介于8到10个字符之间”);
如果(!要求2.成功)
返回新的ValidationResult(“密码必须至少包含1个大写字母”);
如果(!要求3.成功)
返回新的ValidationResult(“密码必须至少包含1个小写字母”);
如果(!要求4.成功)
返回新的ValidationResult(“密码必须至少包含1个数字字符”);
}
}
}
我会在您的ViewModel中包含一个用户ID,或者将其添加到URL中,以便控制器可以拾取它
验证密码组合后,使用Id检索相关用户并用新密码更新。您可以在新密码post操作中执行此操作
顺便说一句,您可能希望与旧密码匹配。您可以使用视图模型中的装饰图案来执行您喜欢的操作。您还可以使用
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;
}
}
据我所知,您的UI验证和逻辑验证不应该混淆。即使是同一件事,在逻辑上也值得再做一次。基本上,实体对象不负责进行验证。可能是某个服务层类为实体执行此操作。在这一点上,你可能会抛出一个异常。因此,在UI和逻辑中,它是以完全不同的方式处理的 “每当编辑/创建配置文件时,我只需要验证密码” 在ViewModel上使用数据注释结合IsValid检查故障。至于将模型映射到视图模型,只需使用装饰器模式即可 使用System.ComponentModel.DataAnnotations(它们甚至有一个您可以使用的正则表达式验证器) 根据策略验证密码后,将其转换为MD5散列并存储该散列,而不是密码值
如果所有其他方法都失败了,那么创建一个单独的UserValidation类并在视图模型和模型之间共享逻辑没有什么错,例如,它们都调用相同的方法来确定有效性(减少代码)。好的,我仍然不太清楚您所说的将视图模型连接到模型实体是什么意思。。。我认为您现在需要检查实际用户的密码是否与传递给视图模型的密码匹配 我个人不会在视图模型本身中这样做,而是在控制器中这样做,如果密码不正确,我会添加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);
}
public LoginViewModel()
{
[必需]
公共字符串LoginId{get;set;}
[数据类型(数据类型.密码)]
公共字符串密码{get;set;
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);
}