L'elemento ViewData che ha la chiave 'MY KEY' è di tipo 'System.String' ma deve essere di tipo 'IEnumerable <SelectListItem>'


142

Sto cercando di popolare un elenco a discesa da un database mappato con Linq-2-SQL, utilizzando ASP.NET MVC 2, e continuo a ricevere questo errore.

Sono così confuso perché sto dichiarando una variabile di tipo IEnumerable<SelectListItem>sulla seconda riga, ma l'errore mi fa pensare che non sia così. Sento che questo dovrebbe essere molto semplice, ma sto lottando. Qualsiasi aiuto è apprezzato.

Ecco i bit interessanti del mio 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();
}

E qui ci sono le parti interessanti della mia visione:

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

Ecco l'azione POST al momento dell'invio del modulo

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

Grazie.


1
L'elenco a discesa appare nella vista bene. Si popola dal database come dovrebbe, ma è quando invio il modulo che ottengo questi errori.
JBibbs,

6
Riepilogo della risposta accettata: assicurati di compilare l'elenco in entrambe le azioni get e post del controller. È facile dimenticarsi di farlo, e quindi perdere tempo a cercare un bug più complicato.
Adam Tolley,

Risposte:


208

Ho avuto lo stesso problema e finalmente ho avuto la risposta ...

Il problema è che nell'azione POST, dopo aver inviato il modulo, ModelState non è valido o sta rilevando un errore in try / catch, quindi viene restituita la vista. Ma questa volta la vista non è ViewData["basetype"]impostata correttamente.

Devi popolarlo di nuovo, probabilmente con lo stesso codice usato in precedenza, quindi ripeti questo:

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

prima del return View(meal)nel [HttpPost]metodo.

esattamente questo risolverà il tuo 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);
    }
}

So che questa domanda è molto vecchia, ma sono venuto qui oggi con lo stesso problema, quindi altri potrebbero venire qui più tardi ...


8
+1 per "popolare di nuovo" ... Ho un sistema abbastanza robusto per comporre i miei modelli di vista, ma mi ero completamente dimenticato di chiamarlo. Pertanto, la proprietà non era popolata e ho ricevuto questo messaggio (piuttosto ambiguo), indipendentemente da ciò che ho provato.
Tim Medora,

8
se ricevi questo PRIMA di un post, è perché non c'è niente nella SelectList, ho appena trovato quello.
Martin,

1
+1 Perché stavo impostando il mio ViewBag nel metodo Index quando stavo davvero chiamando un HTML. Azione a un altro metodo di azione !!
SwampyFox,

Grazie. Sarebbe bello se fosse solo conservato, ma suppongo che non sarebbe il "modo" MVC.
Casey

se il modello sta ottenendo è invalidato allora vengo i dati inviati dall'utente verranno salvati nel db? anche io sto affrontando lo stesso problema. sono un novizio. correggimi se sbaglio.
Koushik Saha,

87

Riceverai questo errore se SelectList è null.


3
Sì, questo è un errore / supervisione comune quando si imposta SelectList su un GET, quindi si esegue il postback a un'azione POST (ovviamente) che ha un ModelState.IsValid==falsemodo per restituire il modello return View(model) ma non ripopolare l'origine SelectList prima di tornare dal POST. Dal momento che non è disponibile alcun modulo Web ViewState ala, non esiste alcuna fonte per l' @Html.DropDownhelper con cui ricostruire la selezione. Devi compilare l'elenco delle fonti ogni volta che restituisci la vista al client non solo sul GET.
rism

sì, questo era il mio problema. Hai dimenticato di popolare la selectList al momento della chiamata. Errore molto fuorviante. Ottimo post.
Matt,


1

Per i lettori futuri, se si utilizza il rasoio, provare a cambiare il tipo di elemento selectlist da Elenco a IEnumerable.

A partire dal

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

Per

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

0

Prova ad aggiungere una stringa per il nome del tuo elenco a discesa come primo parametro e estrai l'elemento dal tuo viewdata:

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

Ecco anche un metodo di estensione che puoi usare, quindi l'elenco a discesa è impostato in uno stile simile a quello che hai fatto con gli altri controlli:

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

Per esempio

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

0

Stai impostando la raccolta come un elemento nel dizionario ViewData e stai provando a recuperarla come proprietà sul modello. Una soluzione semplice sarebbe fare riferimento allo stesso modo in cui lo hai impostato:

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

In alternativa, il codice seguente utilizza una vista fortemente tipizzata:

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

Quindi, nella vista fortemente tipizzata:

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

Ho provato a utilizzare il codice nell'esempio "correzione semplice" e ho riscontrato lo stesso errore. Avrei dovuto menzionare che l'elenco a discesa viene popolato nella visualizzazione ok, ma quando si invia il modulo viene visualizzato questo errore.
JBibbs,

È possibile pubblicare il codice per l'azione del controller che gestisce l'invio del modulo?
Igor Zevaka,

Certo, lo aggiungerò al post originale. Grazie per il tuo aiuto finora.
JBibbs,

0

Se usi Html.DropDownList() metodo, potrebbe verificarsi lo stesso errore, se l'elemento ViewData / Viewbag non è impostato, come ha risposto @Peto.

Ma potrebbe non essere impostato nel caso in cui l'elemento set controller sia corretto, ma nella vista principale si utilizza una chiamata viw parziale con nuovi valori ViewDataDictionary.

se hai @Html.Partial("Partianame", Model,new ViewDataDictionary() { /* ... */ })quindi la vista parziale non vedrà ViewDatae ViewBagdati, rimuovere il new ViewDataDictionary()parametro


0

Ai futuri lettori,

Oggi ho riscontrato il problema e non sono riuscito a risolverlo. Dopotutto è diventato davvero semplice. Stavo lavorando con una tabella + vista. Quando ho aggiornato la tabella (aggiunto alcune colonne) ho dimenticato di aggiornare (rilasciare e ricreare) la vista, il che mi ha causato il problema. Spero che aiuti qualcuno.


0

Ho avuto lo stesso errore oggi e la mia soluzione è rendere il modello "valido".

Nel mio caso, dopo l'invio dell'utente facendo clic su "Salva", ho ottenuto lo stato del modello: non valido se l'utente digita "0", ma lo stato del modello sarà valido se l'utente digita "0.0".

Quindi ho la precedenza sul metodo "IsValid" per restituire la chiave utente "0".

Spero che sia d'aiuto.

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.