DTO 和实体是否都应该具有输入验证

2023-12-26

我有一个 WCF 层,我的域模型位于该 WCF 层后面。我使用 Nhibernate 作为 ORM 工具,我的所有业务逻辑/数据访问等都将位于此 WCF 层后面。

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

1)我应该创建DTO吗?直接向 WCF 客户端公开实体是否有任何危害,因为我的实体也将具有业务逻辑方法,这样做我将不得不使用我认为不好的 WCF 属性来破坏我的实体对象?

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

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

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

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


Edit

根据响应,我现在同意保留 DTO 层,这是一个示例,以便场景变得更加明确

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

输入验证:



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

业务验证:


1)我应该创建DTO吗?直接向 WCF 客户端公开实体是否有任何危害,因为我的实体也将具有业务逻辑方法,这样做我将不得不使用我认为不好的 WCF 属性来破坏我的实体对象?

是的,SOA 需要data合同。

它们或多或少可以是正式的(CSV、JSON、XSD、WSDL、WADL,甚至 HTML 或 txt 文件),但如果您无法找到此类合同的协议,则不应采用任何“服务”技术或技巧(也没有任何其他 IPC)。

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

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

您应该验证“合同”,而不是业务规则。

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

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

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

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

你需要的是表达性例外 http://epic.tesio.it/2013/03/04/exceptions-are-terms-ot-the-ubiquitous-language.html可以轻松地将其映射到正确定义的故障。

编辑以回答新问题

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

但实际上年龄超过 18 岁是一个业务规则,而不是一个输入规则。

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

然而合同验证并不enough.

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

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

要了解业务规则,请考虑一个跟踪某种专门治疗类型的医疗记录应用程序:command http://epic.tesio.it/doc/manual/command_query_separation.html void Prescribe(Age patientAge, AntibioticPrescription prescription)可以检查患者年龄参数是否大于先前处方的年龄。那是一个business规则。另一项业务规则应该检查当前处方与前一个处方之间是否存在危险的相互作用。

如果是这样,这个命令应该记录并抛出3 个例外:

  • ArgumentNullException,当处方为空时(假设它是参考类型)
  • InconsistentAge,当提供的患者年龄低于上一个时
  • MortalPrescription,当这样的处方可能会杀死病人时。

此类异常表示前提条件 http://www.stanford.edu/class/cs295/lectures/lecture03.pdf那是business规则(除了参数 null,当程序员引入某种错误时,它会尽快失败)。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

DTO 和实体是否都应该具有输入验证 的相关文章

