C# 如何验证DTO';用于客户机-服务器应用程序的

C# 如何验证DTO';用于客户机-服务器应用程序的,c#,web-services,validation,dto,C#,Web Services,Validation,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

我最近读了很多关于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对象时,如果缺少Person名称,则会引发验证异常


由于DTO本身是特定于服务操作的,所以在这里进行此验证是正常的还是违反了有关业务逻辑应该驻留在何处的某种规则?

这取决于。但通常情况下,将验证登录放到DTO中并不是一个好地方。您将遇到重用性问题。例如,如果您需要更新person,则必须创建UpdatePersonDTO并将所有相同的逻辑放在那里。

作为另一种选择,您可以将验证逻辑放入Person本身,这样您就不能创建无效的Person,并且它将是可重用的。或者,您可以将实体验证逻辑放入某种服务层。

我认为每个DTO都应该根据正在执行的服务操作进行调整,这意味着如果您有庞大的域对象,DTO可以表示与特定服务操作相关的子集。也就是说,它可能只对域对象的一些属性感兴趣。

DTO不应进行验证;它们严格用于传输数据。除了验证之外,他们真的不应该有任何行为


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

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


除了这里的职责分离之外,您的逻辑实际上无法序列化。唯一可以通过网络传输的东西就是价值本身。如果您将此对象传递给非.NET使用者(例如通过WCF),则他们不一定会在对象中内置与将数据反序列化到的规则相同的规则。

同意。您最不需要的是DTO在WCF(或其他通信提供程序)中齐膝深的数据序列化/反序列化层抛出异常。另一个好处是只保留DTOs数据,很可能在使用同一代码文件的两个地方(例如Silverlight和ASP.NET web服务)都可以重用该代码文件,这样可以确保如果添加/删除/更改属性,每个源都会相应地更新。一旦您将验证(甚至日志记录)放在那里,它很有可能不兼容于不同的环境/平台。好的,我可以看出这是一个多么糟糕的主意。是否有一个干净的模式用于验证不涉及if(String.IsNullOrEmpty(personDto))的DTO在控制器的中间抛出新的异常…<代码>?@戴维,您是想验证DTO是否从您的服务返回到一个有效的状态?@ Jay Sorry,我刚才注意到我的注释中有一个错误。不,我想验证发送给我的服务的DTO。如果我发送了一个JSON对象,缺少一个表示类型布尔的属性,It可以解析为默认值false或null(able)bool。然后我需要将该属性映射到我的域对象以进行保存。在什么情况下我才能发现该属性丢失了?@David我一直在努力解决这个问题——我们最终做了很多映射,这可能会变得单调乏味。我倾向于说,您可以创建验证程序类来验证为您构建的DTO,或者您可以创建接受您的输入并返回DTO(正常)或错误(无效输入)的DTOFATORY类。理想情况下,您应该允许域验证完成它的工作,并且任何问题都会返回到前端,但我可以看出,您不希望执行额外的映射或往返坏数据。如果服务在本地托管到web服务器,则只需使用域逻辑。是的,这也是我认为的意思。