145 votes

L'élément ViewData qui possède la clé 'MY KEY' est de type 'System.String' mais doit être de type 'IEnumerable<SelectListItem>'.

J'essaie d'alimenter une liste déroulante à partir d'une base de données mappée avec Linq-2-SQL, en utilisant ASP.NET MVC 2, et je continue à obtenir cette erreur.

Je suis tellement confus parce que je déclare une variable de type IEnumerable<SelectListItem> sur la deuxième ligne, mais l'erreur me fait penser que ce n'est pas le cas. J'ai l'impression que cela devrait être très simple, mais je me débats. Toute aide est la bienvenue.

Voici les éléments intéressants de mon contrôleur :

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

Et voici les éléments intéressants de mon point de vue :

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

Voici l'action POST lors de la soumission du formulaire

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

Merci.

1 votes

La liste déroulante apparaît très bien dans la vue. Elle se remplit à partir de la base de données comme il se doit, mais c'est lorsque je publie le formulaire que j'obtiens ces erreurs.

8 votes

Résumé de la réponse acceptée : Assurez-vous que vous remplissez la liste dans les actions get et post de votre contrôleur. Il est facile d'oublier de le faire, et de perdre du temps à chercher un bogue plus compliqué.

211voto

Peto Points 1100

J'ai eu le même problème, et finalement j'ai eu la réponse...

Le problème est que dans l'action POST, après avoir soumis le formulaire, le ModelState n'est pas valide, ou bien il attrape une erreur dans try/catch, donc la vue est retournée. Mais cette fois, la vue n'a pas le ViewData["basetype"] correctement réglé.

Vous devez le remplir à nouveau, probablement avec le même code que celui utilisé précédemment, donc répétez ceci :

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

avant le return View(meal) dans le [HttpPost] méthode.

exactement ce qui va résoudre votre problème :

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

Je sais que cette question est très ancienne, mais je suis venu ici aujourd'hui avec le même problème, donc d'autres pourraient venir plus tard...

8 votes

+J'ai mis en place un système assez robuste pour composer mes modèles de vue, mais j'avais complètement oublié de l'appeler. Ainsi, la propriété n'a pas été remplie et j'ai reçu ce message (plutôt ambigu), peu importe ce que j'ai essayé.

8 votes

Si vous obtenez ceci AVANT un message, c'est parce qu'il n'y a rien dans la SelectList, je viens de trouver celui-là.

1 votes

+1 Parce que je réglais mon ViewBag dans la méthode Index alors qu'en réalité j'appelais une Html.Action à une autre méthode d'action ! !!

88voto

BenAdler Points 96

Vous recevrez cette erreur si la SelectList est nulle.

4 votes

Oui, il s'agit d'une erreur courante ou d'une erreur d'inattention lorsque vous configurez la liste de sélection sur un GET, puis que vous revenez à une action POST (évidemment) qui a une fonction ModelState.IsValid==false donc vous renvoyez le modèle return View(model) mais ne repeuplez pas votre source SelectList avant le retour du POST. Puisqu'il n'y a pas de ViewState à la manière de WebForms, il n'y a pas de source pour l'élément @Html.DropDown pour reconstruire la sélection. Vous devez remplir cette liste de sources CHAQUE fois que vous renvoyez la vue au client, et pas seulement lors de l'extraction.

0 votes

Oui, c'était mon problème. J'ai oublié de remplir la selectList lors de l'appel get. Erreur très trompeuse. Excellent article.

3voto

Michael Points 44

Je viens de rencontrer ce problème et cet article m'a aidé à le résoudre. http://odetocode.com/Blogs/scott/archive/2010/01/18/drop-down-lists-and-asp-net-mvc.aspx

La cause la plus probable est que votre collection a été repeuplée après que le po

0voto

Igor Zevaka Points 32586

Vous définissez la collection comme un élément dans le dictionnaire ViewData et essayez de la récupérer comme une propriété sur le modèle. Une solution simple serait de la référencer de la même manière que vous l'avez définie :

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

Alternativement, le code ci-dessous utilise une vue fortement typée :

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

Ensuite, dans votre vue fortement typée :

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

0 votes

J'ai essayé d'utiliser le code de votre exemple "simple fix", et j'ai obtenu la même erreur. J'aurais dû mentionner que la liste déroulante se remplit bien dans la vue, mais j'obtiens cette erreur lorsque je soumets le formulaire.

0 votes

Pouvez-vous afficher le code de l'action du contrôleur qui gère la soumission du formulaire ?

0 votes

Bien sûr, je vais l'ajouter au message original. Merci pour votre aide jusqu'à présent.

0voto

CRice Points 4717

Essayez d'ajouter une chaîne de caractères pour le nom de votre liste déroulante comme premier paramètre, et récupérez l'élément dans vos données d'affichage :

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

Voici également une méthode d'extension que vous pouvez utiliser pour que la liste déroulante soit configurée dans un style similaire à celui de vos autres contrôles :

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

Par exemple

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

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X