ASP.net MVC - 如何在各种视图上保持模型

时间:2009-11-05 15:34:41

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

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

我的抽象解决方案是:

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

我的问题是:

  • 不同的视图使用相同模型的不同属性,但是在它们之间传递此模型时,数据将被重置(无论如何重新加载或保存)。
  • 我猜这是通过数据的自动绑定发生的 - 虽然我认为表单上没有的字段不会覆盖传递下来的现有模型数据。
  • 控制器中几乎没有任何代码在操作模型 - 在这些情况下它只从视图传递到视图。

这是控制器代码:

    // 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依赖的解决方案,但如果它们确实是最佳解决方案,我不会对这些解决方案感到满意。

谢谢, 亚当托利

4 个答案:

答案 0 :(得分:3)

一个简单的解决方案是将ViewModel对象保存在Session变量中,并从该源绑定View.I ts当然不是最优雅的解决方案。另一种选择,可能不那么优雅,是在数据库中保留这个模型数据,带有一些临时/未保存的标志。

答案 1 :(得分:2)

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

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

答案 2 :(得分:2)

也许我正在努力解决错误的问题(ala Bruce Eckel)。我将尝试移动到需要这种模糊边界的结构。我不想采用REST范例只是为了将它变成一个有状态的应用程序。

这些控件可能属于同一页面,我可以使用一些JQuery的优点放入一个标签窗格,以方便眼睛。

感谢那些回答的人,我发现每个人都很有用,并会尽快记得在我有更多代表后立即投票。

答案 3 :(得分:1)

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

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

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