Asp.net 哪个项目层应屏蔽DTO';他住在哪里?

Asp.net 哪个项目层应屏蔽DTO';他住在哪里?,asp.net,n-tier-architecture,dto,project-structure,Asp.net,N Tier Architecture,Dto,Project Structure,我有一个项目,我们使用屏幕DTO来封装服务层和表示层之间的数据。在我们的例子中,表示层是ASP.Net 唯一知道DTO的类是服务层类和调用这些服务并显示DTO的页面/控件 DTO几乎总是特定于页面/控件,因此我觉得它们属于表示层,但这意味着服务层必须引用表示层才能使用DTO 我几乎认为服务层应该返回更丰富的对象(但不是域实体?),然后表示层可以获取这些对象,并将它们映射到每个页面/控件关注点的特定DTO 下面是一个接口声明和DTO,您可以看到我所说的内容: public interface IB

我有一个项目,我们使用屏幕DTO来封装服务层表示层之间的数据。在我们的例子中,表示层是ASP.Net

唯一知道DTO的类是服务层类和调用这些服务并显示DTO的页面/控件

DTO几乎总是特定于页面/控件,因此我觉得它们属于表示层,但这意味着服务层必须引用表示层才能使用DTO

我几乎认为服务层应该返回更丰富的对象(但不是域实体?),然后表示层可以获取这些对象,并将它们映射到每个页面/控件关注点的特定DTO

下面是一个接口声明和DTO,您可以看到我所说的内容:

public interface IBlogTasks
{
    BlogPostDisplayDTO GetBlogEntryByTitleAndDate(int year, int month, string urlFriendlyTitle);
}

public class BlogPostDisplayDTO 
{
    public string Title { get; set; }
    public DateTime PostDate { get; set; }
    public string HtmlContent { get; set; }
    public string ImageUrl { get; set; }        
    public string Author { get; set; }
    public int CommentCount { get; set; }
    public string Permalink { get; set; }
}   
编辑

下面是另一个代码示例,用于描述不涉及域模型的用例。也许这会澄清一些事情。我想我已经把DTO的意思说得太多了。我不是说DTO,它的功能是通过导线传输对象。我正在创建DTO,以将通信与服务层之间的契约形式化

public interface IAuthenticationTasks
{
    bool AuthenticateUser(AuthenticationFormDTO authDTO);
}

public class AuthenticationFormDTO
{
    public string UserName { get; set; }
    public string Password { get; set; }
    public bool persistLogin { get; set; }
}
假设我的身份验证突然需要一个IP地址参数。现在,我可以将该属性添加到DTO,而无需更改合同接口


我不想将实体传递到表示层。我不希望我的代码隐藏能够转到BlogPost.AddComment(new Comment())您使用的是实际的服务(web还是WCF)?如果是这样,则在服务层中定义DTO,并且在添加服务(或使用旧ASMX的web)引用时创建的代理将包含所有DTO类型。这是实现这一点的最简单方法,并且在ASP.NET项目和服务项目之间只保持松散耦合——两个方向都不需要直接的项目引用。当您更新DTO时,您所需要做的就是更新您的服务引用,它将通过生成的代理类自动向您的web项目公开更新

在任何情况下,如果您采用DDD方法,最好让您的基础设施项目(例如特定于web平台的UI)引用您的域对象,而不是相反。但是,如果您遵循我上面的建议,您的web项目将不会直接依赖于该项目,这是一件好事,当然比让您的富域对象依赖于您的web项目要好(如果这是一个考虑因素的话-我意识到您并没有说您正在这样做)


如果DTO是特定于视图的,那么我会将它们包括在UI项目中。控制器的工作应该是确保视图只从模型中得到它所需要的东西——在您的例子中,值对象只包含视图所需的字段。

甚至认为“DTO”的规范用例更“可通过线路传递的可序列化对象”,在这种情况下,您实际上更多地指的是“演示传输对象”或“视图模型”


通常,对于我们的项目,这些问题的答案是“翻译”代码的位置,它将DDD域模型映射到PTO类。如果这是在婚前协议层(也许不是很好的答案),那么压力层就是我声明PTO的地方。但通常情况下,是“服务”为您进行翻译,这意味着“服务”和“表示”层都需要引用PTO,并且(通常)导致它们在单独的,中性项目/程序集/命名空间/表示层和服务层都可以引用的任何内容。

我不是说服务是一种实现。我的服务层只是UI和域之间的一个精简服务。你是对的,我遵循的是DDD方法,但我不会让我的域实体位于服务层之外。这样一来,你的DTO就成了实体对象,没有任何传输。它们驻留在服务层中,表示基于服务层提供的实体对象创建自己的对象,这些对象驻留在表示层。我说的对吗?我已经编辑了我的问题来描述我对DTO的期望使用。我会回到事实上来,这些DTO是特定于您的UI层的,因此应该存在于那里。如果你不能创建一个域对象依赖于你的基础设施和UI层的设计,那么就把DTO放到他们自己的第三个项目中,让UI域dpend在上面,我更新了我的答案-见最后一段。您希望DTO位于UI项目中。您希望控制器成为域对象和视图之间的网关守护者。这就是它的工作。谢谢!我想我的困惑部分是在错误的上下文中使用DTO这个术语。PTO和ViewModel为我提供了一些更好的术语,以便进一步阅读。