c# - 具有键 'XXX' 的 ViewData 项的类型为 'System.Int32' 但必须为 'IEnumerable<SelectListItem>' 类型

标签 c# asp.net-mvc

我有以下 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>'.

如果我使用 ViewBagViewData 传递 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/

相关文章:

c# - 为什么会出现 Service Bus 链接日志?

asp.net - 将 Bootstrap 双列表框与 ASP.NET MVC 结合使用

asp.net - 无法复制或无法复制 "c:\pagefile.sys"和 "c:\hiberfile.sys"。重试次数超过 10。失败

asp.net-mvc - ASP.NET MVC - .mvc 路由在 II6 中失败

c# - 哪个更好?在存储库或域级服务(通过 IQueryable 或其他)中有复杂的搜索逻辑吗?

c# - 如何在图表中设置系列 Z-Order

c# - 外键约束 : false match with empty string and whitespace

c# - 如何使用 C# 应用程序连接到 telnet 的 tcp 端口 23?

asp.net - MVC 路由与区域 : Multiple types were found that match the controller 中的匹配 Controller

asp.net - Url.Action 如何在 Asp.net MVC 中工作?