0

我是 MVC 的新手,并且在状态和对象持久性方面存在概念问题,希望有人可以整理我的想法。

我有一个远程网络服务,它提供了管理订单的方法。如您所料,订单由标题和行组成。线路可以有额外的要求。

我创建了我的域对象(使用 webservice 模式中的 xsd2code),webservice 调用和对象序列化都工作正常。我已经构建了 DAL/BLL 层,并且一切正常 - 使用 WinForms 测试平台应用程序前端进行了测试。

我有使用 Automapper 从域对象映射的视图模型对象。由于订单是从带有行等的单个 web 服务方法返回的,所以我有一个 OrderViewModel,如下所示

    public class OrderViewModel
{
    public OrderHeaderViewModel OrderHeader { set; get; }
    public List<OrderLineViewModel> OrderLines { set; get; }
    public List<OrderLineAdditionalViewModel> OrderLineAdditional { set; get; }
    public List<OrderJustificationViewModel> OrderJustifications { set; get; }

}

首先,我想知道我是否应该放弃 OrderViewModel,就好像我将它作为模型传递给我传递的数据比我需要的多得多的视图一样。视图只需要 OrderHeader 或 OrderLines 等 - 而不是整个订单。

现在我的概念问题在于控制器、视图和对象持久性。

My Order 控制器有一个 Detail Action,它执行从 web 服务加载订单并将 Domain 对象映射到 OrderViewModel 对象。

    public ActionResult Details(string orderNumber)
    {

        OrderViewModel viewModel = new OrderViewModel();
        var order = WebServiceAccess.LoadOrderByOrderNumber(orderNumber,"OBOS_WS");

        viewModel = AutoMapper.Mapper.Map<BusinessEntities.Order, ViewModels.OrderViewModel>(order);

        return View(viewModel);
    }

但是 Order/Details.cshtml 只有页面布局和对标题和行的两个部分页面的调用(我使用 Ajax 将 Headerview 交换为 HeaderEdit,LinesView 相同)

@{ Html.RenderPartial("DetailsHeaderViewPartial", Model);}
@{ Html.RenderPartial("DetailsLinesViewPartial", Model);}

目前我将模型传递到主细节容器页面,然后传递到 RenderPartials,但是我不认为模型应该传递到主细节页面,因为它不需要它 - 模型是仅在 DetailsHeaderViewPartial、DetailsLinesViewPartial 中需要,所以我最好在此处使用 @RenderAction 并将模型传递到 Header/Lines 视图中。

但是,订单是从 ActionResult Details() 中的 web 服务中检索到的,我怎样才能使检索到的 OrderViewModel 对象在控制器的 ActionResult HeaderDetails() / LineDetails() 方法中可用,以作为模型在 return PartialView(... ,模型) ?

我是否应该使用用户会话来存储 Order ViewModel,以便它可以在控制器中的操作中使用。

从这个阶段开始,用户将能够维护订单(添加/删除行 - 编辑标题等)。由于保存订单的 web 服务调用可能需要几秒钟才能完成,我宁愿只在用户完成订单后调用 save 方法。因此,我想在处理过程中将正在进行的订单保留在本地某个地方。用户会话?

非常感谢您的任何建议。一旦我了解了 ViewModel 的状态管理,我就可以停止阅读一百万篇博客文章并实际编写这个东西!

4

1 回答 1

1

您实际上在这里有几个问题,所以我会尽力解决它们。

1)免除视图模型:我会说不。视图模型表示填充视图所需的数据。您似乎将视图模型用作与域模型对象相同的容器。因此,您在问是否应该放弃它并将域模型传递给视图,而您最初担心的是您传递的数据比您真正需要的数据更多?

与其放弃视图模型,不如重新审视您在视图模型上的属性。仅使用您需要的属性并创建映射逻辑(使用自动映射器或您自己)以获取复杂的域对象并填充视图模型上的属性。

总结:将视图模型构建为视图需要的东西,并编写映射逻辑来填充该视图模型。

2)在我分解您的具体情况之前,这只是最佳实践的陈述。

您将您的架构描述为具有 BLL 和 DAL。如果是这种情况,那么您不应该从控制器中保留任何对象。即使存在,控制器也不应该对数据库有任何了解,并且控制器中使用的对象应该不知道如何保存自己。在您的控制器和 Web 服务之间传递的对象严格来说应该是数据传输对象 (DTO)。如果您不熟悉 DTO 的构成,那么我强烈建议您进行一些研究并尝试将它们构建到您的解决方案中。它将帮助您从概念上了解视图模型对象、域对象和数据传输对象之间的区别。

3)我不会尝试在会话中存储订单对象。我将重新分析您如何分解视图中的部分视图,以便您可以以您需要的方式调用以 ordersviewmodel 为参数的操作。听起来您不必要地将视图分解为部分视图。

4) 你不应该关心视图模型对象的状态管理。您的视图(可以由许多局部视图组成)根据视图模型提供的属性进行填充。用户可以使用您开发的 UI 进行更改。由于您表示希望仅在他们完成所有更改以优化对 Web 服务的调用后才保存,因此您只需在单击提交时重新填充视图模型的字段。现在您有一个代表用户更改的 orderviewmodel 的“状态”。您可以在转换回 DTO(如果您按照我上面所说的)或将其映射到域对象后将此对象发送到 Web 服务。

1 最后注。您正在使用 automapper 将您的域映射到视图模型。我假设您的视图模型太复杂并且包含您不需要的东西,因为您构建了视图模型来模拟域对象,以便自动映射器可以通过命名约定进行映射。Automapper 有一个 api 用于执行不属于标准同名属性的复杂(自定义)映射。不要让自动映射器限制您以某种方式构建视图模型。

希望这可以帮助

于 2012-12-13T15:15:34.113 回答