ASP MVC 4管理控制器中的对象状态

时间:2012-12-13 14:37:01

标签: asp.net-mvc asp.net-mvc-4 session-state

我是MVC的新手,我对状态和对象持久性存在概念性问题,希望有人能够按顺序思考。

我有一个远程网络服务,提供管理订单的方法。订单包含标题和行,如您所料。行可以有其他要求。

我创建了我的域对象(使用来自webservice架构的xsd2code),webservice调用和对象序列化都正常工作。我已经构建了DAL / BLL层并且它们全部正常工作 - 使用WinForms测试平台应用程序前端进行测试。

我使用Automapper查看从域对象映射的模型对象。由于订单是从单个webservice方法返回完成的行等,我有一个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等 - 而不是整个订单。

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

我的订单控制器有一个详细操作,它从webservice执行订单的加载,并将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交换HeaderEdit的Headerview,对于LinesView也是如此)

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

目前我将模型传递到主要的详细信息容器页面,然后传递到RenderPartials,但是我不认为该模型应该传递到主详细信息页面,因为它没有&# 39; t需要它 - 只在DetailsHeaderViewPartial,DetailsLinesViewPartial中需要模型,所以我最好在这里使用@RenderAction,而是将模型传递到Header / Lines视图中。

但是,在ActionResult Details()中从Web服务检索Order如何在控制器的ActionResult HeaderDetails()/ LineDetails()方法中使检索到的OrderViewModel对象可用作模型返回PartialView( ......,模特)?

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

从这个阶段开始,用户将能够维护订单(添加/删除行 - 编辑标题等)。由于用于保存订单的web服务调用可能需要几秒钟才能完成,而是在用户完成订单时仅调用save方法。因此,我希望在正在进行工作的同时在当地保留正在进行的订单。用户会话?

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

1 个答案:

答案 0 :(得分:1)

你实际上有几个问题,所以我会尽力解决这些问题。

1)分配视图模型:我会说不。视图模型表示填充视图所需的数据。您似乎将视图模型用作域模型对象的相同容器。所以你问你是否应该放弃它并且只是将域模型传递给视图,而你原来关心的是你传递了更多数据,那么你真的需要它吗?

而不是放弃视图模型,我会在您的视图模型上重新访问您的属性。仅使用您需要的属性并创建映射逻辑(使用automapper或您自己)以获取复杂域对象并在视图模型上填充属性。

求和:将视图模型构建为视图所需的内容,并编写映射逻辑以填充该视图模型。

2)在我细分您的具体方案之前,这只是最佳做法的陈述。

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

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

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

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

希望这有帮助