Il n'y a pas d'élément ViewData de type 'IEnumerable <SelectListItem>' qui a la clé 'xxx'

87

Il y a quelques articles à ce sujet sur Stack Overflow mais aucun avec une réponse qui semble résoudre le problème dans ma situation actuelle.

J'ai une page avec un tableau, chaque ligne a un certain nombre de champs de texte et une liste déroulante. Tous les menus déroulants doivent utiliser les mêmes données SelectList, je l'ai donc configuré comme suit:

Manette

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

Vue

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

J'ai utilisé exactement cette configuration dans de nombreux endroits, mais pour une raison quelconque dans cette vue particulière, j'obtiens l'erreur:

Il n'y a pas d'élément ViewData de type «IEnumerable» qui a la clé «submarket_0».

Jimbo
la source
1
Avez-vous essayé cela? <%= Html.DropDownList("submarket_0", ((SelectList)ViewData["Submarkets"]).Items, "(none)") %>DropDownList prend IEnumerable<SelectListItem>.
LukLed
@LukLed - c'est en effet ainsi que j'ai finalement trouvé la source de l'erreur :) ainsi que des informations provenant d'autres messages! Merci
Jimbo
<%= Html.DropDownList("submarket_0", ViewData["Submarkets"] as IEnumerable<SelectListItem>, "(none)") %>
Arvis
J'ai rencontré cela aujourd'hui et j'ai trouvé que le deuxième argument de mon assistant DropDownList était nul, selon la découverte ci-dessous de @jonathansewell.
Ken Palmer

Réponses:

79

Ok, donc la réponse a été dérivée de quelques autres articles sur ce problème et c'est:

Si votre ViewDatacontient un SelectListavec le même nom que votre DropDownListie "submarket_0", l'assistant Html vous remplira automatiquement DropDownListavec ces données si vous ne spécifiez pas le 2ème paramètre qui dans ce cas est la SelectList source.

Ce qui s'est passé avec mon erreur était:

Étant donné que la table contenant les listes déroulantes était dans une vue partielle et qu'elle ViewDataavait été modifiée et ne contenait plus celle SelectListque j'avais référencée, le HtmlHelper(au lieu de lancer une erreur) a essayé de trouver la SelectList appelée "submarket_0" dans ViewData (GRRRR! !!) qu'il n'a toujours pas pu trouver, puis a jeté une erreur à ce sujet :)

Corrigez-moi si j'ai tort, s'il-vous plait

Jimbo
la source
104
J'ai eu cette erreur parce que ma collection de SelectListItems pour la liste déroulante était nulle, ce qui est le même problème que vous avez eu, je pense.
Jonathan Sewell
6
Pour les autres confrontés à ce problème, enveloppez temporairement votre liste déroulante dans une vérification nulle, par exemple @if (ViewData ["Submarkets"]! = Null). Si la vue s'affiche ensuite sans générer d'erreur (et sans votre liste déroulante), vous aurez identifié votre problème. L'erreur "no view data item" est très trompeuse dans ce cas.
GDB
J'ai rencontré cela en utilisant un fichier Ajax.ActionLink. Ajoutez simplement le SelectList Getau ActionMethodqui contient l'appel Ajax.
stink le
Oui! J'avais changé le nom de la liste que je transmettais à ViewData à partir du contrôleur, et je ne l'avais pas changé dans la vue. C'est un message d'erreur vraiment terriblement déroutant!
neminem
1
@JonathanSewell merci, merci, merci! C'était mon problème exact.
johnw182
29

Ancienne question, mais voici une autre explication du problème. Vous obtiendrez cette erreur même si vous avez des vues fortement typées et n'utilisez pas ViewData pour créer votre liste déroulante. La raison de l'erreur peut devenir claire lorsque vous regardez la source 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;
}

Donc, si vous avez quelque chose comme:

@Html.DropDownList("MyList", Model.DropDownData, "")

Et Model.DropDownDataest null, MVC recherche dans votre ViewData quelque chose de nommé MyListet renvoie une erreur s'il n'y a aucun objet dans ViewData avec ce nom.

