asp.net-mvc - 访问 View 中的域对象

标签 asp.net-mvc domain-driven-design

如果我不想公开我的域对象的内部状态,但我需要显示它们,我可以想到三种方法。 以下哪个是最“正确”的(如果有的话?)。

  1. “DTO/ViewModel 方法”。 这似乎是一种流行的方法 在 ASP.NET MVC 世界中(特别是 使用 AutoMapper)。
  2. 的 “装饰方法”。如果我有一个 “客户”实体,我装饰它 有一个“DisplayableCustomer”谁可以 访问的内部状态 客户(在大多数语言中 我处理过)。
  3. “接口(interface) 方法”。我在哪里做类似的事情 这个:

    class Customer {
        ....
        public void renderWith(CustomerRenderer renderer) {
             renderer.renderCustomer(address,name);
        } 
    }
    
    interface CustomerRenderer {
        public void renderCustomer(Address address, Name name);
    }
    

最佳答案

我投票支持并广泛使用您的第一选项。几个原因:

  • 允许复杂的 View 模型,例如组合我的域对象的多个列表。想象一个带有 Post 元素的 PostViewModel 和一个悬卡在它上面的 IList 容器。
  • 在我当前的项目中,我们已经将域验证抽象到它冒泡到我们的自定义 ViewModel 中的地方,并对表单进行一些巧妙的 Ajax 验证。
  • 虽然这个概念不会直接在模型上公开您的域对象,但我可以毫无问题地将 Post 卡在我的 PostViewModel 的属性之外。

最后一点是 ViewModels 概念真正存在的原因。将您的域对象一直暴露到您的 UI 甚至 View 并不违反 DDD - 这是 DDD 和 UI 概念的设计和预期。您只公开域中的对象以供使用,并通过服务和基础架构锁定/保留它们的状态。因此,您没有违反在 UI 中使用实际域对象的规定。

当您将 MVC 概念用于您的 UI 并尝试呈现页面/位置的特定 View 时。您可能(并且将会)拥有与域完全无关的其他显示元素,例如 Progress Bar这仅适用于用户界面。进度条只与 UI 和应用层有关。它与您的域无关。

因此,我接受的 DDD 解决方案是在应用程序/UI 层中使用一个混合对象,它可以容纳多个对象:领域对象和应用程序对象,以呈现一个特定的 View 。这是 ViewModel 的概念,其存在的核心原因。

ViewModel 概念可以被认为是 DDD 术语中的应用层非业务对象。


稍微偏离主题,谈谈一种特定的技术,ASP.NET MVC 有额外的功能来帮助使这个概念很好地协同工作。它没有直接内置到 ASP.NET MVC 中,而是作为 Microsoft 称为 Futures 项目的附加程序集提供。

Check out my blog post about a couple of features ,最有用的功能是 RenderAction 扩展方法:

http://eduncan911.com/blog/html-renderaction-for-asp-net-mvc-1-0.aspx

这是一个非常强大的概念,可以启动底层 Controller 并调用操作方法。这样做极大地简化了我们的 ViewModel,使其只关心它们正在渲染的 View 。我不再需要附加与 View 无关的内容,例如边栏控件或其他常用数据框、导航栏等。

出于纯粹的 DDD 原因,RenderAction 与 RenderPartial 不同:它允许您将业务逻辑移回到它所属的 Controller 中。并且 Controller 调用正确的 View 来呈现它的显示。这严格遵循 DDD 和 MVC 概念。

Microsoft 已声明 RenderAction 将在明年发布时成为 ASP.NET MVC 2.0 的一部分。

对不起,我的咆哮......

关于asp.net-mvc - 访问 View 中的域对象,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1723889/

相关文章:

css - 打开下拉列表后设置第一行样式

asp.net-mvc - Blazor WASM 页面路由

c# - C# 和 MVC 中的 System.Environment.Username 和 User.Identity.Name 有什么区别?

c# - NHibernate 聚合遍历 (C#)

domain-driven-design - 更新聚合根内的多态子实体

c# - 使用 ViewModel 的 Winforms 数据绑定(bind)

domain-driven-design - DDD 中是否存在应用程序事件术语?

angularjs - 使用 ASP.NET MVC 6 和 AngularJS 在 SPA 中进行路由

c# - 需要有关 MVC 中 AJAX 表单流程的建议

c# - Nhibernate/Domain 对象使用来自工厂的随机数据生成测试对象