简体   繁体   English

DDD和客户端验证

[英]DDD & client-side validation

Suppose you have an application that utilizes the domain-model pattern, DDD and lots of other design patterns. 假设您有一个使用域模型模式,DDD和许多其他设计模式的应用程序。 assume that we have a number of solutions as listed below: 假设我们有许多解决方案,如下所示:

  • Solution.Model Solution.Model
  • Solution.Repository Solution.Repository
  • Solution.Services Solution.Services
  • Solution.Presentation Solution.Presentation
  • Solution.UI.Web Solution.UI.Web

The user experience layer will be Solution.UI.Web and we'll assume that it'll be an ASP.NET WebForms application. 用户体验层将是Solution.UI.Web,我们假设它将是一个ASP.NET WebForms应用程序。 how do you enforce client-side validation? 你如何执行客户端验证?

There are a number of things to be considered: 有许多事情需要考虑:

First and foremost, we shouldn't have to hit the application/database server(s) to return any validation errors to the client, we could however implement server-side validation too, but we're gonna need client-side validation as well. 首先,我们不应该点击应用程序/数据库服务器将任何验证错误返回给客户端,但我们也可以实现服务器端验证,但我们还需要客户端验证。

Second, we don't want to implement the validation rules on the user experience layer. 其次,我们不希望在用户体验层上实现验证规则。 that's because if your application is a WebApp and then you decide to create a WinApp client as well, you're gonna have to implement the validation rules all over again --> maintenance nightmare. 那是因为如果您的应用程序是WebApp,然后您决定创建一个WinApp客户端,那么您将不得不再次实施验证规则 - >维护噩梦。

One simple approach would be to implement your validation logic withing your ViewModel objects (flattened views of your domain entities that will be sent to the client) and then validate those objects before hitting the application/database server(s). 一种简单的方法是使用ViewModel对象(将被发送到客户端的域实体的展平视图)实现验证逻辑,然后在命中应用程序/数据库服务器之前验证这些对象。

Another approach, one that I have seen used many times in different applications, is to just generate a collection of validation error messages and send that collection to the client. 我见过的另一种方法是在不同的应用程序中多次使用,只是生成一组验证错误消息并将该集合发送给客户端。 that's fine, but there's a problem. 那没关系,但是有问题。 just a simple summary message of validation errors won't do, specially if you have big data entry form. 只是一个简单的验证错误摘要消息将不会发生,特别是如果您有大数据输入表单。

Now the ASP.NET MVC framework makes life much easier. 现在,ASP.NET MVC框架使生活变得更加容易。 you can use EF + DataAnnotations, and MVC Scaffolding framework can do most of the job for you. 您可以使用EF + DataAnnotations,而MVC Scaffolding框架可以为您完成大部分工作。 but that's the case if you want to create an MVC application and implement your validation logic with jQuery and JavaScript. 但是如果你想创建一个MVC应用程序并使用jQuery和JavaScript实现验证逻辑就是这种情况。

But what if you need a more generic approach to implement a validation framework that can be utilized and used in different applications, say WinForms and WebForms ? 但是,如果你需要一种更通用的方法来实现一个可以在不同的应用程序中使用和使用的验证框架,比如WinForms和WebForms呢?

Just to clarify, what im looking for is a set of design patterns/principles and/or techniques/frameworks to implement a validation framework that can be implemented withing your domain model and then be enforced on your client applications. 只是为了澄清,我正在寻找的是一组设计模式/原则和/或技术/框架,以实现一个验证框架,该框架可以使用您的域模型实现,然后在您的客户端应用程序上实施。 And, I don't want to just return a collection of string error messages about the broken rules or anything, I want to be able to update my data-bound controls (TextBox, ComboBox, DateTimePicker, etc) upon validation failure so that the user experience layer would be more intuitive (if you will). 并且,我不想只返回关于破坏的规则或任何东西的字符串错误消息的集合,我希望能够在验证失败时更新我的​​数据绑定控件(TextBox,ComboBox,DateTimePicker等),以便用户体验层将更直观(如果您愿意)。

