具有键“XXX"的 ViewData 项的类型为“System.Int32",但必须为“IEnumerable<SelectListItem>"类型 [英] The ViewData item that has the key &#39;XXX&#39; is of type &#39;System.Int32&#39; but must be of type &#39;IEnumerable&lt;SelectListItem&gt;&#39;

查看:29
本文介绍了具有键“XXX"的 ViewData 项的类型为“System.Int32",但必须为“IEnumerable<SelectListItem>"类型的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有以下视图模型

public class ProjectVM
{
    ....
    [Display(Name = "Category")]
    [Required(ErrorMessage = "Please select a category")]
    public int CategoryID { get; set; }
    public IEnumerable<SelectListItem> CategoryList { get; set; }
    ....
}

和以下控制器方法来创建一个新项目并分配一个Category

and the following controller method to create a new Project and assign a Category

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
}

在视图中

@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" />
}

视图显示正确,但在提交表单时,我收到以下错误消息

The view displays correctly but when submitting the form, I get the following error message

InvalidOperationException:具有键CategoryID"的 ViewData 项的类型为System.Int32",但必须为IEnumerable"类型.

InvalidOperationException: The ViewData item that has the key 'CategoryID' is of type 'System.Int32' but must be of type 'IEnumerable<SelectListItem>'.

使用 @Html.DropDownList() 方法时会发生同样的错误,如果我使用 ViewBagViewData 传递 SelectList.

The same error occurs using the @Html.DropDownList() method, and if I pass the SelectList using a ViewBag or ViewData.

推荐答案

该错误意味着 CategoryList 的值为 null(因此 DropDownListFor()方法期望第一个参数的类型为 IEnumerable).

The error means that the value of CategoryList is null (and as a result the DropDownListFor() method expects that the first parameter is of type IEnumerable<SelectListItem>).

您没有为 CategoryList 中每个 SelectListItem 的每个属性生成输入(您也不应该),因此 SelectList 没有值被发布到控制器方法中,因此POST方法中model.CategoryList的值为null.如果返回视图,则必须首先重新分配 CategoryList 的值,就像在 GET 方法中所做的一样.

You are not generating an input for each property of each SelectListItem in CategoryList (and nor should you) so no values for the SelectList are posted to the controller method, and therefore the value of model.CategoryList in the POST method is null. If you return the view, you must first reassign the value of CategoryList, just as you did in the GET method.

public ActionResult Create(ProjectVM model)
{
    if (!ModelState.IsValid)
    {
        model.CategoryList = new SelectList(db.Categories, "ID", "Name"); // add this
        return View(model);
    }
    // Save and redirect
}

解释内部工作原理(源代码可以在看到这里)

To explain the inner workings (the source code can be seen here)

DropDownList()DropDownListFor() 的每个重载最终都会调用下面的方法

Each overload of DropDownList() and DropDownListFor() eventually calls the following method

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

which checks if the selectList (the second parameter of @Html.DropDownListFor()) is 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)

which evaluates the the first parameter of @Html.DropDownListFor() (in this case 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>"));
}

因为属性 CategoryIDint 的类型,所以它不能被强制转换为 IEnumerable 并抛出异常(定义在MvcResources.resx 文件为)

Because property CategoryID is typeof int, it cannot be cast to IEnumerable<SelectListItem> and the exception is thrown (which is defined in the MvcResources.resx file as)

<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>

这篇关于具有键“XXX"的 ViewData 项的类型为“System.Int32",但必须为“IEnumerable<SelectListItem>"类型的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