具有键“MY KEY”的ViewData项的类型为“System.String”,但必须是“IEnumerable <selectlistitem>”类型</selectlistitem>

时间:2010-08-03 04:09:40

标签: asp.net-mvc

我正在尝试使用ASP.NET MVC 2从使用Linq-2-SQL映射的数据库填充下拉列表,并继续收到此错误。

我很困惑,因为我在第二行声明了IEnumerable<SelectListItem>类型的变量,但错误让我觉得情况并非如此。我觉得这应该很简单,但我很挣扎。任何帮助表示赞赏。

以下是我的控制器的有趣内容:

public ActionResult Create()
{
    var db = new DB();
    IEnumerable<SelectListItem> basetypes = db.Basetypes.Select(
        b => new SelectListItem { Value = b.basetype, Text = b.basetype });
    ViewData["basetype"] = basetypes;
    return View();
}

以下是我观点的有趣内容:

<div class="editor-label">
   <%: Html.LabelFor(model => model.basetype) %>
</div>
<div class="editor-field">
   <%: Html.DropDownList("basetype") %>
   <%: Html.ValidationMessageFor(model => model.basetype) %>
</div>

这是提交表单时的POST操作

// POST: /Meals/Create
[HttpPost]
public ActionResult Create(Meal meal)
{
    if (ModelState.IsValid)
    {
        try
        {
            // TODO: Add insert logic here
            var db = new DB();
            db.Meals.InsertOnSubmit(meal);
            db.SubmitChanges();
            return RedirectToAction("Index");
        }
        catch
        {
            return View(meal);
        }
    }
    else
    {
        return View(meal);
    }
}

感谢。

9 个答案:

答案 0 :(得分:204)

我有同样的问题,最后我得到了答案......

问题是在POST操作中,提交表单后,ModelState无效,或者它在try / catch中捕获错误,因此返回View。但这次View没有正确设置ViewData["basetype"]

您需要再次填充它,可能使用之前使用的相同代码,因此请重复此步骤:

var db = new DB();
IEnumerable<SelectListItem> basetypes = db.Basetypes.Select(
    b => new SelectListItem { Value = b.basetype, Text = b.basetype });
ViewData["basetype"] = basetypes;
return View(meal)方法的[HttpPost]之前

这将解决您的问题:

[HttpPost]
public ActionResult Create(Meal meal)
{
    if (ModelState.IsValid)
    {
        try
        {
            // TODO: Add insert logic here
            var db = new DB();
            db.Meals.InsertOnSubmit(meal);
            db.SubmitChanges();
            return RedirectToAction("Index");
        }
        catch
        {
            var db = new DB();
            IEnumerable<SelectListItem> basetypes = db.Basetypes.Select(
               b => new SelectListItem { Value = b.basetype, Text = b.basetype });
            ViewData["basetype"] = basetypes;
            return View(meal);
        }
    }
    else
    {
        var db = new DB();
        IEnumerable<SelectListItem> basetypes = db.Basetypes.Select(
            b => new SelectListItem { Value = b.basetype, Text = b.basetype });
        ViewData["basetype"] = basetypes;
        return View(meal);
    }
}

我知道这个问题已经很老了,但是今天我带着同样的问题来到这里,所以其他人可能会来这里...

答案 1 :(得分:86)

如果SelectList为null,您将收到此错误。

答案 2 :(得分:3)

我刚刚遇到过这个问题,本文帮助我完成了这个问题 - http://odetocode.com/Blogs/scott/archive/2010/01/18/drop-down-lists-and-asp-net-mvc.aspx

最有可能导致你的收藏品在po

之后重新填充

答案 3 :(得分:1)

对于将来的读者,如果您使用的是剃刀,请尝试将选择列表项的类型从“列表”更改为IEnumerable。

来自

@Html.DropDownListFor(m => m.id, ViewBag.SomeList as List<SelectListItem>)

收件人

@Html.DropDownListFor(m => m.id, ViewBag.SomeList as IEnumerable<SelectListItem>)

答案 4 :(得分:0)

您正在将集合设置为ViewData字典中的项目,并尝试将其作为模型上的属性进行检索。一个简单的解决方法是以与设置它相同的方式引用它:

    <%var basetype = ViewData["basetype"] as IEnumerable<SelectListItem>;%>
    <div class="editor-label">
        <%: Html.Label("basetype") %>
    </div>
    <div class="editor-field">
        <%: Html.DropDownList("basetype", basetype) %>
        <%: Html.ValidationMessage("basetype") %>
    </div>

或者,以下代码使用强类型视图:

public class ViewModel {
   //Model properties
   public IEnumerable<SelectListItem> basetype {get;set;}
}

public ActionResult Create()
    {
        var db = new DB();
        IEnumerable<SelectListItem> basetypes = db.Basetypes.Select(b => new SelectListItem { Value = b.basetype, Text = b.basetype });
        return View(new ViewModel { basetype=basetypes });
    }

然后,在强类型视图中:

    <div class="editor-label">
        <%: Html.LabelFor(model => model.basetype) %>
    </div>
    <div class="editor-field">
        <%: Html.DropDownListFor(model=>model.basetype) %>
        <%: Html.ValidationMessageFor(model => model.basetype) %>
    </div>

答案 5 :(得分:0)

尝试添加下拉列表名称的字符串作为第一个参数,并从viewdata中获取该项目:

 <%= Html.DropDownList("SomeDropdownName", (IEnumerable<SelectListItem>)ViewData["basetype"]) %>

以下是您可以使用的扩展方法,因此下拉列表的设置方式与您完成其他控件的方式类似:

        public static string DropDownList<TModel, TProperty>(this HtmlHelper<TModel> htmlHelper, Expression<Func<TModel, TProperty>> expression, IEnumerable<SelectListItem> selectList, string optionLabel)
        where TModel : class
    {
        string inputName = ExpressionHelper.GetInputName(expression);
        return htmlHelper.DropDownList(inputName, selectList, optionLabel);
    }

例如

<%= Html.DropDownList(x => x.BaseType, (IEnumerable<SelectListItem>)ViewData["basetype"], "")%>

答案 6 :(得分:0)

如果使用Html.DropDownList()方法 - 如果未设置ViewData / Viewbag项目,则可能会出现相同的错误,如@Peto所示。

但是在控制器设置项正确的情况下可能没有设置,但在主视图中,您使用具有新ViewDataDictionary值的部分viw调用。

如果您有@Html.Partial("Partianame", Model,new ViewDataDictionary() { /* ... */ }),那么您的部分视图将看不到ViewDataViewBag数据,请删除new ViewDataDictionary()参数

答案 7 :(得分:0)

对未来的读者,

我今天遇到了这个问题但无法修复它。毕竟它变得非常简单。我正在使用表+视图。当我更新表(添加了几个列)时,我忘了更新(删除并重新创建)视图,这给我带来了问题。 希望它对某人有所帮助。

答案 8 :(得分:0)

今天我遇到了同样的错误,我的解决方案是使模型“有效”。

在我的情况下,用户单击“保存”提交后,我得到了模型状态:如果用户键入“ 0”则无效,但如果用户键入“ 0.0”则模型状态才有效。

因此,我重写了“ IsValid”方法,即使用户键入“ 0”也返回true。

希望有帮助。