如何在绑定到ViewModel时更新Model?

时间:2011-05-05 05:04:37

标签: asp.net-mvc asp.net-mvc-3 viewmodel model-binding updatemodel

我有一个[HttpPost]动作方法签名,如下所示:

[HttpPost]
public ActionResult Edit(ExistingPostViewModel model)
{
   // Save the edited Post.
}

现在,在过去(当我没有使用ViewModel,例如R& D)时,我有一个编辑方法的实现,如下所示:

[HttpPost]
public ActionResult Edit(Post model)
{
    var existingPost = repo.Find(model.Id);
    TryUpdateModel(existingPost);
    repo.Save(existingPost);  
    return RedirectToAction("Success", existingPost.Id);
}

哪个效果很好。

但我很困惑如何使上述内容适应ViewModel方法。

如果我这样做:

TryUpdateModel(existingPost)

使用我的ViewModel方法,没有太多事情发生。没有错误,但没有任何内容正在更新,因为MVC不知道如何从PostExistingPostViewModel - &gt; Post之前)更新Post。< / p>

现在,我正在使用AutoMapper。所以我想我可以从ViewModel映射到Post,然后保存帖子。

然后我基本上压倒一切。我不想这样做,并且打败了ViewModel。

有人可以让我迷惑吗?

这似乎是一种非常常见的情况,我对人们如何解决这个问题感到非常难过。我只能看到3种可能的解决方案:

  1. 不要在HTTP POST中使用ViewModel。正如我所说,我过去为R&amp; D做过这个并且它有效,但现在我看到我的View已经进化(验证,简单),并且我不能仅仅为了这个问题而妥协。

  2. 请勿使用TryUpdateModel。可能,但那么我将如何合并这些变化呢?

  3. 使用从左到右。啊。但目前这似乎是我倾向的方式。

  4. 有人请给我解决方案#4! :)

    BTW,我正在使用ASP.NET MVC 3,Razor和Entity Framework。

3 个答案:

答案 0 :(得分:2)

我实际上在我正在进行的项目中遇到了同样的问题。尽管我不是它的粉丝,但我最终做了从左到右的方法并手动将我的viewmodel数据映射回我的实体。

这种方法唯一的好处是它确实可以让你获得更多的控制权。自从我开始使用更多复合视图模型以来,你在视图模型中实际拥有来自多个实体的字段时,开始以这种方式做事更有意义。

我也在使用AutoMapper,你是绝对正确的,当你尝试进行简单的更新操作时,它确实很尴尬。希望我能为你做一些超级聪明的解决方法,但是“老式的方式”似乎让我的工作做得最好。

答案 1 :(得分:0)

对于在实现更新之前不必运行任何控件的简单事情,你正在做的事情是可以的(db.get(),然后更新)。

当事情变得复杂时,您必须加载实体,然后从视图模型中选择并应用用户的更改属性。在这些情况下,您最终编写Update方法,将新数据作为输入,然后加载现有实体,然后比较状态,并根据视图模型数据采取所需操作。实际上在这种情况下,可能你没有Update方法但会有行为,如CancelPost,AddComment,EditPost(也记录编辑原因),AddTagsToPost等。

答案 2 :(得分:0)

不确定这是否会有所帮助,但它对我有用。我将我的基础域表作为访问者对象。我的viewmodel包含访问者对象以及几个用于下拉列表的IEnumerables。

    [HttpPost]
    [ValidateAntiForgeryToken]
    public ActionResult Edit(int id)

    {
        Visitor Visitor = new Visitor();
        Visitor = db.Visitors.FirstOrDefault(v => v.VisitorID == id);

        UpdateModel(Visitor, "Visitor");

        db.SaveChanges();
        return RedirectToAction("Index");

    }

UpdateModel使用我的viewmodel,因为&#34;访问者&#34;字符串告诉它要比较什么值。