faucon
la source
1
Salut, c'est aussi mon problème, que faisons-nous si la liste est nulle! pouvez-vous suggérer quelque chose,
transformer
4
@transformer La chose la plus simple à faire serait de définir Model.DropDownData sur une liste vide au lieu de null. Si ce n'est pas possible, vous pouvez modifier le balisage de votre rasoir pour vérifier si la liste est nulle, et si tel est le cas, restituer une liste de sélection vide.
hawkke
15

J'ai eu la même erreur, je pense que le problème est que le texte d'erreur est déroutant , car il donne un faux nom de clé.

Dans votre cas, il devrait indiquer "Il n'y a pas d'élément ViewData de type 'IEnumerable' qui a la clé" Sous-marchés "".

Mon erreur était une faute d'orthographe dans le code de vue (vos "Sous-marchés"), mais le texte d'erreur m'a rendu fou.

Je poste cette réponse parce que je veux dire aux gens qui recherchent cette erreur, comme moi, que le problème est que ce n'est pas de trouver le IENumerable, mais dans le var qu'il est censé le chercher ("Sous-marchés" dans ce cas), pas dans celui affiché par erreur ("submarket_0") .

La réponse acceptée est très intéressante, mais comme vous l'avez dit, la convention est appliquée si vous ne spécifiez pas le 2ème paramètre, dans ce cas il a été spécifié, mais la var n'a pas été trouvée (dans votre cas parce que les viewdata ne l'avaient pas, dans mon cas parce que J'ai mal orthographié le nom du var)

J'espère que cela t'aides!

Peto
la source
9

Le problème est dû au fait que la publication se produit lors du clic sur le bouton Soumettre. Ainsi, tout en publiant des données lors de la soumission, cliquez à nouveau sur écrire avant de retourner View ()

ViewData["Submarkets"] = new SelectList(submarketRep.AllOrdered(), "id", "name");
râteau
la source
3

Vérifiez l'espace de noms.

Vous pouvez affecter System.Web.Webpages.Html.SelectListItem dans le contrôleur, au lieu de System.Web.Mvc.SelectListItem .

MovGP0
la source
1

C'est bien aussi; Par exemple:
==> Dans le fichier "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();
}

==> Dans le fichier 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>

Maintenant, si nous supprimons cette déclaration:

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

à l'arrière de la déclaration suivante (dans notre contrôleur):

return View();

nous verrons cette erreur:

Il n'y a aucun élément ViewData de type 'IEnumerable' qui a la clé 'OperatorId'.

* Assurez-vous donc de l'existence de ces déclarations. *

Morteza
la source
0

Pour moi, le problème qui a causé cette erreur est survenu lorsque j'enregistrais une nouvelle ligne dans la base de données, mais un champ était nul. Dans la conception de table de base de données, ce champ n'est PAS NULL. Ainsi, lorsque j'ai essayé d'enregistrer une nouvelle ligne avec une valeur nulle pour un champ non nul, Visual Studio a renvoyé cette erreur. Ainsi, je me suis assuré que le champ se voyait attribuer une valeur et le problème a été résolu.

Thuy
la source
0

Dans mon cas, j'ai constaté que j'avais défini la méthode de publication comme privée par erreur. après avoir changé de privé en public.

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

changer en

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

Fonctionne maintenant très bien.

Mohammed Sabbir
la source
0

La cause n'est pas contraire à la syntaxe plutôt qu'à une utilisation inappropriée des objets. Le cycle de vie des objets dans ViewData, ViewBag et View Life Cycle est plus court que dans la session. Les données définies dans les formulaires seront perdues après une requête-réponse (si vous essayez d'accéder après une requête-réponse, vous obtiendrez des exceptions). Ainsi, les formers sont appropriés pour passer des données entre View & Controller tandis que ce dernier pour stocker des données temporaires. Les données temporaires doivent être stockées dans la session afin de pouvoir y accéder plusieurs fois.

sdfs
la source
-1

Dans mon cas, il y a eu un conflit dans les espaces de noms, j'ai:

using System.Web.Mvc;

et

using System.Collections.Generic;

Je veux explicitement utiliser celui de Mvc, alors je l'ai déclaré comme:

new System.Web.Mvc.SelectList(...)
Solutions IndieTech
la source
1
À moins que mes yeux me tromper, il n'y a pas SelectListdans System.Collections.Generic.
Erik Philips