ASP.Net MVC 2:使用viewmodel破坏我的模型绑定

时间:2011-01-28 01:26:47

标签: c# asp.net-mvc-2

我想这是一个关于框架如何愉快地完成你所需要的95%的故事,但随后对最后的5%不满地皱眉;告诉你,如果你想参加非标准的malarky这是你自己的事业,非常感谢你,如果你决定要回归做擅长的事情,它就会在这里。一般来说,最后的5%将不可避免地包含必备功能的某些版本。

我有一个强类型视图,用于更新数据对象。我使用了惯用的MVC2助手,例如Html.TextBoxFor(model = > model.Name)。我已经为嵌套对象使用了编辑器模板。 (我的后端是Mongo文档的集合,所以我需要表示复杂的类型)。

然后我需要一个下拉菜单。事实证明,下拉有点挑剔;没问题,我会创建一个viewmodel而不是直接传递item

class itemViewModel
{
    ...
    public Item item { get; set; }
    public IEnumerable<SelectListItem> dropdown { get; set; }
}

public ActionResult()
{
    return View("Update", new itemViewModel(item, dropdown))
}

...工作正常,下拉列表填充。但!我的观点需要更新:

Html.TextBoxFor(model => model.Name) ->
Html.TextBoxFor(model => model.item.Name)

很好,问题解决了。哎呀,现在我的模型绑定不起作用。我调试并查看Request.Form值:哦。 item.Name代替Name。说得通。我告诉我的更新视图,期望itemViewModel代替,并且绑定有效。

等等,不,不。因为我有嵌套使用编辑器的对象。它们是强类型的,并且它们不知道它们接收的模型实际上是视图模型的属性。所以他们仍在吐出Address.City而不是item.Address.City,并且绑定失败。

我可以想到几个解决方法:

  1. 编写专门的自定义模型绑定器
  2. 将整个该死的表单放入自己的类型编辑器中,因此它获取item模型而不知道它是属性
  3. 使用ViewData词典
  4. 杀死viewmodel并破解下拉列表
  5. 使用HtmlHelpers退出并手写整个表单
  6. 编写我自己的HtmlHelper扩展名,将lamba 作为参数。
  7. 将每个标签/字段分组放入单独的编辑器模板中。
  8. 所有这些感觉都像是矫枉过正或邋.. Viewmodels似乎是一个干净,有用的方法。使用它们是否意味着我必须在其他方面马虎,或者在框架的相当大的块上重现微小的变​​化?在过去的三个月里,我自学了C#(一位平面设计师试图弄清楚什么是静态打字,没有CS背景可能很有趣)。我孤立地工作;没有人可以从中学习最佳实践。我觉得如果我不学习其中的一些,我最终会得到一个难以维护的粪堆。所以,您的意见表示赞赏。

2 个答案:

答案 0 :(得分:8)

叹息。几个小时的谷歌搜索和黑暗中的一些镜头,似乎有一个令人难以置信的直截了当的方式,使用Bind属性:

[HttpPost]
public ActionResult([Bind(Prefix="item")] item)
{
    //item's complex types populate correctly
}

该属性似乎足够智能,可以进入复杂的类型。

我将此作为对自己无知的致敬,并希望其他一些倒霉的n00b能比我更快找到答案。

答案 1 :(得分:-10)

丹尼尔,首先,我应该说我赞扬你的努力,并将.NET,C#和ASP.NET MVC全部放在一起。好的,所以你很沮丧,我与此有关。它偶尔发生在我们所有人身上。

我应该让你知道我不是ASP.NET MVC(Problems with ASP.NET MVC Framework Design)的粉丝(实际上不是一点点),所以我不能给你一个解决方案你的问题。但是我希望你能看到你所处的情况:

你正处于一个迷宫中,你在某个地方做了一个错误的转弯,你正在深入迷宫,但你不会找到出路。所以你需要做的就是回到错误的转弯,看看是否还有另一条路线。因此,从你所处的位置开始,问问自己,“为什么”对于你所做的每一步/改变,并一次又一步地回答问为什么。那有意义吗?你最终会遇到另一种方法来解决相同的(原始)问题。