gpt4 book ai didi

c# - DTO 和 Entity 是否都应该有输入验证

转载 作者:可可西里 更新时间:2023-11-01 08:45:33 27 4
gpt4 key购买 nike

我有一个 WCF 层,我的领域模型在这个 WCF 层后面。我正在使用 Nhibernate 作为 ORM 工具,我所有的业务逻辑/数据访问等都将在这个 WCF 层之后。

我正在向我的客户公开 DTO。我有以下问题

1) 我应该创建 DTO 吗?将实体直接暴露给 wcf 客户端有什么坏处,因为我的实体也会有业务逻辑方法,这样做我将不得不用我认为不好的 WCF 属性破坏我的实体对象?

2) 如果我公开 DTO,我是否应该验证 DTO 以及实体。如果我只验证 DTO,那么我不会为我的 Enitity 对象提供任何输入验证。这样可以吗?

3) 我是否应该考虑使用模式验证在应用程序服务层(WCF 层)中验证 DTO?或者我应该使用文章 [博客] 中给出的 IValidator 方法:http://lostechies.com/jimmybogard/2007/10/24/entity-validation-with-visitors-and-extension-methods/正如 Jimmy Bogard 所示

DTO 有时对我来说似乎是多余的,但我可以用它来合并一个或多个实体的详细信息。

我会向各种客户端公开此服务,因此我的 DTO 将从一些具有凭据详细信息的基本 dto 派生,我会在实际 wcf 方法调用之前检查每个传入请求(可能使用 IEndpointBehaviour 和 IParamInspector)


编辑

根据回复,我现在有点同意保留 DTO 层,这是一个例子,这样场景就变得更加明确

假设我的 WCF 应用程序服务层中有 CreateCustomer 方法接受 CustomerDetailsDTO,它可能会被 MVC 应用程序调用。有一些输入验证,例如

输入验证:

i)Name length should be greater than 2 but less than 50ii) Age is mandatory and cann not be less than 18(Different other field validations)etc 

业务验证:

There could then be some business rules to check for dupliate customer 
based on say email or some other factor whcih i think should be part of
my Domain business logic and should reside in CustomerEntity class.

当我们从客户端获取 DTO 时,是否应该仅在服务接口(interface)层应用输入验证或者它也应该应用于 CustomerEntity

最佳答案

1) Should i create DTOs? is there any harm in exposing entities directly to wcf clients as my entities would also have business logic methods also in doing so i would have to corrupt my entitiy object with WCF attributes which i think is not good?

是的,SOA 需要数据契约。

它们可以或多或少地形式化(CSV、JSON、XSD、WSDL、WADL 甚至 HTML 或 txt 文件),但如果您找不到此类契约(Contract)的协议(protocol),则不应采用任何“服务”技术或技术(也不是任何其他重要的 IPC)。

远程处理是唯一试图避免此类要求的技术。从抽象上讲,这是一个了不起的想法,但具体来说却行不通。

2) If i expose DTO, should i be validating DTO as well as Entity. If i validate only DTO then i am not providing any input validations for my Enitity object . is this ok?

您应该验证“契约(Contract)”,而不是业务规则。

例如,WCF DTO 可能需要填充一些字段,我会在构造函数中使用 ArgumentNullException

但是您应该记住,DTO 用于传输数据。如果您有一个数字字段由于某些奇怪的原因必须作为字符串传输,您可以验证它,例如防止 DTO 的初始化。

3) Should i consider validating the DTO in the Application Service layer (WCF layer) using Schema validation? or Should i use IValidator Approach given in article [blog]: http://lostechies.com/jimmybogard/2007/10/24/entity-validation-with-visitors-and-extension-methods/ as shown by Jimmy Bogard

如果你需要一个领域模型(这意味着你需要聘请专家来理解应用程序的目的),它必须是唯一负责业务规则的人 .因此对于简单的验证,您不需要任何验证框架。

你需要的是expressive exceptions可以很容易地映射到正确定义的故障。

编辑以回答新问题

在WCF中,我经常在DTO构造函数中使用输入验证,这样客户端就不能发送“无效请求”。这有很多优点,例如,客户端不能使用无效输入来配置 DOS 攻击。此外,如果您有大量客户端,这可以减少网络负载,并使用户体验更好一些,因为他不需要等待服务器响应只是为了知道他忘记了电子邮件字段中的@。

但实际上大于 18 岁是业务规则,而不是输入规则。

输入规则可以是:“年龄字段必须大于零”,因为负年龄是不可能的,零年龄听起来太像用户错误了(它是 int32 默认值)。

然而,契约(Contract)验证还不够

如果年龄与您的域相关,您将拥有一个 Age 结构,包装一个 UInt32(因此之前的 input 规则)。为什么要包装一个 UInt32?例如,因为在您的领域模型中,您知道两个用户年龄的总和没有意义。

是的,您最多检查该数字 3 次(一次在客户端上,两次在服务器上),但这是正确的做法,在这里。 DTO 可以独立于领域模型发展,并且领域模型不能冒意外行为的风险(或者您根本不需要领域模型)。

要了解业务规则,请考虑跟踪某种特殊疗法的医疗记录应用程序:command void Prescribe(Age patientAge, AntibioticPrescription prescription) 可以检查 patientAge 参数是否大于先前处方的年龄。这是商业规则。另一条业务规则应检查当前处方与之前处方之间是否存在危险的相互作用。

如果是这样,此命令应记录并抛出 3 个异常:

  • ArgumentNullException,当处方为空时(假设是引用类型)
  • InconsistentAge,当提供的patientAge小于上一个时
  • MortalPrescription,当这种处方可能会杀死病人时。

此类异常表示 preconditions这是业务规则(参数 null 除外,当程序员引入某种错误时,它会尽快失败)。

关于c# - DTO 和 Entity 是否都应该有输入验证,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20091826/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com