没有类型为“IEnumerable<SelectListItem>”且键为“xxx”的ViewData项。

87

关于这个问题在Stack Overflow上有几篇帖子,但没有一个答案似乎可以解决我当前的情况。

我有一个包含表格的页面,每一行都有几个文本字段和一个下拉列表。所有下拉列表都需要使用相同的SelectList数据,因此我已经按以下方式设置:

控制器

ViewData["Submarkets"] = new SelectList(submarketRep.AllOrdered(), "id", "name");

视图

<%= Html.DropDownList("submarket_0", (SelectList)ViewData["Submarkets"], "(none)") %>

我在许多地方都使用了完全相同的设置,但是在这个特定的视图中,我却遇到了错误:

没有类型为“IEnumerable”的 ViewData 项具有键“submarket_0”。


1
你试过这个吗?<%= Html.DropDownList("submarket_0", ((SelectList)ViewData["Submarkets"]).Items, "(none)") %> DropDownList需要 IEnumerable<SelectListItem> - LukLed
@LukLed - 这确实是我最终找到错误源的方法:) 另外还参考了一些其他帖子的信息!谢谢。 - Jimbo
<%= Html.DropDownList("submarket_0", ViewData["Submarkets"] as IEnumerable<SelectListItem>, "(none)") %> - Arvis
今天遇到了这个问题,发现我的DropDownList助手中的第二个参数是null,根据@jonathansewell的发现。 - Ken Palmer
10个回答

81

好的,因此答案是从其他有关此问题的帖子中得出的:

如果您的ViewData包含与您的DropDownList相同名称的SelectList,即"submarket_0",并且您没有指定第二个参数,则Html helper将自动使用该数据填充您的DropDownList

我的错误原因是:

因为包含下拉列表的表位于偏视图中,并且已更改ViewData并不再包含我引用的SelectList,所以HtmlHelper(而不是抛出错误)尝试在ViewData中找到名为"submarket_0"的SelectList(GRRRR!!!),它仍然找不到,然后抛出错误 :)

如果我错了请纠正我。


108
我得到了这个错误,因为我用于下拉列表的SelectListItems集合为空,这可能是你遇到的同样的问题。 - Johnathan Sewell
6
对于其他遇到这个问题的人,可以尝试在下拉列表周围加上一个空值检查,例如@if (ViewData["Submarkets"] != null)。如果视图在不抛出错误(且没有下拉列表)的情况下呈现,则说明您已经确定了问题所在。在这种情况下,“没有视图数据项”错误信息可能会非常误导。 - GDB
我在使用 Ajax.ActionLink 时遇到了这个问题。只需将 SelectListGet 添加到包含 Ajax 调用的 ActionMethod 中即可解决。 - stink
是的!我已经更改了从控制器传递到ViewData的列表名称,但在视图中没有更改。这是一个非常令人困惑的错误消息! - neminem
1
@JonathanSewell 谢谢你,谢谢你,谢谢你!这正是我的问题。 - johnw182
是的,在我的情况下,我只是在错误的方法中添加了ViewBag赋值。 - Mirek Michalak

30

虽然这是一个老问题,但我这里有另一种解释。即使您使用强类型视图并且不使用ViewData创建下拉列表,您仍会遇到此错误。当您查看MVC源码时,错误的原因就变得清晰了:

// 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;
}
如果您有类似以下的内容: @Html.DropDownList("MyList", Model.DropDownData, "")
如果Model.DropDownData为空,MVC将在您的ViewData中寻找名为“MyList”的对象,如果没有具有该名称的对象,MVC会抛出一个错误。

1
嗨,这也是我的问题,如果列表为空,我们该怎么办!你能提供一些建议吗? - Transformer
4
将 Model.DropDownData 设置为一个空列表而不是 null 是最简单的方法。如果不行,可以修改你的 Razor 标记,检查列表是否为空,如果是,则呈现一个空的下拉列表。 - hawkke

