รายการ ViewData ที่มีคีย์ 'MY KEY' เป็นประเภท 'System.String' แต่ต้องเป็นประเภท 'IEnumerable <SelectListItem>


142

ฉันพยายามเติมรายการแบบหล่นลงจากฐานข้อมูลที่แมปกับ Linq-2-SQL โดยใช้ ASP.NET MVC 2 และรับข้อผิดพลาดนี้ต่อไป

ฉันสับสนมากเพราะฉันประกาศตัวแปรประเภทหนึ่งIEnumerable<SelectListItem>ในบรรทัดที่สอง แต่ข้อผิดพลาดทำให้ฉันคิดว่านี่ไม่ใช่กรณี ฉันรู้สึกว่าสิ่งนี้ควรจะง่ายมาก แต่ฉันกำลังลำบาก ความช่วยเหลือใด ๆ ที่ชื่นชม

นี่คือบิตที่น่าสนใจของคอนโทรลเลอร์ของฉัน:

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

และนี่คือบิตที่น่าสนใจในมุมมองของฉัน:

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

นี่คือการกระทำ POST เมื่อส่งแบบฟอร์ม

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

ขอบคุณ


1
รายการแบบเลื่อนลงจะปรากฏขึ้นในมุมมองได้ดี มันเติมจากฐานข้อมูลตามที่ควร แต่เมื่อฉันโพสต์แบบฟอร์มที่ฉันได้รับข้อผิดพลาดเหล่านี้
JBibbs

6
สรุปคำตอบที่ยอมรับ: ตรวจสอบให้แน่ใจว่าคุณเติมรายการทั้งในการดำเนินการรับและโพสต์ของตัวควบคุมของคุณ มันง่ายที่จะลืมที่จะทำสิ่งนี้และจากนั้นก็เสียเวลาค้นหาข้อผิดพลาดที่ซับซ้อนมากขึ้น
Adam Tolley

คำตอบ:


208

ฉันมีปัญหาเดียวกันและในที่สุดฉันก็ได้รับคำตอบ ...

ปัญหาคือว่าในการดำเนินการ POST หลังจากส่งแบบฟอร์ม ModelState ไม่ถูกต้องหรือกำลังตรวจจับข้อผิดพลาดในการลอง / จับดังนั้นมุมมองจะถูกส่งกลับ แต่คราวนี้มุมมองยังไม่ViewData["basetype"]ได้ตั้งค่าอย่างถูกต้อง

คุณจำเป็นต้องเติมข้อมูลอีกครั้งอาจใช้รหัสเดิมที่เคยใช้มาก่อนดังนั้นให้ทำสิ่งนี้ซ้ำ:

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)ใน[HttpPost]วิธีการ

ตรงนี้จะแก้ปัญหาของคุณ:

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

ฉันรู้ว่าคำถามนี้เก่ามาก แต่ฉันมาที่นี่วันนี้ด้วยปัญหาเดียวกันดังนั้นคนอื่น ๆ จะมาที่นี่ในภายหลัง ...


8
+1 สำหรับ "เติมใหม่อีกครั้ง" ... ฉันมีระบบที่แข็งแกร่งพอสมควรสำหรับการสร้างแบบจำลองมุมมองของฉัน แต่ฉันลืมที่จะเรียกมันอย่างสมบูรณ์ ดังนั้นทรัพย์สินจึงไม่ได้รับการเติมและฉันได้รับข้อความ (ค่อนข้างคลุมเครือ) ไม่ว่าฉันจะพยายามทำอะไร
Tim Medora

8
หากคุณได้รับก่อนโพสต์นี้เป็นเพราะไม่มีสิ่งใดใน SelectList เพียงแค่พบสิ่งนั้น
มาร์ติน

1
+1 เพราะฉันตั้งค่า ViewBag ของฉันในวิธีการทำดัชนีเมื่อฉันเรียก Html.Action ไปยังวิธีการดำเนินการอื่น !!
SwampyFox

ขอบคุณ มันคงจะดีถ้ามันถูกเก็บรักษาไว้ แต่ฉันคิดว่ามันคงไม่ใช่ MVC "ทาง"
Casey

หากรูปแบบที่ได้รับไม่ถูกต้องแล้วฉันมาข้อมูลที่ส่งโดยผู้ใช้จะถูกบันทึกไว้ในฐานข้อมูลหรือไม่ ฉันกำลังเผชิญกับปัญหาเดียวกัน ฉันเป็นมือใหม่ แก้ไขฉันถ้าฉันผิด
Koushik Saha

87

คุณจะได้รับข้อผิดพลาดนี้หาก SelectList เป็นโมฆะ


