Item ViewData yang memiliki kunci 'MY KEY' adalah tipe 'System.String' tetapi harus tipe 'IEnumerable <SelectListItem>'

142

Saya mencoba mengisi daftar dropdown dari database yang dipetakan dengan Linq-2-SQL, menggunakan ASP.NET MVC 2, dan terus mendapatkan kesalahan ini.

Saya sangat bingung karena saya mendeklarasikan variabel tipe IEnumerable<SelectListItem>pada baris kedua, tetapi kesalahan membuat saya berpikir ini tidak terjadi. Saya merasa ini harus sangat sederhana, tetapi saya berjuang. Bantuan apa pun dihargai.

Berikut ini bagian-bagian menarik dari pengontrol saya:

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

Dan inilah bagian-bagian menarik dari pandangan saya:

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

Ini adalah tindakan POST ketika mengirimkan Formulir

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

Terima kasih.

JBibbs
sumber
1
Daftar dropdown muncul dalam tampilan baik-baik saja. Ini mengisi dari database sebagaimana mestinya, tetapi ketika saya memposting formulir saya mendapatkan kesalahan ini.
JBibbs
6
Ringkasan jawaban yang diterima: Pastikan Anda mengisi daftar di kedua tindakan mendapatkan dan memposting controller Anda. Sangat mudah untuk melupakan hal ini, dan akhirnya membuang waktu untuk mencari bug yang lebih rumit.
Adam Tolley

Jawaban:

208

Saya memiliki masalah yang sama, dan akhirnya saya mendapat jawabannya ...

Masalahnya adalah bahwa dalam tindakan POST, setelah mengirimkan formulir, ModelState tidak valid, atau menangkap kesalahan dalam coba / tangkap, sehingga tampilan dikembalikan. Tapi kali ini tampilan belum ViewData["basetype"]diatur dengan benar.

Anda perlu mengisinya lagi, mungkin dengan kode yang sama yang digunakan sebelumnya, jadi ulangi ini:

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

sebelum return View(meal)dalam [HttpPost]metode.

tepatnya ini akan menyelesaikan masalah Anda:

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

Saya tahu pertanyaan ini sudah sangat lama, tetapi saya datang ke sini hari ini dengan masalah yang sama, sehingga orang lain bisa datang ke sini nanti ...

Peto
sumber
8
+1 untuk "mengisi lagi" ... Saya memiliki sistem yang cukup kuat untuk menyusun model tampilan saya, tetapi saya benar-benar lupa menyebutnya. Dengan demikian, properti tidak terisi dan saya menerima pesan ini (agak ambigu) tidak peduli apa yang saya coba.
Tim Medora
8
jika Anda mendapatkan ini SEBELUM posting, itu karena tidak ada apa pun di SelectList, hanya menemukan yang itu.
Martin
1
+1 Karena saya sedang mengatur ViewBag saya di metode Indeks ketika saya benar-benar memanggil Html.Action ke Metode Tindakan lain !!
SwampyFox
Terima kasih. Akan lebih baik jika itu hanya diawetkan tapi saya kira itu tidak akan menjadi "jalan" MVC.
Casey
jika model semakin tidak valid maka saya datang data yang dikirimkan oleh pengguna akan disimpan dalam db? saya juga menghadapi masalah yang sama. saya seorang pemula. koreksi saya jika saya salah.
Koushik Saha
87

Anda akan menerima kesalahan ini jika SelectList adalah nol.

Ben
sumber
3
Yap, ini adalah kesalahan umum / kekeliruan ketika Anda mengatur SelectList pada GET kemudian postback ke tindakan POST (jelas) yang memiliki ModelState.IsValid==falsesehingga Anda mengembalikan model return View(model) tetapi tidak mengisi kembali sumber SelectList Anda sebelum kembali dari POST. Karena tidak ada ViewState ala WebForms, tidak ada sumber bagi @Html.DropDownhelper untuk membangun kembali yang terpilih. Anda harus mengisi daftar sumber itu SETIAP kali Anda mengembalikan tampilan ke klien tidak hanya di GET.
rism
ya ini masalah saya. Lupa mengisi daftar pilih pada panggilan penerimaan. Kesalahan yang sangat menyesatkan. Pos yang bagus.
Matt
1

Untuk pembaca masa depan, jika Anda menggunakan pisau cukur, cobalah untuk mengubah jenis item daftar pilih dari Daftar ke IEnumerable.

Dari

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

Untuk

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

Coba tambahkan string untuk nama daftar dropdown Anda sebagai parameter pertama, dan keluarkan item dari viewdata Anda:

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

Berikut ini juga metode ekstensi yang dapat Anda gunakan sehingga daftar dropdown diatur dalam gaya yang mirip dengan cara Anda melakukan kontrol lainnya:

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

Sebagai contoh

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

Anda mengatur koleksi sebagai item dalam kamus ViewData dan mencoba untuk mengambilnya sebagai properti pada model. Perbaikan sederhana adalah dengan merujuknya dengan cara yang sama seperti Anda mengaturnya:

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

Atau, kode di bawah ini menggunakan tampilan yang sangat diketik:

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

Kemudian, dalam tampilan yang sangat Anda ketik:

    <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
sumber
Saya sudah mencoba menggunakan kode dalam contoh "perbaikan sederhana" Anda, dan mendapat kesalahan yang sama. Saya seharusnya menyebutkan bahwa daftar dropdown mengisi dalam tampilan ok, tapi saya mendapatkan kesalahan ini ketika saya mengirimkan formulir.
JBibbs
Bisakah Anda memposting kode untuk Aksi Pengendali yang menangani pengiriman formulir?
Igor Zevaka
Tentu, saya akan menambahkannya ke posting asli. Terima kasih atas bantuan Anda sejauh ini.
JBibbs
0

Jika Anda menggunakan Html.DropDownList()metode - kesalahan yang sama dapat terjadi, jika item ViewData / Viewbag Anda tidak disetel, seperti yang dijawab @Peto.

Tapi itu mungkin tidak diatur jika controller set item dengan benar, tetapi dalam tampilan utama Anda menggunakan panggilan viw parsial dengan nilai-nilai ViewDataDictionary baru.

jika sudah, @Html.Partial("Partianame", Model,new ViewDataDictionary() { /* ... */ })maka sebagian tampilan Anda tidak akan melihat ViewDatadan ViewBagdata, hapus new ViewDataDictionary()parameter

Evgeny Levin
sumber
0

Untuk pembaca masa depan,

Saya menemukan masalah hari ini dan tidak bisa memperbaikinya. Ternyata menjadi sangat sederhana. Saya bekerja dengan tampilan tabel +. Ketika saya memperbarui tabel (menambahkan beberapa kolom) saya lupa memperbarui (menjatuhkan dan membuat ulang) tampilan, yang menyebabkan masalah bagi saya. Semoga ini bisa membantu seseorang.

Mariano Gianni
sumber
0

Saya mendapat kesalahan yang sama hari ini dan solusi saya adalah membuat model "valid".

Dalam kasus saya, setelah pengguna mengirim dengan mengeklik "simpan", saya mendapat status model: tidak valid jika pengguna memasukkan "0", tetapi status model akan valid jika pengguna memasukkan "0,0".

Jadi saya mengganti metode "IsValid" untuk mengembalikan true bahkan pengguna key-in "0".

Semoga ini bisa membantu.

Ray Chung
sumber