我正在使用POCO创建一个带有EF4的MVC3应用程序。我已经为我的EF实体添加了验证属性。现在,当我构建视图时,我想使用视图模型(也许使用AutoMapper来填充它们)。
我遇到的问题是我必须在我的视图模型上重新定义违反DRY主体的验证属性。例如,如果我决定更改字段的大小,我必须更改POCO和使用它的任何视图模型的MaxLength属性。
是否有一些棘手的方法可以将验证规则从我的POCO映射到我的视图模型?
答案 0 :(得分:5)
我个人在视图模型中执行验证。这是控制器从视图接收的内容,它是包含用户输入的类。我区分了两种类型的验证规则:表面验证和业务验证。应在视图模型中强制执行必填字段,正确格式等规则,而应在模型上验证数据库中已存在具有给定名称的用户等业务规则。
此外,您可以将不同的视图模型映射到同一模型,但基于视图验证规则可能会有所不同。因此,您不会在视图模型上具有完全相同的验证规则。
答案 1 :(得分:2)
获得抽象的一种方法是让ViewModel'由您的业务模型类组成',包括您需要的其他视图信息。
class MyObject
{
public int ID {get;set}
[Required]
[StringLength(512)]
public string Name {get;set;}
}
class MyViewModel // ViewModel for a specific view
{
public MyObject MyModel {get;set;} // the model that is being edited
// other data the view might need, set by the controller
public string SomeMessage { get; set; }
public List<SomeObject> SomeObjects {get;set;} /// e.g. for a drop-down list
}
然后在视图中相应地引用ViewModel。
@model My.Namespace.MyViewModel
Hello @model.MyModel.Name !!!
这样,您只能在一个地方指定商家类中的验证和/或数据注释。
如果您想要进行不同的验证,则需要一些策略来有选择地应用验证逻辑。
答案 2 :(得分:1)
我也很挣扎,我同意它违反DRY。我最近发布了一个关于这个Here的问题并得到了相当多的推迟。
在任何现实世界的应用程序中,你都无法获得完美的DRY。有时你会因违反原则而获得更多好处,而不是盲目地坚持下去。
编辑:
有人可能会认为DRY可能违反单一责任原则(SRP)。通过重用类似的代码,您现在正在使代码执行多个操作。如果您认为数据模型和视图模型具有不同的目的,从而具有不同的职责......将它们组合到单个模型中会违反SRP。也就是说,通过使您的数据模型也成为一个视图模型,这是两个不同的职责。
现在,人们可以想到在这方面可以尝试和协调SRP与DRY的多种方法,但在某些时候你必须权衡成本的好处。