2012-09-04 171 views
3

最近我一直在做关于DTO的大量阅读,从未使用过它们。我读过的一篇文章谈到了DTO应该如何不仅仅复制域模型对象,而是每个DTO应该适合正在执行的服务操作。如何验证客户端服务器应用程序的DTO

如果我决定使用DTO并且想知道下面是否可以接受,这让我想到了验证吗?

public class Person { 
    public Guid Id {get; set;} 
    public string Name {get; set;} 
    public Address Address {get; set;} 
} 

public class Address { 
    public Guid Id {get; set;} 
    public string AddressLine1 {get;set;} 
    ... 
} 

publuc class CreatePersonDTO { 
    private string _name; 
    private string _addressLine1; 

    public string Name { 
     get { 
      if (_name == null) 
       throw new Exception("Missing"); 

      return _name; 
     } 
     set { _name = value; } 
    } 

    public string AddressLine1 { 
     get { return _addressLine1; } 
     set { _addressLine1 = value; } 
    } 
} 

所以,你通过任何JSON或XML传递你的数据,这是序列化对象CreatePersonDTO和映射这些值创建一个Person和Address对象时,如果人缺少名称那么它会抛出一个验证例外。

由于DTO本身就是特定于服务操作的,所以在这里进行验证是好的还是打破了某种有关业务逻辑应该驻留的规则?

回答

4

DTOs应该没有验证;它们是严格用于传输数据。除了验证之外,他们应该根本没有任何行为。

如果名称是必需的,那是域或给定服务操作的一个方面;验证应封装在相应的位置(尽管您也可以在UI中执行规则以获得更好的体验)。

+0

同意。你需要的最后一件事是你的DTO在WCF(或其他通信提供者)深处的数据序列化/反序列化层中抛出异常。另一个好处是通过保持DTO的仅数据,很可能你可以在两个地方使用相同的代码文件(比如说Silverlight和ASP.NET Web服务),这样你可以保证,如果你添加/删除/更改属性,每个来源相应地更新。只要您在那里进行验证(甚至是日志记录),就很有可能它不适合不同的环境/平台。 –

+1

好吧,我可以看到这将是一个坏主意。有没有一个干净的模式来验证DTO的不涉及'if(String.IsNullOrEmpty(personDto)在我的控制器中间抛出新的异常...'? – David

+0

@David您是否想要验证DTO是否从您的服务以有效状态返回? – Jay

1

这取决于。但通常将验证登录放入DTO并不是一个好的地方。您将有可重用性的问题。例如,如果您需要更新人员,则必须创建UpdatePersonDTO并将所有相同的逻辑放在那里。
作为另一种选择,您可以将验证逻辑放入Person中,以便您无法创建无效的人员,并且可以重用。或者您可以将实体验证逻辑放入某种服务层。

2

我会解释每个DTO应该适合执行的服务操作意思是如果你有庞大的域对象DTO可以表示一个与特定服务操作相关的子集。即它可能只对域对象的一些属性感兴趣。

+0

是的,这也是我所说的。 – David

1

您不应该将验证逻辑放入您的DTO中,这应该主要由您的域层处理,并且在某些情况下应该在您的UI层中进行复制。你的DTO应该就是这样,笨重的对象来传输数据。

除了责任分离之外,你的逻辑实际上不能被序列化。通过电线传递的唯一东西就是价值本身。如果你将这个对象传递给一个非.NET消费者(例如通过WCF),那么他们不一定有相同的规则构建到它们将数据反序列化到的对象中。

相关问题