我有以下 View 模型
public class ProjectVM
{
....
[Display(Name = "Category")]
[Required(ErrorMessage = "Please select a category")]
public int CategoryID { get; set; }
public IEnumerable<SelectListItem> CategoryList { get; set; }
....
}
和以下 Controller 方法来创建一个新项目并分配一个类别
public ActionResult Create()
{
ProjectVM model = new ProjectVM
{
CategoryList = new SelectList(db.Categories, "ID", "Name")
}
return View(model);
}
public ActionResult Create(ProjectVM model)
{
if (!ModelState.IsValid)
{
return View(model);
}
// Save and redirect
}
在 View 中
@model ProjectVM
....
@using (Html.BeginForm())
{
....
@Html.LabelFor(m => m.CategoryID)
@Html.DropDownListFor(m => m.CategoryID, Model.CategoryList, "-Please select-")
@Html.ValidationMessageFor(m => m.CategoryID)
....
<input type="submit" value="Create" />
}
View 显示正确,但是在提交表单时,我收到以下错误消息
InvalidOperationException: The ViewData item that has the key 'CategoryID' is of type 'System.Int32' but must be of type 'IEnumerable<SelectListItem>'.
如果我使用 ViewBag
或 ViewData
传递 SelectList,使用 @Html.DropDownList()
方法会发生同样的错误。
最佳答案
错误表示CategoryList
的值为空(因此 DropDownListFor()
方法期望第一个参数的类型为 IEnumerable<SelectListItem>
)。
您没有为每个 SelectListItem
的每个属性生成输入在 CategoryList
(你也不应该)所以 SelectList
没有值被发布到 Controller 方法,因此 model.CategoryList
的值在 POST 方法中是 null
.如果返回 View ,则必须先重新分配 CategoryList
的值,就像您在 GET 方法中所做的那样。
public ActionResult Create(ProjectVM model)
{
if (!ModelState.IsValid)
{
model.CategoryList = new SelectList(db.Categories, "ID", "Name"); // add this
return View(model);
}
// Save and redirect
}
解释内部工作原理(源代码可以是seen here)
DropDownList()
的每次重载和 DropDownListFor()
最终调用了下面的方法
private static MvcHtmlString SelectInternal(this HtmlHelper htmlHelper, ModelMetadata metadata,
string optionLabel, string name, IEnumerable<SelectListItem> selectList, bool allowMultiple,
IDictionary<string, object> htmlAttributes)
它检查是否 selectList
(@Html.DropDownListFor()
的第二个参数)是null
// If we got a null selectList, try to use ViewData to get the list of items.
if (selectList == null)
{
selectList = htmlHelper.GetSelectData(name);
usedViewData = true;
}
依次调用
private static IEnumerable<SelectListItem> GetSelectData(this HtmlHelper htmlHelper, string name)
评估 @Html.DropDownListFor()
的第一个参数(在本例中为 CategoryID
)
....
o = htmlHelper.ViewData.Eval(name);
....
IEnumerable<SelectListItem> selectList = o as IEnumerable<SelectListItem>;
if (selectList == null)
{
throw new InvalidOperationException(String.Format(CultureInfo.CurrentCulture,
MvcResources.HtmlHelper_WrongSelectDataType,
name, o.GetType().FullName, "IEnumerable<SelectListItem>"));
}
因为属性CategoryID
类型是 int
, 它不能转换为 IEnumerable<SelectListItem>
并抛出异常(在 MvcResources.resx
文件中定义为)
<data name="HtmlHelper_WrongSelectDataType" xml:space="preserve">
<value>The ViewData item that has the key '{0}' is of type '{1}' but must be of type '{2}'.</value>
</data>
关于c# - 具有键 'XXX' 的 ViewData 项的类型为 'System.Int32' 但必须为 'IEnumerable<SelectListItem>' 类型,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40313611/