8

假设您有一个使用域模型模式、DDD 和许多其他设计模式的应用程序。假设我们有许多解决方案,如下所示:

  • 解决方案.模型
  • 解决方案.存储库
  • 解决方案.服务
  • 解决方案.介绍
  • 解决方案.UI.Web

用户体验层是 Solution.UI.Web,我们假设它是一个 ASP.NET WebForms 应用程序。您如何执行客户端验证?

有很多事情需要考虑:

首先,我们不应该访问应用程序/数据库服务器来向客户端返回任何验证错误,但是我们也可以实现服务器端验证,但我们也需要客户端验证.

其次,我们不想在用户体验层实现验证规则。那是因为如果您的应用程序是一个 WebApp,然后您决定创建一个 WinApp 客户端,那么您将不得不重新实施验证规则 --> 维护噩梦。

一种简单的方法是使用 ViewModel 对象(将发送到客户端的域实体的扁平视图)实现验证逻辑,然后在访问应用程序/数据库服务器之前验证这些对象。

另一种方法,我见过在不同的应用程序中多次使用的方法,就是生成一组验证错误消息并将该集合发送到客户端。这很好,但有一个问题。只是验证错误的简单摘要消息是行不通的,特别是如果您有大数据输入表单。

现在,ASP.NET MVC 框架让生活变得更加轻松。您可以使用 EF + DataAnnotations,而 MVC Scaffolding 框架可以为您完成大部分工作。但如果您想创建一个 MVC 应用程序并使用 jQuery 和 JavaScript 实现您的验证逻辑,情况就是如此。

但是,如果您需要一种更通用的方法来实现可以在不同应用程序中使用和使用的验证框架,比如 WinForms 和 WebForms 怎么办?

澄清一下,我正在寻找的是一组设计模式/原则和/或技术/框架来实现一个验证框架,可以用你的域模型来实现,然后在你的客户端应用程序上强制执行。而且,我不想只返回有关违反规则或任何内容的字符串错误消息集合,我希望能够在验证失败时更新我的​​数据绑定控件(TextBox、ComboBox、DateTimePicker 等),以便用户体验层会更直观(如果你愿意的话)。

我在这里和那里看到了一些实现和框架,并且我已经使用 ASP.NET MVC 客户端验证有一段时间了,所以我的回答与 MVC 或 JavaScript 验证没有任何关系。

4

3 回答 3

5

在 DDD 中,域通常是自我验证的。换句话说,不允许对象处于无效状态。值对象在这里有很大帮助。它们只是封装了格式化规则。例如,您可以拥有保证始终格式正确的类ZipCode 。作为一个额外的责任,它可以有一个静态方法,如ZipCode.TryParseZipCode.Validate这将采用任意字符串作为参数并进行验证。这种方式验证逻辑集中在一个地方。如果您的域对象可以直接从 UI 访问,那么您不需要在其他任何地方复制此逻辑。胖客户端(Windows 窗体、WPF)就是这种情况。不幸的是,当 Web 客户端需要在不往返服务器的情况下执行验证时,无法避免一些重复。

于 2011-08-11T01:55:10.030 回答
4

您应该将验证逻辑封装在代表您的领域知识的简单类中。

我在我的原始痴迷博客文章中写过它。如果您创建此类类,您的 ASP.NET MVC 控制器可能如下所示:

public class CustomerController : Controller
{
    [HttpPost]
    public ActionResult CreateCustomer(CustomerInfo customerInfo)
    {
        Result<Email> emailResult = Email.Create(customerInfo.Email);
        Result<CustomerName> nameResult = CustomerName.Create(customerInfo.Name);

        if (emailResult.Failure)
            ModelState.AddModelError("Email", emailResult.Error);
        if (nameResult.Failure)
            ModelState.AddModelError("Name", nameResult.Error);

        if (!ModelState.IsValid)
            return View(customerInfo);

        Customer customer = new Customer(nameResult.Value, emailResult.Value);
        // Rest of the method
    }
}

无需使用注释,因为它们本质上鼓励您复制验证逻辑。

比较这些代码示例:

于 2015-03-07T14:19:39.097 回答
3

我还没有遇到一个包罗万象的验证解决方案。原因之一是验证逻辑可能会因应用层而略有不同。例如,并非域层强制执行的所有规则都可以在客户端强制执行,因此总会有客户端验证可能通过但您仍然需要显示从域层传播的验证消息的情况。

但是,ASP.NET MVC 中的验证模型是可扩展的,您可以对其进行扩展以支持其他验证规则或事件验证框架而不是 DataAnnotations。是一个将 Enterprise Library Validation 块与 ASP.NET MVC 集成的示例,但是正如文章指出的那样,客户端验证没有实现。另一种方法是在域层中使用 DataAnnotations 属性。DataAnnotations 命名空间不绑定到 ASP.NET MVC。

然而,这些方法的挑战在于将验证规则从域对象传播到视图模型。理论上,您可以扩展AutoMapper,以便将域模型中的验证规则传递到视图模型类,但是实施和维护的成本可能超过此解决方案的好处。

Fluent Validation框架可以用作一个包罗万象的验证解决方案的起点。有许多将这个框架与 ASP.NET MVC 结合使用的示例

于 2011-08-07T22:18:03.137 回答