2012-09-04 373 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),那麼他們不一定有相同的規則構建到它們將數據反序列化到的對象中。

相關問題