绑定到MVC中的SelectList
我再一次遇到了“这不应该是这个?*!#困难”的情况。绑定到MVC中的SelectList
问题:我想在MVC中使用表单来创建对象。该对象的其中一个元素是一组有限的选择 - 完美的候选下拉列表。
但是,如果我在我的模型中使用SelectList,并在View中使用下拉列表,然后尝试将模型发回到我的Create方法,则会出现错误“Missing Method Exception:No Parameterless constructor for this目的”。浏览MVC源代码,似乎为了绑定到模型,Binder必须能够首先创建它,并且它不能创建SelectList,因为它没有默认的构造函数。
这里的简化代码: 对于模型:
public class DemoCreateViewModel
{
public SelectList Choice { get; set; }
}
对于控制器:
//
// GET: /Demo/Create
public ActionResult Create()
{
DemoCreateViewModel data = new DemoCreateViewModel();
data.Choice = new SelectList(new string[] { "Choice1", "Choice2", "Choice3" });
ViewData.Model = data;
return View();
}
//
// POST: /Demo/Create
[HttpPost]
public ActionResult Create(DemoCreateViewModel form)
{
try
{
// TODO: Add insert logic here
return RedirectToAction("Index");
}
catch
{
return View();
}
}
而对于浏览:
<fieldset>
<legend>Fields</legend>
<%= Html.LabelFor(model => model.Choice) %>
<%= Html.DropDownListFor(model => model.Choice, Model.Choice) %>
<p>
<input type="submit" value="Create" />
</p>
</fieldset>
现在,我知道我可以使这项工作回落10码和踢球:绕过模型绑定并退回到FormCo我自己选择并验证和绑定所有的领域,但是必须有一个更简单的方法。我的意思是,这只是一个简单的要求。有没有办法在MVC ModelBinding体系结构中进行这项工作?如果是这样,那是什么?如果不是,怎么样?
编辑:好吧,我的脸上有鸡蛋,但也许这会帮助别人。我做了一些更多的尝试,并找到了一个似乎可行的简单解决方案。
提供一个简单的值(字符串或整数,取决于您选择的列表值类型),并将其命名为您绑定的模型元素。然后提供第二个元素作为选择列表,并将其命名为其他内容。所以,我的模型变成了:
public class DemoCreateViewModel
{
public string Choice { get; set; }
public SelectList Choices { get; set; }
}
然后在视图中DropDownListFor声明变成:
<%= Html.DropDownListFor(model => model.Choice, Model.Choices) %>
当我这样做,提交按钮正确结合的形式作出了串选择的选择,并将模型提交回第二个Create方法。
这里有一个办法:
@Html.DropDownListFor(model => model.Choice,
ViewBag.Choices as SelectList,
"-- Select an option--",
new { @class = "editor-textbox" })
请注意,我用ViewBag包含我的SelectList。这样,当您回发时,客户端不会将整个选择列表作为模型的一部分发送到服务器。
在控制器代码,你只需要设置视图袋:
ViewBag.Choices = new SelectList(....
*请注意,我使用ViewBag来包含我的SelectList。通过这种方式,当您回发时,客户端不会将整个选择列表作为模型的一部分发送到服务器。*(1)它不会; (2)如果是这样,使用ViewBag不会阻止它被发布,它会阻止它绑定到模型。 – 2014-03-13 19:53:43
考虑不选择列表的属性为您创造职位的行动不同的视图模型:
public class DemoCreateViewModelForUpdate
{
public string Choice { get; set; }
}
然后你就可以如果模型状态无效且您想要重新显示视图,则始终将DemoCreateViewModelPost实例映射到DemoCreateViewModel实例。我倾向于将视图所需的所有内容都放在我的显示视图模型类中,因此使用单独的仅更新视图模型让我可以将事情保持苗条并修剪以便返回到服务器。
在你看来,你会怎么做:
@Html.DropDownListFor(m => m.Choice, Model.Choices)
如前面的答案,所以没有不必要的数据将往返。
感谢您发布您的修复程序,我遇到过类似的问题,并且您的修改帮助 – Chris 2010-10-25 11:54:06
难道您不能将它绑定到IEnumerable或ListList的SelectListItems吗? – 2012-09-26 08:40:58