我正在开发我的第一个.NET MVC应用程序,并使用NerdDinner教程作为引用点。目前令我着迷的一点是UpdateModel()方法。 (我不喜欢使用我不太了解的东西。)

取自NerdDinner tutorial-

//
// POST: /Dinners/Edit/2

[AcceptVerbs(HttpVerbs.Post)]
public ActionResult Edit(int id, FormCollection formValues) {

    Dinner dinner = dinnerRepository.GetDinner(id);

    UpdateModel(dinner);

    dinnerRepository.Save();

    return RedirectToAction("Details", new { id = dinner.DinnerID });
}

我的主要问题是UpdateModel()如何访问在Edit方法中传递的formValues?为什么未将集合作为参数明确传递给方法?

最佳答案

UpdateModel()是Controller的辅助方法,试图将一堆不同的输入数据源(来自View的HTTP POST数据,QueryString值,Session变量/ Cookies等)绑定(bind)到您指定为参数的显式模型对象。本质上,它仅用于模型绑定(bind)。

如果将Action的输入参数表示为强类型模型(例如View模型),则说明调用UpdateModel()时已执行了所有在后台执行的步骤。如果您从DataContext中检索对象并编辑其属性,则只需要将SaveChanges()推送回数据库(在本例中为Save())。

例:

//
// POST: /Dinners/Edit/2

[AcceptVerbs(HttpVerbs.Post)]
public ActionResult Edit(DinnerViewModel incoming) {

    var dinner = dinnerRepository.GetDinner(incoming.DinnerID);
    dinner.Description = incoming.Description;
    dinnerRepository.Save();

    return RedirectToAction("Details", new { id = incoming.DinnerID });
}

但是,有一个用例将UpdateModel()与强类型模型一起使用:当您传递强类型模型并希望其值直接从数据库中替换实体的值时(如果它们是所有的名称和类型都相同)。在这种情况下,您将检索对象,在其上使用UpdateModel(),并且其模型绑定(bind)操作会将所有具有相似名称和类型的属性从强类型对象引入到检索到的对象中。换句话说,它将为您执行反射

因此,就像您的示例一样,如果您要更新所有属性而不指定要更新的属性,并且您的强类型模型和数据库模型具有名称相似的属性,则您仍想使用UpdateModel()来利用反射。

例:
//
// POST: /Dinners/Edit/2

[AcceptVerbs(HttpVerbs.Post)]
public ActionResult Edit(DinnerViewModel incoming) {

    var dinner = dinnerRepository.GetDinner(incoming.DinnerID);
    UpdateModel(dinner);
    dinnerRepository.Save();

    return RedirectToAction("Details", new { id = incoming.DinnerID });
}

这里(相对于使用FormCollection对象)的唯一优点是,您可以访问强类型对象的所有其他属性(如入库.DinnerID所示)。

结论:如果要将强类型的对象转换为派生对象,则使用UpdateModel()可能最简单。但是,如果仅更新派生对象的一些属性,则基本上没有必要。另外,请注意,使用 Entity Framework (而不是类似Linq to SQL)会引起所有这些麻烦,因为它可以将强类型对象和派生对象与自己的方法相关联。

10-06 02:34