【问题标题】:ASP.net MVC - How to persist model over various viewsASP.net MVC - 如何在各种视图中保留模型
【发布时间】:2010-12-13 11:19:25
【问题描述】:

情况:在一些用 asp.net 编写的项目管理软件中,我有一个创建项目页面(工作正常)。我需要添加将任务从模板列表添加到此项目预创建的能力,但可用任务列表取决于创建表单中的某些值。

我的抽象解决方案是这样的:

  • 我有一个“创建”视图和一个“添加任务”视图 - 两者都强类型化到控制器中定义的复合 viewModel
  • 我的 Create 方法检查使用哪个按钮来调用它 - 如果 按钮是“添加任务”,然后它呈现 AddTasks 视图,从创建视图传递模型,再次在同一个控制器中。
  • AddTasks 视图使用两个按钮之一发布到 Create 视图,一个加载视图,另一个导致实际的数据库保存。

我的问题是这样的:

  • 不同的视图使用相同模型的不同属性,但是在它们之间传递这个模型时,数据被重置(在任何情况下都重新加载或保存)。
  • 我猜这是由于数据的自动绑定而发生的 - 尽管我认为表单上不存在的字段不会覆盖传递下来的现有模型数据。
  • 目前控制器中几乎没有任何代码来操作模型 - 在这些情况下,它只在视图之间传递。

这是控制器代码:

    // POST: /Project/Create/<viewModel>
    [Authorize, AcceptVerbs(HttpVerbs.Post)]
    public ActionResult Create([Bind(Exclude = "Id,id")] ProjectViewModel model)
    {
        if (model.SubmitValue == "Create")
        {
            try
            {
                model.Project.Id = Guid.NewGuid();
                model.Save(this.User.Identity.Name);
                return this.RedirectToAction("Details", new {id = model.Project.Id});
            }
            catch (Exception e)
            {
                this.ModelState.AddModelError(e.ToString(), e.ToString());
            }
            return View(model);
        }

        if(model.SubmitValue == "AddTasks")
        {
            return this.View("AddTasks",model);
        }

        return this.View(model);

    }


    //POST: /Project/AddTasks/ + model
    [Authorize, AcceptVerbs(HttpVerbs.Post)]
    public ActionResult AddTasks([Bind(Include = SelectedCarrierTasks")]ProjectViewModel model)
    {
        return View(model);
    }

问题是:如何在这些视图中保持模型的状态,直到最终保存它?

我宁愿避免使用任何 hackish (TempData) 或 JS 依赖的解决方案,但如果它们真的是最好的解决方案,我不会拒绝这些。

谢谢, 亚当·托利

【问题讨论】:

    标签: asp.net-mvc model-view-controller mvccontrib


    【解决方案1】:

    一个简单的解决方案是将 ViewModel 对象持久化到一个 Session 变量中并从这个源绑定视图。这当然不是最优雅的解决方案。另一种可能不太优雅的选择是将此模型数据保存在数据库中,并带有一些临时/未保存的标志。

    【讨论】:

      【解决方案2】:

      问题在于,当您显示添加任务视图时,您没有为“项目”对象提供字段,因此 ModelState 会丢失与项目相关的数据,您需要提供此字段以确保您不会丢失这些数据。

      您不需要显示这些字段,它们可以是隐藏类型,它们会保留值。只要确保如果您要绑定到视图模型,您需要像 Model.Project.Property 一样正确命名这些字段。

      【讨论】:

      • 所以我可以通过将它存储在客户端隐藏字段中来持久化它,有没有办法不依赖客户端存储?用这样一个相当大的模型来加载页面和浏览器感觉有点奇怪,只是为了在同一个控制器中保存跨方法/视图。感谢您的意见
      【解决方案3】:

      也许我正在尝试解决错误的问题(ala Bruce Eckel)。我将尝试转移到不需要这种模糊边界的结构。我不想采用 REST 范式只是将它硬塞进一个有状态的应用程序中。

      可能这些控件属于同一页面,我可以使用一些 JQuery 优点将其放入选项卡窗格中,以便于查看。

      感谢那些回答的人,我发现每一个都很有用,一旦我有更多的代表,我会尽量记住给他们投票。

      【讨论】:

        【解决方案4】:

        目前我无法评论其他人的问题,但唯一真正的选择是会话,如果您想在 Web 请求期间保持对象状态,或者将其序列化并将其放置在隐藏字段中。

        或者最后的选择是更改页面的工作方式,以便在每次请求后保存对象...

        如果您使用 nHibernate,那么您可能需要查看对话模式,但这实际上只是将 nHibernate 会话保存到 asp.net 会话中......

        【讨论】:

        • 我会将其标记为答案,因为它是最完整的选项集,并且包括 NHibernate 方法(尽管我目前坚持使用 EF1)。
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2011-08-15
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2018-10-13
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多