10

我最近开始使用 MVC,但我有点失望。该框架没有帮助我,而是妨碍了我。

我正在尝试编写这样的控制器操作(伪代码)

ActionResult Save(long id, string whichForm)
{
    if (whichForm == "A")
    {
        var vm = CreateModel(Request.Form);
        if (!TryValidate(vm))
            return View(vm);
        else
            return RedirectToRoute("Success");
    }
    else ....
}

基本上我想控制我的视图模型何时构建以及何时验证。这可能吗?如何实现 CreateModel 方法?考虑一下我可能想在这个控制器动作中创建几个不同的视图模型。

*咆哮:我真的不明白为什么视图模型绑定和验证在 DefaultModelBinder 中混合在一起。看起来像代码气味。特别是当很难覆盖这种行为时。

4

2 回答 2

22

您可以自行决定创建并绑定到现有模型:

public ActionResult Save(long id, string whichForm)
{
    if (whichForm == "A")
    {
        var vm = new FormAViewModel();

        if (!TryUpdateModel(vm))
            return View(vm);
        else
            return RedirectToRoute("Success");
    }
    // else ....
}

IModelBinder如果您想完全控制绑定过程,您还可以选择创建自己的。您可以替换默认模型绑定器,也可以IModelBinder为特定类型注册特定实现。但是,我建议除非您的绑定逻辑很简单,否则您可能希望从中派生自定义模型绑定器DefaultModelBinder并覆盖您不喜欢的部分。

我讨厌留下一个 troll-ish 的评论,但是 10 次中有 9 次有人觉得框架妨碍他们的原因是因为他们还不了解如何正确使用它。这是一篇关于模型绑定的一般提示的文章

至于您的咆哮:验证和绑定是分开的,但是,默认模型绑定器会触发验证。这样做的原因是允许您的应用程序优雅地处理绑定到缺失/无效/不完整值的问题,而不是允许绑定静默失败或抛出异常。

于 2012-05-31T00:21:57.430 回答
0

您可以利用 IModelBinder 接口并编写一个完整的自定义模型绑定器。这里解释得很好。本质上,此接口公开了一个方法“BindModel”,您可以在其中控制模型绑定行为以及验证。

http://www.dotnetcurry.com/ShowArticle.aspx?ID=584

但是,这可能会使问题复杂化,并且您可能会遇到意大利面条式代码。如果适合您,我会建议一个简单的“每个模型的操作”。所以你可以写这样的东西:

ActionResult SaveA(long id, AViewModel)
{
      //.... Action to be conducted in case it is form A.
}
ActionResult SaveB(...., BViewModel)
{
       //... Action to be conducted in case it is form B.
}


// Your view models can be structured for code reuse as well.
class AViewModel {  ...  }
class BViewModel : AViewModel {  ...  }
于 2012-05-31T00:24:36.897 回答