我正在设计一个包含ASP.NET MVC 4(Beta),VS 11(Beta),EF 5(Beta)的新网站,但这个问题适用于ASP.NET MVC 3,VS 2010,EF的发布版本4,也是。
第一步:我正在使用Entity Framework Code First方法,例如,我有以下用户模型:
public class User
{
[Key]
public int UserId {get;set;}
public String LoginName { get; set; }
public String Password { get; set; }
}
现在,为了注册我需要另一个模型,即注册模型:
public class Registration
{
public String LoginName { get; set; }
public String Password { get; set; }
public String PasswordConfirm { get; set; }
}
这是我的问题开始的地方:我应该在哪里放置我的DataValidation注释?例如,密码长度至少为10个字符,PasswordConfirmed必须与密码匹配,依此类推。我是否必须在每个可以使用密码做某事的模型上写这个(我正在考虑使用ChangePassword模型)
另一件事是如何处理控制器。当我显示我的注册ViewModel并且一切正常时,我是否创建用户模型并将注册ViewModel中的变量分配给它?
有时我会有很多属性进入数据库,但没有向用户显示(外键,计算值等)。
作为DRY的思考,我不想重复我的自我。
这个的最佳做法是什么?
要明确:注释不是必需的。如果有更好的验证方法,我很高兴,如果你展示它们。
答案 0 :(得分:2)
我不能客观地说哪个是“最佳做法”,但这就是我看到它的方式。 如果您绑定到视图模型,请验证视图模型,以便:
public class Registration
{
public String LoginName { get; set; }
[Required]
[StringLength(50, MinimumLength=10)]
public String Password { get; set; }
[Required]
[StringLength(50, MinimumLength=10)]
public String PasswordConfirm { get; set; }
}
您可以在控制器中“手动”进行验证,如果密码和确认匹配则检查POST
,如果没有向ModelState添加条目(但可能导致代码重复,并且是有点麻烦)或者在模型上使用漂亮的IValidatableObject
接口:
public class Registration : IValidatableObject
{
public String LoginName { get; set; }
[Required]
[StringLength(50, MinimumLength=10)]
public String Password { get; set; }
[Required]
[StringLength(50, MinimumLength=10)]
public String PasswordConfirm { get; set; }
public IEnumerable<ValidationResult> Validate(ValidationContext context)
{
if(Password != PasswordConfirm)
yield return new ValidationResult("Confirmation doesn't match", new[] {"PasswordConfirm"})
//etc.
}
}
现在,当您在POST
之后绑定模型时,只需调用ModelState.IsValid
即可完成验证,如果它无效,则会返回错误列表 - 包括您的错误自定义错误。
现在当然你可以将DataAnnotations放在DB模型上作为一个额外的措施,只是为了“以防万一”,以避免字符串截断异常等,如果你以某种方式忘记并试图将更长的字符串推送到数据库< / p>
对于映射,是的,在验证模型后,在POST
操作结束时,通常将属性从模型映射到新的User
实例(添加时)到DB)或现有的更新。您可以使用AutoMapper或使用反射自己编写一个天真的映射器 - 这是一个相对容易的任务,但最好将其作为一个独立的练习,重新发明轮子是没有意义的。
答案 1 :(得分:1)
您应该只在域图层中创建实体。但是当您需要为您的实体添加一些DataValidation Annotations时,可以使用MvcExtensions。如果您有一些复合或嵌套实体,并且希望将它们作为展平对象,则应使用automapper。这对您来说是最好的做法!