根据 DTO、实体模型或其他东西验证服务层中的数据?

Posted

技术标签:

【中文标题】根据 DTO、实体模型或其他东西验证服务层中的数据?【英文标题】:Validating data in the service layer against DTOs, Entity Models, or something else? 【发布时间】:2018-01-05 01:18:37 【问题描述】:

我正在开发一个 ASP.NET MVC 项目。在项目中,我有一个接受 DTO 进行 CRUD 操作的服务层。当我需要验证业务逻辑时,验证器应该完全接受 DTO、实体模型还是其他东西?

例如:

public class ProductService: IProductService

    public ValidationResult CreateProduct(ProductDTO productDto)
    
       //call productValidator.Validate(productDto) on the DTO here?

        Product productEntityModel = mapper.Map<Product>(productDto);

        //or, call productValidator.Validate(productEntityModel) on the Entity model here?

        if(validationResult.Valid)
        
            _dbContext.Products.Add(productEntityModel);
            _dbContext.SaveChanges();
        

        return validationResult
    

一些想法:

我在网上看到一些关于创建 POCO 的讨论,该 POCO 可以具有验证逻辑(而不是使用验证服务),甚至可以在其中包含其他业务逻辑。这是有道理的,但它又是一种必须管理和维护的产品的“代表”。 根据 DTO 进行验证可能看起来更合理一些,因为那是调用者正在发送到服务?

感谢您的帮助!

【问题讨论】:

我使用 DTO 方法并有一个问题。当您的方法签名为 List&lt;History&gt; ListHistory(int userId, string specialString) 时,您将如何返回验证错误? 【参考方案1】:

当我需要验证业务逻辑时,验证器是否接受 DTO、实体模型,还是完全其他的东西?

通常,我们在ViewModel 类中使用DataAnnotations 执行验证,以便我们可以返回用户友好的ModelError。例如,

public class LoginViewModel

   [Display(Name = "Username")]
   [Required(ErrorMessage = "Please enter your username.")]
   public string UserName  get; set; 


public async Task<ActionResult> Login(LoginModel model, string returnUrl)

   if (ModelState.IsValid)
   
      ...
      ModelState.AddModelError("", "User is not authorized!");
   
   ...

虽然您可以验证 ProductService 内部的一些业务逻辑,但您不能返回 MVC ModelError,因为服务/存储库层不应依赖于 ASP.NET MVC(或任何 UI 组件)。

Service/Repository Layer 中的大部分错误都是意外错误,而不是用户错误。我们通常在 NLog 或 Log4Net 中记录这些错误,并将用户重定向到自定义错误页面。

【讨论】:

我应该指定需要数据库访问的深层/复杂逻辑,而不是像必填字段这样的简单验证。例如,验证数据库中不存在另一个同名产品。 个人喜欢将业务逻辑保留在操作方法中。我喜欢我的服务/存储库层尽可能干净。看看这个基于 ASP.NET MVC 的最好的开源购物车之一 - Create Action Method 和 InsertCustomer method 在 Repository/Service 类中。 啊,我个人喜欢 Service 或 Core 项目中的业务逻辑,而不是 web/presentation 项目。如果需要添加另一个表示层或需要使用单独的 API,我不想重复逻辑。 没有正确或错误的答案。看来您已经准备好做出决定了;我会说去吧。

以上是关于根据 DTO、实体模型或其他东西验证服务层中的数据?的主要内容,如果未能解决你的问题,请参考以下文章

(扫盲)DTO数据传输对象

暴露 DTO 或实体的 WCF 服务

MVC 3 应用程序中的模型、视图模型、DTO

在 RESTful API 中创建和验证实体模型及其 DTO 的正确方法是啥?

我们为什么需要DTO(数据传输对象)

Spring Rest API 验证应该在 DTO 中还是在实体中?