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

C# DTO和实体是否都应具有输入验证,c#,wcf,validation,nhibernate,domain-driven-design,C#,Wcf,Validation,Nhibernate,Domain Driven Design,我有一个WCF层,我的域模型在这个WCF层后面。我使用Nhibernate作为ORM工具,我所有的业务逻辑/数据访问等都将在这个WCF层后面 我向我的客户公开DTO。我有以下问题 1) 我应该创建DTO吗?直接向wcf客户机公开实体有什么害处吗?因为我的实体也会有业务逻辑方法。在这样做的时候,我会用wcf属性损坏我的实体对象,我认为这是不好的 2) 若我公开DTO,我应该验证DTO以及实体。如果我只验证DTO,那么我不会为我的Enitity对象提供任何输入验证。这样行吗 3)是否应该考虑使用模

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

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

1) 我应该创建DTO吗?直接向wcf客户机公开实体有什么害处吗?因为我的实体也会有业务逻辑方法。在这样做的时候,我会用wcf属性损坏我的实体对象,我认为这是不好的

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

3)是否应该考虑使用模式验证来验证应用程序服务层(WCF层)中的DTO?或者我应该使用[博客]文章中给出的IValidator方法:如Jimmy Bogard所示

拥有DTO有时对我来说似乎是多余的,但我可以使用它来从一个或多个实体了解俱乐部的细节

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


编辑 基于我现在有点同意保留DTO层的响应,这里有一个exmaple,以便场景变得更加明确

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

输入验证:

i) 名称长度应大于2但小于50 ii)年龄是强制性的,不得低于18岁 (不同的其他现场验证)等
业务验证:

然后,可能会有一些业务规则来检查重复客户
基于电子邮件或其他一些因素,我认为这应该是我的域业务逻辑的一部分,并且应该位于CustomerEntity类中。 当我们从客户端获得DTO时,输入验证是否应该只应用于服务接口层
或者它也应该应用于CustomerEntity

拥有DTO总是一件好事,它可以将我们的域对象隐藏在任何UI或外部处理中。这还允许您创建稍微不同的对象结构,因为您的域模型可能与数据库关系图非常紧密,并且不能总是反映对象的逻辑含义

也就是说,不应该通过服务直接公开实体

要将实体转换为DTO,我在大多数情况下都使用Automapper,这非常方便

关于验证,例如,您可以在实体上使用数据注释来验证它们

但是,如果您的DTO反映了不同类型或更复杂的业务逻辑,而单靠注释是无法验证的,那么您可以使用类似的东西,这是非常灵活且易于设置的

我目前正在一个项目中使用这些。 例如,对于标准验证,如必填字段、字段长度,甚至电子邮件或电话号码验证,您可以使用简单的数据注释和正则表达式等

对于复杂的事情,如字段A为空字段B不能为空等,您可以使用fluent验证。。。这实际上取决于您是在实体级别还是在DTO级别执行此操作。如果您没有任何仅由DTO反映的自定义逻辑,DTO可以是视图模型(就MVC而言),那么您可以在实体级别执行所有这些操作

这还取决于您的应用程序是否是使用实体的唯一应用程序。如果您计划将您的实体和数据访问层作为api公开给其他开发人员,那么大多数验证都应该在该级别上完成

1) 我应该创建DTO吗?直接向wcf客户机公开实体有什么害处吗?因为我的实体也会有业务逻辑方法。在这样做的时候,我会用wcf属性损坏我的实体对象,我认为这是不好的

是的,SOA需要数据契约

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

远程处理是唯一试图避免这种要求的技术。这是一个惊人的想法,抽象地说,但具体地说,它不起作用

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

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

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

但您应该记住,DTO用于传输数据。如果您有一个数字字段,由于某些奇怪的原因必须将其作为字符串传输,则可以对其进行验证,例如防止DTO的序列化

3)是否应该考虑使用模式验证来验证应用程序服务层(WCF层)中的DTO?或者我应该使用[博客]文章中给出的IValidator方法:如Jimmy Bogard所示

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

您需要的是可以轻松映射到正确定义的故障

编辑以回答新问题

在WCF中,我经常在DTO构造函数中使用输入验证,这样客户端就不能发送“无效请求”。这有很多优点,例如客户端不能使用无效的inpu 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
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.