The ViewData item that has the key 'MY KEY' is of type 'System.String' but must be of type 'IEnumerable<SelectListItem>'

asp.net Mvc

asp.net Mvc Problem Overview


I am trying to populate a dropdown list from a database mapped with Linq-2-SQL, using ASP.NET MVC 2, and keep getting this error.

I am so confused because I am declaring a variable of type IEnumerable<SelectListItem> on the second line, but the error makes me think this is not the case. I feel like this should be very simple, but I am struggling. Any help is appreciated.

Here are the interesting bits of my controller:

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();
}

And here are the interesting bits of my view:

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

Here is the POST action when submitting the Form

// 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);
    }
}

Thanks.

asp.net Mvc Solutions


Solution 1 - asp.net Mvc

I had same problem, and finally I got the answer...

The problem is that in the POST action, after submitting the form, the ModelState is not valid, or it's catching an error in try/catch, so the View is returned. But this time the View has not the ViewData["basetype"] correctly set.

You need to populate it again, probably with the same code used before, so repeat this:

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

before the return View(meal) in the [HttpPost] method.

exactly this will solve your problem:

[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);
    }
}

I know this question is very old, but I came here today with the same problem, so other could come here later...

Solution 2 - asp.net Mvc

You will receive this error if the SelectList is null.

Solution 3 - asp.net Mvc

I've just come across this issue and this article helped me through it - http://odetocode.com/Blogs/scott/archive/2010/01/18/drop-down-lists-and-asp-net-mvc.aspx

The most likely cause it that your collection is repopulated after the po

Solution 4 - asp.net Mvc

For future readers, if you are using razor, try to change type of selectlist item from List to IEnumerable.

From

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

To

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

Solution 5 - asp.net Mvc

You are setting the collection as an item in ViewData dictionary and trying to retreive it as property on the model. A simple fix would be to reference it the same way as you set it:

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

Alternatively, the below code uses a strongly typed view:

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 });
    }

Then, in your strongly typed view:

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

Solution 6 - asp.net Mvc

Try adding a string for the name of your dropdown list as the first parameter, and get the item out of your viewdata:

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

Here is also an extension method you can use so the dropdown list is set up in a similar style to how you have done your other controls:

        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);
    }

For example

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

Solution 7 - asp.net Mvc

If you use Html.DropDownList() method - same error may occur, if your ViewData/Viewbag item not set, as @Peto answered.

But it may be not set in case of controller set item correctly, but in main view you use partial viw call with new ViewDataDictionary values.

if you have @Html.Partial("Partianame", Model,new ViewDataDictionary() { /* ... */ }) then your partial view will not see ViewData and ViewBag data, remove new ViewDataDictionary() parameter

Solution 8 - asp.net Mvc

To future readers,

I came across with the problem today and couldnĀ“t fix it. It turned to be really simple after all. I was working with a table + view. When I updated the table (added a few colums) I forgot to update (drop and recreate) the view, which caused the problem for me. Hope it helps somebody.

Solution 9 - asp.net Mvc

I got same error today and my solution is to make model "valid".

In my case, after user submit by clicking "save", I got model state: invalid if user key-in "0", but model state will be valid if user key-in "0.0".

So I override "IsValid" method to return true even user key-in "0".

Hope it helps.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionJBibbsView Question on Stackoverflow
Solution 1 - asp.net MvcPetoView Answer on Stackoverflow
Solution 2 - asp.net MvcBenView Answer on Stackoverflow
Solution 3 - asp.net MvcMichaelView Answer on Stackoverflow
Solution 4 - asp.net MvcsxyplexView Answer on Stackoverflow
Solution 5 - asp.net MvcIgor ZevakaView Answer on Stackoverflow
Solution 6 - asp.net MvcCRiceView Answer on Stackoverflow
Solution 7 - asp.net MvcDavid LevinView Answer on Stackoverflow
Solution 8 - asp.net MvcKoniView Answer on Stackoverflow
Solution 9 - asp.net MvcRay ChungView Answer on Stackoverflow