El elemento ViewData que tiene la clave 'MY KEY' es del tipo 'System.String' pero debe ser del tipo 'IEnumerable <SelectListItem>'

142

Estoy tratando de completar una lista desplegable de una base de datos asignada con Linq-2-SQL, usando ASP.NET MVC 2, y sigo recibiendo este error.

Estoy tan confundido porque estoy declarando una variable de tipo IEnumerable<SelectListItem>en la segunda línea, pero el error me hace pensar que este no es el caso. Siento que esto debería ser muy simple, pero estoy luchando. Cualquier ayuda es apreciada.

Aquí están los bits interesantes de mi controlador:

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

Y aquí están los puntos interesantes de mi punto de vista:

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

Aquí está la acción POST al enviar el formulario

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

Gracias.

JBibbs
fuente
1
La lista desplegable aparece en la vista muy bien. Se rellena desde la base de datos como debería, pero es cuando publico el formulario que recibo estos errores.
JBibbs
66
Resumen de la respuesta aceptada: asegúrese de completar la lista en las acciones get y post de su controlador. Es fácil olvidar hacer esto, y luego terminar perdiendo el tiempo buscando un error más complicado.
Adam Tolley

Respuestas:

208

Tuve el mismo problema y finalmente obtuve la respuesta ...

El problema es que en la acción POST, después de enviar el formulario, el ModelState no es válido o detecta un error en try / catch, por lo que se devuelve la Vista. Pero esta vez la Vista no se ha ViewData["basetype"]configurado correctamente.

Debe rellenarlo nuevamente, probablemente con el mismo código utilizado anteriormente, así que repita esto:

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

antes de return View(meal)en el [HttpPost]método.

exactamente esto resolverá tu problema:

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

Sé que esta pregunta es muy antigua, pero vine aquí hoy con el mismo problema, por lo que podría venir aquí más tarde ...

Peto
fuente
8
+1 para "poblarlo de nuevo" ... Tengo un sistema bastante robusto para componer mis modelos de vista, pero había olvidado por completo llamarlo. Por lo tanto, la propiedad no estaba poblada y recibí este mensaje (bastante ambiguo) sin importar lo que intenté.
Tim Medora
8
si obtienes esto ANTES de una publicación, es porque no hay nada en la Lista de selección, acabo de encontrar esa.
Martin
1
+1 ¡Porque estaba configurando mi ViewBag en el método Index cuando realmente estaba llamando a un Html.Action a otro Método de Acción!
SwampyFox
Gracias. Sería bueno si solo se conservara, pero supongo que esa no sería la "forma" de MVC.
Casey
si el modelo se está invalidando, ¿vengo que los datos enviados por el usuario se guardarán en la base de datos? También estoy enfrentando el mismo problema. Soy un novato. corrígeme si estoy equivocado.
Koushik Saha
87

Recibirá este error si la SelectList es nula.

Ben
fuente
3
Sí, este es un error / supervisión común cuando configura la SelectList en un GET y luego la devuelve a una acción POST (obviamente) que tiene un ModelState.IsValid==falsemodo de devolver el modelo return View(model) pero no repoblar su fuente SelectList antes de regresar de la POST. Como no hay ViewState ala WebForms, no hay fuente para que el @Html.DropDownayudante pueda reconstruir la selección con. Debe completar esa lista de origen CADA vez que devuelva la vista al cliente, no solo en el GET.
rism
Sí, este era mi problema. Olvidé llenar la lista de selección en la llamada de obtención. Error muy engañoso. Buena publicación.
Matt
1

Para futuros lectores, si está utilizando la maquinilla de afeitar, intente cambiar el tipo de elemento de la lista de selección de Lista a IEnumerable.

De

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

A

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

Intente agregar una cadena para el nombre de su lista desplegable como primer parámetro y saque el elemento de sus datos de vista:

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

Aquí también hay un método de extensión que puede usar para que la lista desplegable esté configurada en un estilo similar al de sus otros controles:

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

Por ejemplo

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

Está configurando la colección como un elemento en el diccionario ViewData e intenta recuperarla como propiedad en el modelo. Una solución simple sería hacer referencia a él de la misma manera que lo configuró:

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

Alternativamente, el siguiente código utiliza una vista fuertemente tipada:

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

Luego, en su vista fuertemente tipada:

    <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>
Igor Zevaka
fuente
Intenté usar el código en su ejemplo de "arreglo simple" y obtuve el mismo error. Debería haber mencionado que la lista desplegable se completa en la Vista ok, pero recibo este error cuando envío el formulario.
JBibbs
¿Puede publicar el código de la Acción del controlador que maneja el envío del formulario?
Igor Zevaka
Claro, lo agregaré a la publicación original. Gracias por su ayuda hasta ahora.
JBibbs
0

Si usa el Html.DropDownList()método, puede ocurrir el mismo error si su elemento ViewData / Viewbag no está configurado, como respondió @Peto.

Pero es posible que no se configure correctamente en el caso de que el elemento configurado sea el controlador, pero en la vista principal se usa una llamada viw parcial con nuevos valores ViewDataDictionary.

si tiene, @Html.Partial("Partianame", Model,new ViewDataDictionary() { /* ... */ })entonces su vista parcial no verá ViewDatani ViewBagdatos, elimine el new ViewDataDictionary()parámetro

Evgeny Levin
fuente
0

Para futuros lectores,

Encontré el problema hoy y no pude solucionarlo. Resultó ser realmente simple después de todo. Estaba trabajando con una tabla + vista. Cuando actualicé la tabla (agregué algunas columnas) olvidé actualizar (soltar y volver a crear) la vista, lo que me causó el problema. Espero que ayude a alguien.

Mariano Gianni
fuente
0

Hoy recibí el mismo error y mi solución es hacer que el modelo sea "válido".

En mi caso, después de enviar el usuario haciendo clic en "guardar", obtuve el estado del modelo: no válido si el usuario ingresa "0", pero el estado del modelo será válido si el usuario ingresa "0.0".

Por lo tanto, anulo el método "IsValid" para devolver la clave de usuario verdadera incluso "0".

Espero eso ayude.

Ray Chung
fuente