【问题标题】:ASP MVC 4 managing object state in controllerASP MVC 4 在控制器中管理对象状态
【发布时间】:2012-12-01 11:25:23
【问题描述】:

我是 MVC 新手,在状态和对象持久性方面遇到概念性问题,希望有人能整理一下我的想法。

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

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

我有使用 Automapper 从域对象映射的视图模型对象。由于订单是从一个包含行等的网络服务方法返回的,所以我有一个 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() 方法中可用,以作为模型返回 PartialView( ...,型号)?

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

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

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

【问题讨论】:

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


    【解决方案1】:

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

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

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

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

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

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

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

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

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

    希望对你有帮助

    【讨论】:

    • 感谢您的回复。关于视图模型,对不起,我并不打算完全放弃它 - 只是将它从 OrderViewModel 容器(包括标题和行)中拆分为单独的视图模型 - 所以我可以将 OrderHeaderViewModel 传递给标题部分而不是传递整个订单模型。部分视图的原因是在单个页面中显示顺序,但允许通过将部分视图与表示相同数据的编辑视图交换部分视图来编辑标题或行,使用 Ajax 切换视图。所以加载整个订单然后使用部分绘制。
    猜你喜欢
    • 1970-01-01
    • 2017-10-21
    • 1970-01-01
    • 1970-01-01
    • 2015-11-11
    • 1970-01-01
    • 2016-02-28
    • 1970-01-01
    • 2022-10-13
    相关资源
    最近更新 更多