随机推荐

  • Django 管理员不处理 ProtectedError 异常

    我有一个 Django 应用程序 它的模型如下 class Foo models Model name models CharField max length 100 我在此模型中有一个特定实例 其名称为 bar 例如 我想防止删除该实例
  • 如何将 DataFrame 附加到多索引 DataFrame?

    假设我有 DataFrame In 1 a pd DataFrame 1 2 3 4 5 6 7 8 index pd MultiIndex from product A B d e In 2 a Out 2 0 1 A d 1 2 e 3
  • Xcode 崩溃后总是停在 main.m

    过去 使用旧的 良好的 Xcode 3 每次崩溃时 Xcode 都会停在显示崩溃的有问题的行处 这是美好的时光 很高兴调试 现在使用 Xcode 4 2 每次应用程序崩溃时 它都会停在 main m 的这一行 int retVal UIAp
  • 如何在Jaspersoft Studio中制作带有动态列的表格? [复制]

    这个问题在这里已经有答案了 我需要在 Jaspersoft Studio 中制作这张表 我的桌子有时有一个测试 两个 n 个测试或什么都没有 是否可以 我该如何解决这个任务 您无法在 jasper 中动态创建列 但在创建一些固定数量的列后
  • Android 开始屏幕上使用的手势

    使用什么 Android Api 来在 Android 上的开始屏幕上向左或向右滚动 最简单的方法是检测 Fling 手势 Android API 有一个内置的检测器 用于基本手势 如快速滑动 滚动 长按 双击 捏合缩放等 该文档位于htt
  • Mix.exs 文件更改 - (SyntaxError) mix.exs:65: 意外标记:“”(第 1 列,代码点 U+0000)

    保存所做的任何更改mix exsMac OS High Sierra 10 13 6 上的文件会导致文件开头处出现空字符 我最初是针对 intellij elixir 插件打开的 但问题是使用任何文本编辑器 sublime vim inte
  • 什么时候将标志存储为位掩码比使用关联表更好?

    我正在开发一个应用程序 其中用户具有不同的权限来使用不同的功能 例如读取 创建 下载 打印 批准等 权限列表预计不会经常更改 我有几个选项可以选择如何将这些权限存储在数据库中 在什么情况下选项 2 会更好 Option 1 使用关联表 Us
  • 有人可以解释一下这种类型的递归是如何工作的吗?

    我在递归中遇到了这个问题 我不明白它是如何工作的 我了解递归的基础知识 但这让我完全困惑 请帮忙 main foo 3 void foo int x if x gt 1 foo x printf d x foo x 我以为这个程序不会打印任
  • 使用 ImageMagick 检测 EXIF 方向并旋转图像

    佳能数码单反相机似乎可以横向保存照片并使用exif orientation进行旋转 问题 如何使用 imagemagick 使用 exif 方向数据将图像重新保存到预期方向 以便不再需要 exif 数据以正确的方向显示 Use the 自动
  • 检查 SQL 对象是否被任何其他 SQL 对象引用

    我刚刚在读书这个所以线程 https stackoverflow com questions 26336840 accessing the name of the currently executing stored procedure n
  • 解析没有键的 JSON 数组

    我正在尝试解析jsonArray但无法理解这种格式 如何解析这种类型jsonArray 谁能帮我 rows farmfresh 20171211 4 farmfresh product d 20171215 4
  • Selenium ChromeDriver 切换选项卡

    当我单击测试中的链接时 它会打开一个新选项卡 我希望 ChromeDriver 然后专注于该选项卡 我尝试了以下代码来让 ChromeDriver 使用 ctrl tab 快捷方式更改 tabas Actions builder new A
  • 函数“fn:encode-for-uri”导致 XSLT 出错

    我需要对 XSLT 中的字符串进行 URL 编码 但函数 fn encode for uri 破坏了脚本 我在网上查了一下 显然它是命名空间的一部分 http www w3 org 2005 xpath functions 因此 我将以下行
  • 与另一个启动文件链接

    我正在尝试使用以下命令将程序与我自己的启动文件链接STARTUPLD 脚本中的指令 ENTRY start STARTUP my crt1 o GCC驱动程序用于链接程序 不关心像libgcc等库路径 gcc T my script ld
  • 如何仅使某些结构字段可变?

    我有一个结构 pub struct Test pub x i32 pub y i32 我想要一个改变这个的函数 简单 pub fn mutateit mut self self x 1 这使得整个结构在函数调用期间是可变的mutateit
  • java中工厂方法模式如何使用泛型?

    我的代码如下所示 public interface BaseDAO marker interface public interface CustomerDAO extends BaseDAO public void createCustom
  • 如何让 SoapClient 尊重会话?

    我正在使用电子商务购物车的 SOAP API 但我似乎无法让会话在不同页面中持续存在 作为示例 我下面有一些测试代码 带有一堆调试消息 它将一个项目添加到购物车 然后查看购物车 当我在浏览器中运行它时 它工作得很好 但是如果我刷新页面 我预
  • Flutter Google Chart Gauge - 将标签放在中心内

    我正在看图表颤振 https pub dartlang org packages charts flutter包裹 我需要实现一个仪表图表 其中有一个分段及其标签值位于仪表的中心 请参阅下面的模型文件 其中所需类型的三个图表放置在一行中 使
  • 仅使用变量进行单元测试

    我正在使用 Objective c 为 iPhone 应用程序编写单元测试 例如 我只想在编译测试用例时使用一些变量 ifdef UNIT TESTING synthesize requestFinished networkAvailabl
  • DTO 和实体是否都应该具有输入验证

    我有一个 WCF 层 我的域模型位于该 WCF 层后面 我使用 Nhibernate 作为 ORM 工具 我的所有业务逻辑 数据访问等都将位于此 WCF 层后面 我正在向我的客户公开 DTO 我有以下问题 1 我应该创建DTO吗 直接向 W