15

我也遇到了同样的错误,我认为问题在于错误信息很令人困惑,因为它提供了一个错误的键名。

在你的情况下,应该说“没有名为'Submarkets'的类型为'IEnumerable'的ViewData项。”

我的错误是视图代码中拼写错误(你的是“Submarkets”),但错误文本让我发疯了。

我发布这个答案是因为我想告诉像我一样寻找这个错误的人们,问题是它没有找到IENumerable,但是在它应该查找它的变量中(在这种情况下是“Submarkets”),而不是显示错误的变量(“submarket_0”)

接受的答案非常有趣,但正如你所说,如果您没有指定第二个参数,则会应用约定,在这种情况下已经指定了第二个参数,但未找到该变量(在您的情况下,因为viewdata没有它,在我的情况下,因为我拼错了变量名)。

希望这可以帮助!


9
问题是因为在提交按钮点击时发生了后台操作。 因此,在提交数据时,需要在返回View()之前再次编写。
ViewData["Submarkets"] = new SelectList(submarketRep.AllOrdered(), "id", "name");

3

检查命名空间。

你可能在控制器中赋值了 System.Web.Webpages.Html.SelectListItem,而不是 System.Web.Mvc.SelectListItem


1

这也可以;例如:
==> 在“NumberController”文件中:

public ActionResult Create([Bind(Include = "NumberId,Number1,Number2,OperatorId")] Number number)
{
    if (ModelState.IsValid)
    {
        ...
        ...
        return RedirectToAction("Index");
    }
    ViewBag.OperatorId = new SelectList(db.Operators, "OperatorId", 
                                "OperatorSign", number.OperatorId);                
    return View();
}

==> 在视图文件(Create.cshtml)中:

<div class="form-group">
    @Html.LabelFor(model => model.Number1, htmlAttributes: new { @class = 
                   "control-label col-md-2" })
    <div class="col-md-10">
        @Html.EditorFor(model => model.Number1, new { htmlAttributes = new { 
                        @class = "form-control" } })
        @Html.ValidationMessageFor(model => model.Number1, "", new { @class = 
                                   "text-danger" })
    </div>
</div>

现在如果我们移除这个语句:

ViewBag.OperatorId = new SelectList(db.Operators, "OperatorId", "OperatorSign", number.OperatorId);

从以下语句的后面(在我们的控制器中):

return View();

我们会看到这个错误:

'OperatorId'键没有类型为“IEnumerable”的ViewData项。

* 因此,请确保这些语句存在。 *


0

问题不在于语法错误,而是对象使用不当。 ViewData、ViewBag 和 View 的生命周期比会话短。在前者中定义的数据将在请求-响应后丢失(如果在请求-响应后尝试访问,则会出现异常)。因此,前者适用于在视图和控制器之间传递数据,而后者适用于存储临时数据。应该将临时数据存储在会话中以便多次访问。


0
对我来说,导致这个错误的问题是当我将一个新行保存到数据库时,但是一个字段为空。在数据库表设计中,该字段为NOT NULL。因此,当我尝试保存一个具有非空字段的空值的新行时,Visual Studio抛出了这个错误。因此,我确保该字段被分配了一个值,问题得到了解决。

0
在我的情况下,我发现我错误地将“post”方法设置为私有的。在将其更改为公共后,问题得以解决。
[HttpPost]
private async Task<ActionResult> OnPostRemoveForecasting(){}

变成

[HttpPost]
public async Task<ActionResult> OnPostRemoveForecasting(){}

现在运行良好。


-1
在我的情况下,命名空间存在冲突,我有:
using System.Web.Mvc;

using System.Collections.Generic;

我明确想要使用Mvc,因此我将其声明为:

new System.Web.Mvc.SelectList(...)

2
除非我眼花,否则在 System.Collections.Generic 中没有 SelectList - Erik Philips

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接