目前,我的视角模型非常糟糕。
类看起来像这样=>
public class AccountActionsForm
{
public Reader Reader { get; set; }
//something...
}
问题是Reader类型来自域模型(违反SRP)。
基本上,我正在寻找设计技巧(即将视图模型拆分为输入/输出是一个好主意吗?)如何使我的视图模型无摩擦且开发人员友好(即 - 映射应该使用控制器自动工作基类)?
我知道AutoMapper框架,我很可能会使用它。
那么,再一次 - 尝试创建正确的视图模型时常见的问题是什么?如何构建它?当需要多域对象输入时如何进行映射?
当视图需要来自多个聚合根的数据时,我感到很困惑。我正在创建具有Library,Reader,BibliographicRecord等实体的应用程序。
在我的情况下 - 在域级别,将所有这3种类型分组到LibraryReaderThatHasOrderedSomeBooks
或诸如此类的内容是没有意义的,但是应该显示特定库中特定读者的有序书籍列表的视图需要它们。< / p>
所以 - 使用OrderedBooksList
视图模型创建视图OrderedBooksListModel
似乎很好,其中包含LibraryOutput
,ReaderOutput
和BibliographicRecordOutput
视图模型。甚至更好 - OrderedBooksListModel
视图模型,它利用flattening technique并拥有ReaderFirstName
,LibraryName
等道具。
但这导致了映射问题,因为有多个输入
它不再是1:1的关系,我只在一个聚合根中开始。
这是否意味着我的域模型是错误的?
那么纯粹存在于UI层的视图模型字段(即表示选中标签的枚举)呢?
this在这种情况下每个人都做了什么?
FooBarViewData fbvd = new FooBarViewData();
fbvd.Foo = new Foo(){ A = "aaa"};
fbvd.Bar = new Bar(){ B = "bbb"};
return View(fbvd);
我不愿意这样做=&gt;
var fbvd = new FooBarViewData();
fbvd.FooOutput = _mapper.Map<Foo,FooOutput>(new Foo(){ A = "aaa"});
fbvd.BarOutput = _mapper.Map<Bar,BarOutput>(new Bar(){ B = "bbb"});
return View(fbvd);
似乎很多写作。 :)
确定。我经常考虑这个问题,是的 - 添加另一个抽象层似乎是一个解决方案=&gt;
所以 - 在我看来这已经有效了,现在是时候进行一些玩弄了。
吉米答案 0 :(得分:4)
在我们长期以来一直在努力寻找替代方案之后,这是我们遇到的一个问题:渲染数据与接收数据不同。
我们使用ViewModels来呈现数据,但很快就发现,当通过表单发布和类似方式接收数据时,我们无法真正使ViewModel符合ModelBinding的概念。主要原因是浏览器的往返通常会导致数据丢失。
例如,即使我们使用ViewModel,它们也基于来自真实域对象的数据,但它们可能不会公开来自域对象的所有数据。这意味着我们可能无法立即从浏览器发布的数据中重建底层域对象。
相反,我们需要使用映射器和存储库从发布的数据中检索完整的域对象。
在我们意识到这一点之前,我们在尝试实现可以从发布的数据重建完整的域对象或ViewModel的自定义ModelBinder时遇到了很多困难,但现在我们有单独的 PostModels 来模拟我们如何接收数据
我们使用抽象映射器和服务将PostModel映射到域对象 - 然后在必要时返回ViewModel。
答案 1 :(得分:4)
很难定义所有这些,但这里有。我们希望将我们称之为View的内容从Controller构建的内容中分离出来。视图看到一个扁平的,脑死亡的类似DTO的物体。我们称之为视图模型。
在Controller方面,我们构建了构建View Model所需内容的丰富图表。这可能只是一个聚合根,也可能是几个聚合根的组合。所有这些结合在一起我们称之为演示模型。有时,表示模型只是我们的持久性(域)模型,但有时它完全是一个新对象。然而,我们在实践中发现,如果我们需要构建一个复合的表示模型,它往往会成为相关行为的磁铁。
在您的示例中,我将创建一个ViewFooBarModel和一个ViewFooBarViewModel(或ViewFooBarModelDto)。然后,我可以在我的控制器中讨论ViewFooBarModel,然后依靠映射来使用AutoMapper从这个中间模型中展平我需要的东西。
答案 2 :(得分:3)
虽然将不相关的实体(或者更确切地说是他们的存储库)分组到域对象或服务中可能没有意义,但在Presentation层中对它们进行分组可能会很有意义。
正如我们以特别适合特定应用程序的方式构建表示域数据的自定义ViewModel一样,我们也使用自定义表示层服务,根据需要组合事物。这些服务更具特色,因为它们仅用于支持给定视图。
通常,我们会将此服务隐藏在接口后面,以便具体实现可以自由地使用构成所需结果所需的无关注入域对象。