如何保持验证DRY?

时间:2011-01-10 11:11:15

标签: .net asp.net asp.net-mvc asp.net-mvc-3 automapper

使用此方法在MVC中查看模型:http://www.lostechies.com/blogs/jimmy_bogard/archive/2009/06/29/how-we-do-mvc-view-models.aspx

在我的脑海中留下了一个悬而未决的问题。所以现在是我清理它的时候了。

如果我使用自动映射器将域属性映射到dto,那么我很欣赏当dto映射到保存的域实体时,我的域层可以返回一组验证规则。

但是,我没有看到DRY方法让客户端验证工作并将错误添加到模型状态,因此它们对应于视图模型上的正确属性。

干杯

3 个答案:

答案 0 :(得分:11)

我发现了一个相关的问题,并提出了一些有趣的回答:

Mapping Validation Attributes From Domain Entity to DTO

我一直在考虑这个问题,在某种程度上它类似于我们在服务器端和客户端验证方面的情况。 (例如,同时使用NHibernate Validator和jQuery.validate)。

现在很好地接受了您应该拥有一整套服务器端验证,并且您可以选择添加客户端验证,以使您的应用程序更加用户友好。过去,您必须手动实施客户端验证,但由于可用性的好处,您接受了重复工作。

我认为我们在这里处理的非常相似。您应该在您的域图层中进行验证。您不能依赖消费应用程序来自己添加验证。

然后,您可以在应用程序中选择在DTO /视图模型上添加验证。这样做是因为在视图中处理验证错误更有帮助,而不是让它们通过可能引发异常或提供不太有用的错误消息的域。关键是从域的角度来看,你不依赖于这一点。你仍然对你的系统充满信心,因为你知道是否有任何不良数据通过,你的模型会抓住它。

客户端/服务器案例近来不成问题,因为已经做了很多工作来自动化它,从服务器端代码生成客户端代码(例如ASP.Net MVC中的ModelValidatorProvider)。我相信随着越来越多的人开始使用视图模型/ DTO,我们将开始看到类似的解决方案,用于自动将域验证映射到DTO(it's already happening with AutoMapper)。

简而言之,我的(务实而不是理想;))答案是:

暂时接受违反DRY的行为,在这两个地方进行验证,并尝试为将来自动化的项目做出贡献

答案 1 :(得分:5)

我更喜欢将Model作为ViewModel上的属性以及其他特定于视图的字段。这样它在绑定期间由MVC验证,并且当不通过MVC绑定时我可以在后端验证它。这样,客户端验证由MVC提供,我得到的验证对象没有直接绑定到视图的干净模型。

public class MyViewModel
{
    public MyModel MyModel {get;set;}
    public bool IsSomethingAllowed {get;set;}
}

public class MyModel
{
    public int Id {get;set;}
    [Required]
    public string Name {get;set;}
}

答案 2 :(得分:2)

一种常见的方法是将所有验证放在视图模型中,通常使用数据注释。 MVC允许您从数据注释中自动生成客户端(javascript)验证。很干。

您的控制器发布操作接受视图模型并检查IsValid属性。这样,您在客户端和服务器上使用相同的代码进行验证(或者,在数据注释的情况下,我应该说属性):

[HttpPost]
public ActionResult ResetPassword(ResetPasswordViewModel viewModel)
{
  if (ModelState.IsValid)
  {
    // convert to dto/entity and pass to next layer
    // redirect to success page
    return RedirectToAction("ResetPasswordSuccess");
  }
  // display original view which will display error messages
  return View();
}

只是通过让控制器操作将viewModel作为参数来添加,默认的MVC模型绑定器将自动验证您的viewmodel并将任何错误添加到ModelState错误集合中,该集合用于显示视图中的错误。