Nessun elemento ViewData di tipo "IEnumerable <SelectListItem>" con la chiave "xxx"


87

Ci sono un paio di post su questo su Stack Overflow ma nessuno con una risposta che sembra risolvere il problema nella mia situazione attuale.

Ho una pagina con una tabella, ogni riga ha un numero di campi di testo e un menu a discesa. Tutti i menu a discesa devono utilizzare gli stessi dati di SelectList, quindi l'ho impostato come segue:

Controller

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

Visualizza

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

Ho usato esattamente questa configurazione in molti posti, ma per qualche motivo in questa vista particolare ottengo l'errore:

Non è presente alcun elemento ViewData di tipo "IEnumerable" con la chiave "submarket_0".


1
Hai provato questo? <%= Html.DropDownList("submarket_0", ((SelectList)ViewData["Submarkets"]).Items, "(none)") %>DropDownList prende IEnumerable<SelectListItem>.
LukLed

@LukLed - è proprio così che alla fine ho trovato la fonte dell'errore :) così come le informazioni da alcuni altri post! Grazie
Jimbo

<%= Html.DropDownList("submarket_0", ViewData["Submarkets"] as IEnumerable<SelectListItem>, "(none)") %>
Arvis

Ho riscontrato questo oggi e ho trovato che il secondo argomento nel mio helper DropDownList era nullo, secondo la scoperta di seguito da @jonathansewell.
Ken Palmer

Risposte:


79

Ok, quindi la risposta è stata derivata da altri post su questo problema ed è:

Se il tuo ViewDatacontiene un SelectListcon lo stesso nome del tuo DropDownListie "submarket_0", l'helper Html popolerà automaticamente il tuo DropDownListcon quei dati se non specifichi il secondo parametro che in questo caso è la SelectList di origine.

Quello che è successo con il mio errore è stato:

Poiché la tabella contenente gli elenchi a discesa era in una vista parziale ed ViewDataera stata modificata e non conteneva più il SelectListriferimento, HtmlHelper(invece di generare un errore) ha cercato di trovare il SelectList chiamato "submarket_0" nel ViewData (GRRRR! !!) che ANCORA non riusciva a trovare, e quindi ha generato un errore su questo :)

Per favore correggimi se sbaglio


104
Ho ricevuto questo errore perché la mia raccolta di SelectListItems per l'elenco a discesa era nulla, che è lo stesso problema che hai avuto penso.
Jonathan Sewell

6
Per gli altri che si trovano ad affrontare questo problema, racchiudi temporaneamente il tuo elenco a discesa con un controllo nullo, ad esempio @if (ViewData ["Submarkets"]! = Null). Se la visualizzazione viene quindi visualizzata senza generare un errore (e senza l'elenco a discesa), avrai identificato il tuo problema. L'errore "nessun elemento di dati di visualizzazione" è molto fuorviante in questo caso.
GDB

Mi sono imbattuto in questo utilizzando un file Ajax.ActionLink. Basta aggiungere il SelectList Geta ActionMethodche contiene la chiamata Ajax.
puzza il

Sì! Avevo cambiato il nome dell'elenco che stavo passando a ViewData dal controller e non l'avevo cambiato nella vista. Questo è un messaggio di errore davvero terribilmente confuso!
neminem

1
@JonathanSewell grazie, grazie, grazie! Questo era il mio problema esatto.
johnw182

29

Vecchia domanda, ma ecco un'altra spiegazione del problema. Riceverai questo errore anche se hai visualizzazioni fortemente digitate e non stai utilizzando ViewData per creare il tuo elenco a discesa. Il motivo dell'errore può diventare chiaro quando guardi l' origine 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;
}

Quindi se hai qualcosa come:

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

Ed Model.DropDownDataè nullo, MVC cerca in ViewData qualcosa di denominato MyListe genera un errore se non è presente alcun oggetto in ViewData con quel nome.


