Das ViewData-Element mit dem Schlüssel 'MY KEY' ist vom Typ 'System.String', muss jedoch vom Typ 'IEnumerable <SelectListItem>' sein.

142

Ich versuche, eine Dropdown-Liste aus einer mit Linq-2-SQL zugeordneten Datenbank mit ASP.NET MVC 2 zu füllen und erhalte weiterhin diesen Fehler.

Ich bin so verwirrt, weil ich IEnumerable<SelectListItem>in der zweiten Zeile eine Variable vom Typ deklariere , aber der Fehler lässt mich denken, dass dies nicht der Fall ist. Ich denke, das sollte sehr einfach sein, aber ich kämpfe. Jede Hilfe wird geschätzt.

Hier sind die interessanten Teile meines Controllers:

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

Und hier sind die interessanten Teile meiner Ansicht:

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

Hier ist die POST-Aktion beim Absenden des Formulars

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

Vielen Dank.

JBibbs
quelle
1
Die Dropdown-Liste erscheint in der Ansicht einwandfrei. Es wird wie gewünscht aus der Datenbank ausgefüllt, aber wenn ich das Formular poste, werden diese Fehler angezeigt.
JBibbs
6
Zusammenfassung der akzeptierten Antwort: Stellen Sie sicher, dass Sie die Liste sowohl in den Get- als auch in den Post-Aktionen Ihres Controllers ausfüllen. Es ist leicht zu vergessen, dies zu tun, und dann Zeit damit zu verschwenden, nach einem komplizierteren Fehler zu suchen.
Adam Tolley

Antworten:

208

Ich hatte das gleiche Problem und endlich bekam ich die Antwort ...

Das Problem besteht darin, dass in der POST-Aktion nach dem Senden des Formulars der ModelState ungültig ist oder ein Fehler in try / catch auftritt, sodass die Ansicht zurückgegeben wird. Diesmal ist die Ansicht jedoch nicht ViewData["basetype"]richtig eingestellt.

Sie müssen es erneut füllen, wahrscheinlich mit demselben Code, der zuvor verwendet wurde. Wiederholen Sie diesen Vorgang:

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

vor dem return View(meal)in der [HttpPost]Methode.

Genau das wird Ihr Problem lösen:

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

Ich weiß, dass diese Frage sehr alt ist, aber ich bin heute mit dem gleichen Problem hierher gekommen, so dass andere später hierher kommen könnten ...

Peto
quelle
8
+1 für "wieder auffüllen" ... Ich habe ein ziemlich robustes System zum Erstellen meiner Ansichtsmodelle, aber ich hatte völlig vergessen, es zu nennen. Daher war die Immobilie nicht besiedelt und ich erhielt diese (ziemlich mehrdeutige) Nachricht, egal was ich versuchte.
Tim Medora
8
Wenn Sie dies VOR einem Beitrag erhalten, liegt es daran, dass die SelectList nichts enthält, sondern nur diesen gefunden hat.
Martin
1
+1 Weil ich mein ViewBag in der Index-Methode festgelegt habe, als ich wirklich eine Html.Action für eine andere Aktionsmethode aufgerufen habe !!
SwampyFox
Vielen Dank. Es wäre schön, wenn es nur erhalten bleiben würde, aber ich nehme an, das wäre nicht der MVC "Weg".
Casey
Wenn das Modell ungültig wird, werden die vom Benutzer übermittelten Daten in der Datenbank gespeichert. Ich stehe auch vor dem gleichen Problem. Ich bin ein Neuling. korrigiere mich, wenn ich falsch liege.
Koushik Saha
87

Sie erhalten diesen Fehler, wenn die SelectList null ist.

