我最近开始使用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方法?考虑我可能想在此控制器操作中创建几个不同的视图模型。
* Rant:我真的不明白为什么在DefaultModelBinder中将视图模型绑定和验证混合在一起。好像代码味道。特别是当它很难覆盖这种行为时。
答案 0 :(得分:21)
您可以自行决定创建并绑定到现有模型:
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 ....
}
You also have the option of creating your own IModelBinder
,如果您想要完全控制绑定过程。您可以替换默认的模型绑定器,也可以为特定类型注册特定的IModelBinder
实现。但是,我建议,除非您的绑定逻辑很简单,否则您可能希望从DefaultModelBinder
派生自定义模型绑定器,并覆盖您不喜欢的部分。
关于你的咆哮:验证和绑定是分开的,但是,默认的模型绑定器会触发验证。这样做的原因是允许您的应用程序优雅地处理绑定到缺失/无效/不完整值的问题,而不是允许绑定以静默方式失败或抛出异常。
答案 1 :(得分: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 { ... }