1
Ciao, anche questo è un mio problema, cosa facciamo se la lista è nulla! puoi suggerirmi qualcosa,
trasformatore

4
@transformer La cosa più semplice da fare sarebbe impostare Model.DropDownData su un elenco vuoto invece che su null. Se ciò non è possibile, è possibile modificare il markup del rasoio per verificare se l'elenco è nullo e, in tal caso, eseguire il rendering di un elenco di selezione vuoto.
hawkke

15

Ho avuto lo stesso errore, penso che il problema sia che il testo dell'errore è confuso , perché fornisce un nome di chiave falso.

Nel tuo caso dovrebbe dire "Non c'è nessun elemento ViewData di tipo 'IEnumerable' che ha la chiave" Submarkets "".

Il mio errore era un errore di ortografia nel codice di visualizzazione (i tuoi "Sottomercati"), ma il testo dell'errore mi ha fatto impazzire.

Pubblico questa risposta perché voglio dire alle persone che cercano questo errore, come me, che il problema è che non sta trovando IENumerable, ma nella var che dovrebbe cercarlo ("Submarkets" in questo caso), non in quello mostrato per errore ("submarket_0") .

La risposta accettata è molto interessante, ma come hai detto la convenzione viene applicata se non specifichi il 2 ° parametro, in questo caso è stato specificato, ma la var non è stata trovata (nel tuo caso perchè il viewdata non lo aveva, nel mio caso perchè Ho scritto male il nome var)

Spero che sia di aiuto!


9

Il problema è dovuto al fatto che il postback si verifica al clic sul pulsante di invio. Quindi, durante la pubblicazione dei dati durante l'invio, fai di nuovo clic su scrivi prima di tornare Visualizza ()

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

3

Controlla lo spazio dei nomi.

È possibile assegnare System.Web.Webpages.Html.SelectListItem nel controller, invece di System.Web.Mvc.SelectListItem .


1

Anche questo va bene; Ad esempio:
==> Nel file "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();
}

==> Nel file di visualizzazione (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>

Ora se rimuoviamo questa affermazione:

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

dal retro della seguente dichiarazione (nel nostro controller):

return View();

vedremo questo errore:

Non sono presenti elementi ViewData di tipo "IEnumerable" con la chiave "OperatorId".

* Quindi assicurati dell'esistenza di queste affermazioni. *


0

Per me, il problema che ha causato questo errore si è verificato durante il salvataggio di una nuova riga nel database, ma un campo era nullo. Nella struttura della tabella del database, quel campo NON è NULL. Quindi, quando ho provato a salvare una nuova riga con un valore nullo per il campo non nullo, Visual Studio ha generato questo errore. Pertanto, mi sono assicurato che al campo fosse assegnato un valore e il problema è stato risolto.


0

Nel mio caso, ho scoperto di aver impostato erroneamente il metodo di pubblicazione come privato. dopo aver cambiato privato in pubblico.

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

cambia in

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

Ora funziona bene.


0

La causa non è contraria alla sintassi piuttosto che all'uso inappropriato degli oggetti. Il ciclo di vita degli oggetti in ViewData, ViewBag e View Life Cycle è più breve che nella sessione. I dati definiti nei form andranno persi dopo una richiesta-risposta (se si tenta di accedere dopo una richiesta-risposta, si otterranno delle eccezioni). Quindi i primi sono appropriati per il passaggio dei dati tra View e Controller mentre i secondi per la memorizzazione dei dati temporanei. I dati temporanei dovrebbero essere archiviati nella sessione in modo che sia possibile accedervi molte volte.


-1

Nel mio caso c'è stato un conflitto negli spazi dei nomi, ho:

using System.Web.Mvc;

e

using System.Collections.Generic;

Voglio usare esplicitamente quello Mvc quindi l'ho dichiarato come:

new System.Web.Mvc.SelectList(...)

1
A meno che i miei occhi mi ingannano, non c'è SelectListin System.Collections.Generic.
Erik Philips
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.