3
ใช่นี่เป็นข้อผิดพลาดทั่วไป / การกำกับดูแลเมื่อคุณตั้งค่า SelectList บน GET แล้ว postback ไปที่การกระทำ POST (เห็นได้ชัด) ที่มีการModelState.IsValid==falseส่งคืนโมเดลreturn View(model) แต่อย่า Repopulate แหล่ง SelectList ของคุณก่อนที่จะกลับมาจาก POST เนื่องจากไม่มี ViewState ala WebForms จึงไม่มีซอร์สสำหรับ@Html.DropDownผู้ช่วยในการสร้างส่วนที่เลือกด้วย คุณต้องเติมรายการแหล่งที่มาทุกครั้งที่คุณส่งคืนมุมมองไปยังไคลเอ็นต์ไม่ใช่เฉพาะใน GET
rism

ใช่นี่เป็นปัญหาของฉัน ลืมเติมรายการที่เลือกในการรับสาย ข้อผิดพลาดที่ทำให้เข้าใจผิดมาก โพสต์ยอดเยี่ยม
แมตต์


1

สำหรับผู้อ่านในอนาคตหากคุณใช้มีดโกนให้ลองเปลี่ยนประเภทของรายการที่เลือกจากรายการเป็น IEnumerable

จาก

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

ถึง

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

0

ลองเพิ่มสตริงสำหรับชื่อของรายการดรอปดาวน์ของคุณเป็นพารามิเตอร์แรกและนำไอเท็มออกจาก viewdata ของคุณ:

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

ต่อไปนี้เป็นวิธีส่วนขยายที่คุณสามารถใช้เพื่อให้รายการแบบหล่นลงถูกตั้งค่าในลักษณะที่คล้ายคลึงกับวิธีการควบคุมอื่น ๆ ของคุณ:

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

ตัวอย่างเช่น

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

0

คุณกำลังตั้งค่าคอลเลกชันเป็นรายการในพจนานุกรม ViewData และพยายามเรียกคืนเป็นคุณสมบัติในโมเดล การแก้ไขอย่างง่ายจะเป็นการอ้างอิงแบบเดียวกับที่คุณตั้งไว้:

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

อีกวิธีหนึ่งรหัสด้านล่างใช้มุมมองที่พิมพ์อย่างยิ่ง:

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

จากนั้นในมุมมองที่พิมพ์อย่างมากของคุณ:

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

ฉันลองใช้รหัสในตัวอย่าง "การแก้ไขแบบง่าย" ของคุณและได้รับข้อผิดพลาดเดียวกัน ฉันควรจะกล่าวว่ารายการแบบเลื่อนลงจะปรากฏในมุมมองตกลง แต่ฉันได้รับข้อผิดพลาดนี้เมื่อฉันส่งแบบฟอร์ม
JBibbs

คุณสามารถโพสต์รหัสสำหรับ Controller Action ที่จัดการการส่งแบบฟอร์มได้หรือไม่?
Igor Zevaka

แน่นอนว่าฉันจะเพิ่มเข้าไปในโพสต์ดั้งเดิม ขอบคุณสำหรับความช่วยเหลือของคุณ
JBibbs

0

หากคุณใช้Html.DropDownList()วิธีการ - ข้อผิดพลาดเดียวกันอาจเกิดขึ้นได้หากรายการ ViewData / Viewbag ของคุณไม่ได้ตั้งค่าตามที่ @Peto ตอบ

แต่มันอาจไม่ถูกตั้งค่าในกรณีที่รายการควบคุมถูกต้อง แต่ในมุมมองหลักคุณใช้การเรียก viw บางส่วนด้วยค่า ViewDataDictionary ใหม่

หากคุณมี@Html.Partial("Partianame", Model,new ViewDataDictionary() { /* ... */ })มุมมองบางส่วนของคุณจะไม่เห็นViewDataและViewBagข้อมูลให้ลบnew ViewDataDictionary()พารามิเตอร์


0

สำหรับผู้อ่านในอนาคต

ฉันเจอปัญหาในวันนี้และไม่สามารถแก้ไขได้ มันกลายเป็นว่าง่ายจริงๆหลังจากทั้งหมด ฉันทำงานกับตาราง + มุมมอง เมื่อฉันอัปเดตตาราง (เพิ่มไม่กี่ colums) ฉันลืมอัปเดต (ดรอปและสร้างใหม่) มุมมองซึ่งทำให้เกิดปัญหากับฉัน หวังว่าจะช่วยใครซักคน


0

วันนี้ฉันมีข้อผิดพลาดเหมือนกันและวิธีแก้ปัญหาของฉันคือทำให้แบบจำลอง "ถูกต้อง"

ในกรณีของฉันหลังจากผู้ใช้ส่งโดยคลิกที่ "บันทึก" ฉันได้รับสถานะรุ่น: ไม่ถูกต้องถ้าผู้ใช้ใน "0" แต่รัฐรุ่นจะถูกต้องหากผู้ใช้ใน "0.0"

ดังนั้นฉันจึงแทนที่ "IsValid" วิธีการคืนจริงแม้ผู้ใช้รหัส "0"

หวังว่ามันจะช่วย

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.