Ben
quelle
3
Ja, dies ist ein häufiger Fehler / Fehler, wenn Sie die SelectList auf einem GET einrichten und dann (offensichtlich) zu einer POST-Aktion zurückkehren, die eine hat, ModelState.IsValid==falsesodass Sie das Modell zurückgeben, return View(model) aber Ihre SelectList-Quelle nicht neu füllen, bevor Sie vom POST zurückkehren. Da es keinen ViewState ala WebForms gibt, gibt es keine Quelle für den @Html.DropDownHelfer, mit der er die Auswahl neu erstellen kann . Sie müssen diese Quellliste jedes Mal füllen, wenn Sie die Ansicht nicht nur auf dem GET an den Client zurückgeben.
Risma
Ja, das war mein Problem. Ich habe vergessen, die selectList beim Aufruf von get aufzufüllen. Sehr irreführender Fehler. Guter Eintrag.
Matt
1

Wenn Sie für zukünftige Leser Rasiermesser verwenden, versuchen Sie, den Typ des Auswahllistenelements von Liste in IEnumerable zu ändern.

Von

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

Zu

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

Fügen Sie als ersten Parameter eine Zeichenfolge für den Namen Ihrer Dropdown-Liste hinzu und entfernen Sie das Element aus Ihren Ansichtsdaten:

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

Hier ist auch eine Erweiterungsmethode, die Sie verwenden können, damit die Dropdown-Liste in einem ähnlichen Stil eingerichtet wird wie bei Ihren anderen Steuerelementen:

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

Beispielsweise

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

Sie legen die Sammlung als Element im ViewData-Wörterbuch fest und versuchen, sie als Eigenschaft für das Modell abzurufen. Eine einfache Lösung wäre, auf dieselbe Weise zu verweisen, wie Sie es festgelegt haben:

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

Alternativ verwendet der folgende Code eine stark typisierte Ansicht:

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

Dann in Ihrer stark getippten Ansicht:

    <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
quelle
Ich habe versucht, den Code in Ihrem Beispiel für "einfache Korrektur" zu verwenden, und habe den gleichen Fehler erhalten. Ich hätte erwähnen sollen, dass die Dropdown-Liste in der Ansicht OK angezeigt wird, aber ich erhalte diese Fehlermeldung, wenn ich das Formular abschicke.
JBibbs
Können Sie den Code für die Controller-Aktion veröffentlichen, die die Formularübermittlung behandelt?
Igor Zevaka
Klar, ich werde es dem ursprünglichen Beitrag hinzufügen. Vielen Dank für Ihre bisherige Hilfe.
JBibbs
0

Wenn Sie die Html.DropDownList()Methode verwenden, kann derselbe Fehler auftreten, wenn Ihr ViewData / Viewbag-Element nicht festgelegt ist, wie @Peto geantwortet hat.

Es kann jedoch sein, dass es nicht richtig eingestellt ist, wenn das Controller-Set-Element korrekt eingestellt ist. In der Hauptansicht verwenden Sie jedoch einen partiellen viw-Aufruf mit neuen ViewDataDictionary-Werten.

Wenn Sie @Html.Partial("Partianame", Model,new ViewDataDictionary() { /* ... */ })dann haben, wird Ihre Teilansicht nicht sehen ViewDataund ViewBagDaten, entfernen Sie new ViewDataDictionary()Parameter

Evgeny Levin
quelle
0

An zukünftige Leser,

Ich bin heute auf das Problem gestoßen und konnte es nicht beheben. Es wurde schließlich wirklich einfach. Ich habe mit einer Tabelle + Ansicht gearbeitet. Als ich die Tabelle aktualisiert habe (einige Spalten hinzugefügt), habe ich vergessen, die Ansicht zu aktualisieren (löschen und neu erstellen), was das Problem für mich verursacht hat. Hoffe es hilft jemandem.

Mariano Gianni
quelle
0

Ich habe heute den gleichen Fehler erhalten und meine Lösung besteht darin, das Modell "gültig" zu machen.

In meinem Fall wurde nach dem Senden durch den Benutzer durch Klicken auf "Speichern" der Modellstatus angezeigt: ungültig, wenn der Benutzer "0" eingibt, aber der Modellstatus ist gültig, wenn der Benutzer "0.0" eingibt.

Also überschreibe ich die "IsValid" -Methode, um true zurückzugeben, auch wenn der Benutzer "0" eingibt.

Ich hoffe es hilft.

Ray Chung
quelle