16

这里是地势。像大多数人一样,我有我的领域对象和我的视图模型。我喜欢使用视图模型的想法,因为它允许专门为给定的视图上下文创建模型,而无需更改我的业务对象。

我遇到的问题是在我的域对象上定义类型级别验证并将这些规则发送给客户端。在这种情况下,假设我使用数据注释来描述验证规则,当我将数据从域对象移动到视图模型时,视图模型不再知道它应该让接口执行什么验证(因为验证是在域对象上定义)。

使用 MVC 2,您可以让它根据当前对象的验证规则自动执行客户端/服务器端验证。但是因为验证规则是在域对象而不是视图模型上定义的,所以我必须在视图模型上复制验证规则才能使其正常工作。

其他人如何处理此类问题?我的想法是除了将域对象的数据映射到视图模型之外,我们还需要跨验证规则进行映射,但是我还没有真正看到其他人谈论这个问题...... Brad Wilson 最近谈到了这个问题最后,但还没有真正解决域对象和视图模型上的规则重复问题……您的想法是什么?

干杯安东尼

4

5 回答 5

3

DataAnnotation 属性是关于验证输入并向最终用户提供 UI 反馈。这确实是他们唯一的预期用途。我对 UI 对象和业务对象使用不同的验证策略,因此 DA 验证属性最终只出现在向用户显示的模型上。

于 2010-02-06T17:48:06.207 回答
2

这可能不合适,但是如果您只是将验证规则/注释从模型移动到视图模型怎么办?在我参与的一些项目中,我们选择阻止 View 访问除通过其相应 ViewModel 公开的信息之外的任何内容。由于所有数据交互都将通过 ViewModel 执行,因此不需要对 Model 对象进行验证。

这个论点的反驳是你可以很容易地复制某些验证规则,因为不同的 ViewModel 可能与相同的 Model 交互。在这种情况下,将您的模型简单地声明为在您的 ViewModel 上公开的属性可能是有意义的。对于回发,他们可以接受一个模型作为他们的参数,允许 ModelBinder 基础设施来处理请求。在这种情况下,如果 ModelState.IsValid 为 false,您可以在重新显示视图之前将属性重新分配给您的 ViewModel。

我建议将您的注释移动到您的 ViewModel。这是有道理的,因为很多视图是 a) 多个模型组合的结果或 b) 模型数据的子集。

于 2010-02-02T08:07:23.660 回答
2

事实证明,AutoMapper 或许能够自动为我们做这件事,这是最好的情况。

AutoMapper-users:将验证属性转移到视图模型?
http://groups.google.com/group/automapper-users/browse_thread/thread/efa1d551e498311c/db4e7f6c93a77302?lnk=gst&q=validation#db4e7f6c93a77302

我还没有开始尝试那里提出的解决方案,但打算很快尝试。

(Cross 也在我的(欺骗)问题上发布了这个)。

于 2010-02-20T11:09:18.620 回答
0

也许我们根本不应该使用视图模型?并在模型层实体上定义验证规则..

于 2010-02-02T12:24:55.577 回答
0

我也考虑了一段时间。我完全理解布拉德的回答。但是,假设我想使用另一个适用于注释域实体和视图模型的验证框架。

我可以在纸上提出的唯一仍然适用于属性的解决方案是创建另一个“指向”您在视图模型中镜像的域实体属性的属性。这是一个例子:

// In UI as a view model.
public class UserRegistration {
  [ValidationDependency<Person>(x => x.FirstName)]
  public string FirstName { get; set; }

  [ValidationDependency<Person>(x => x.LastName)]
  public string LastName { get; set; }

  [ValidationDependency<Membership>(x => x.Username)]
  public string Username { get; set; }

  [ValidationDependency<Membership>(x => x.Password)]
  public string Password { get; set; }
}

可以扩展像 xVal 这样的框架来处理这个新属性并在依赖类的属性上运行验证属性,但使用您的视图模型的属性值。我只是没有时间进一步充实这一点。

有什么想法吗?

于 2010-02-17T23:43:18.887 回答