I have seen some implementations and frameworks here and there, and I have used ASP.NET MVC client-side validation for a while now, so my answer doesn't have anything to do with MVC or JavaScript validation. 我已经看到了一些实现和框架,我已经使用了ASP.NET MVC客户端验证一段时间了,所以我的答案与MVC或JavaScript验证没有任何关系。

In DDD, domain is usually self validating. 在DDD中,域通常是自我验证的。 In other words objects are not allowed to be in invalid state. 换句话说,不允许对象处于无效状态。 Value objects help a lot here. 值对象在这里有很多帮助。 They simply encapsulate formatting rules. 它们只是封装格式规则。 For example you can have class ZipCode that is guaranteed to always be well formed. 例如,您可以保证ZipCode类始终保持良好状态。 As an additional responsibility it can have a static method like ZipCode.TryParse or ZipCode.Validate that will take arbitrary string as parameter and validate. 作为一项额外的职责,它可以有一个静态方法,如ZipCode.TryParseZipCode.Validate ,它将任意字符串作为参数并进行验证。 This way validation logic is concentrated in one place. 这种方式验证逻辑集中在一个地方。 If your domain objects are accessible directly from UI than you don't need to duplicate this logic anywhere else. 如果您的域对象可以直接从UI访问,则不需要在其他任何地方复制此逻辑。 This is the case for fat clients (Windows Forms, WPF). 胖客户端就是这种情况(Windows窗体,WPF)。 Unfortunately there is no way to avoid some duplication for web clients when they are required to perform validation without round-tripping to server. 遗憾的是,当需要执行验证而不向服务器进行往返运行时,无法避免Web客户端的某些重复。

You should encapsulate the validation logic in simple classes which represent your domain knowledge. 您应该将验证逻辑封装在代表您的领域知识的简单类中。

I write about it in my primitive obsession blog post. 我在原始的痴迷博客文章中写到这一点。 Here's how your ASP.NET MVC controller may look like if you create such classes: 以下是创建此类时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
    }
}

No need to use Annotations because they essentially encourage you to duplicate the validation logic. 无需使用注释,因为它们本质上鼓励您复制验证逻辑。

Compare these code samples: 比较这些代码示例:

I have not come across an all encompassing validation solution. 我没有遇到一个包罗万象的验证解决方案。 One reason for this is that validation logic can be subtly different depending on the application layer. 其中一个原因是验证逻辑可能根据应用层的不同而略有不同。 For example, not all rules enforced by the domain layer can be enforced on the client side and so there will always be cases where client side validation may pass and yet you still need to display a validation message which propagated from the domain layer. 例如,并非所有由域层强制执行的规则都可以在客户端强制执行,因此始终存在客户端验证可能通过的情况,但您仍需要显示从域层传播的验证消息。

However, the validation model in ASP.NET MVC is extensible and you can extend it to support additional validation rules or event a validation framework other than DataAnnotations. 但是,ASP.NET MVC中的验证模型是可扩展的,您可以扩展它以支持其他验证规则或事件除DataAnnotations之外的验证框架。 Here is an example of integrating Enterprise Library Validation block with ASP.NET MVC, however as the article points out, client side validation was not implemented. 以下是将Enterprise Library Validation块与ASP.NET MVC集成的示例,但正如文章所指出的,未实现客户端验证。 Another approach would be to use DataAnnotations attributes in your domain layer. 另一种方法是在域层中使用DataAnnotations属性。 The DataAnnotations namespace is not tied to ASP.NET MVC. DataAnnotations命名空间与ASP.NET MVC无关。

The challenge in these approaches however is that of propagating validation rules from domain objects to view models. 然而,这些方法中的挑战是将验证规则从域对象传播到视图模型。 In theory, you can extend AutoMapper such that validation rules from a domain model are carried over to view model classes, however the cost of implementation and maintenance may outweigh the benefits of this solution. 从理论上讲,您可以扩展AutoMapper ,以便从域模型中继承验证规则以查看模型类,但实现和维护的成本可能超过此解决方案的优势。

The Fluent Validation framework could be used as a starting point for an all encompassing validation solution. Fluent Validation框架可用作全面验证解决方案的起点。 There are many examples of using this framework with ASP.NET MVC. 有许多使用ASP.NET MVC的框架的例子

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM