Mục ViewData có khóa 'MY KEY' thuộc loại 'System.String' nhưng phải là loại 'IEnumerable <SelectListItem>'


142

Tôi đang cố gắng đưa ra một danh sách thả xuống từ cơ sở dữ liệu được ánh xạ với Linq-2-SQL, sử dụng ASP.NET MVC 2 và tiếp tục gặp lỗi này.

Tôi rất bối rối vì tôi khai báo một biến kiểu IEnumerable<SelectListItem>trên dòng thứ hai, nhưng lỗi này khiến tôi nghĩ rằng đây không phải là trường hợp. Tôi cảm thấy như thế này rất đơn giản, nhưng tôi đang vật lộn. Bất kỳ trợ giúp được đánh giá cao.

Dưới đây là các bit thú vị của bộ điều khiển của tôi:

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

Và đây là những điều thú vị trong quan điểm của tôi:

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

Đây là hành động POST khi gửi Biểu mẫu

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

Cảm ơn.


1
Danh sách thả xuống xuất hiện trong chế độ xem tốt. Nó xuất hiện từ cơ sở dữ liệu như bình thường, nhưng đó là khi tôi đăng mẫu đơn mà tôi gặp phải những lỗi này.
JBibbs

6
Tóm tắt câu trả lời được chấp nhận: Đảm bảo bạn điền vào danh sách trong cả hành động nhận và đăng của bộ điều khiển. Thật dễ dàng để quên làm điều này, và sau đó kết thúc lãng phí thời gian để tìm kiếm một lỗi phức tạp hơn.
Adam Tolley

Câu trả lời:


208

Tôi đã có cùng một vấn đề, và cuối cùng tôi đã có câu trả lời ...

Vấn đề là trong hành động POST, sau khi gửi biểu mẫu, ModelState không hợp lệ hoặc nó bắt lỗi trong thử / bắt, do đó, Chế độ xem được trả về. Nhưng lần này, Chế độ xem chưa ViewData["basetype"]được đặt chính xác.

Bạn cần phải nhập lại nó, có thể với cùng mã được sử dụng trước đó, vì vậy hãy lặp lại điều này:

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

trước return View(meal)trong [HttpPost]phương thức.

chính xác điều này sẽ giải quyết vấn đề của bạn:

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

Tôi biết câu hỏi này rất cũ, nhưng tôi đã đến đây hôm nay với cùng một vấn đề, vì vậy những người khác có thể đến đây sau ...


8
+1 cho "điền lại lần nữa" ... Tôi có một hệ thống khá mạnh mẽ để soạn thảo các mô hình xem của tôi, nhưng tôi đã hoàn toàn quên gọi nó. Do đó, tài sản không được điền và tôi nhận được tin nhắn (khá mơ hồ) này bất kể tôi đã thử gì.
Tim Medora

8
nếu bạn nhận được điều này TRƯỚC một bài đăng, thì đó là vì không có gì trong Danh sách chọn, chỉ cần tìm thấy bài đăng đó.
Martin

1
+1 Bởi vì tôi đã đặt ViewBag của mình trong phương thức Index khi tôi thực sự gọi một Html. Chuyển sang một Phương thức hành động khác !!
SwampyFox

Cảm ơn. Sẽ thật tuyệt nếu nó chỉ được bảo tồn nhưng tôi cho rằng đó không phải là "cách" của MVC.
Casey

Nếu mô hình đang bị vô hiệu thì tôi đến dữ liệu do người dùng gửi sẽ được lưu trong db? tôi cũng đang đối mặt với vấn đề tương tự tôi là người mới đúng nếu tôi đã sai lầm.
Koushik Saha

87

Bạn sẽ nhận được lỗi này nếu Chọn danh sách là null.


3
Đúng, đây là một lỗi / giám sát phổ biến khi bạn thiết lập Chọn Danh sách trên GET sau đó gửi lại cho một hành động POST (rõ ràng) có một ModelState.IsValid==falsemô hình để bạn trả lại mô hình return View(model) nhưng không lặp lại nguồn Chọn của bạn trước khi quay lại từ POST. Vì không có ViewFate ala WebForms, nên không có nguồn nào để người @Html.DropDowntrợ giúp xây dựng lại lựa chọn với. Bạn phải điền danh sách nguồn đó MERYI lần bạn trả lại chế độ xem cho khách hàng không chỉ trên GET.
nghĩa

vâng đây là vấn đề của tôi. Quên để điền danh sách select vào cuộc gọi nhận. Lỗi rất sai. Bài đăng tuyệt vời.
Matt


1

Đối với độc giả trong tương lai, nếu bạn đang sử dụng dao cạo, hãy thử thay đổi loại mục danh sách chọn từ Danh sách sang IEnumerable.

Từ

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

Đến

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

0

Hãy thử thêm một chuỗi cho tên của danh sách thả xuống của bạn làm tham số đầu tiên và đưa mục ra khỏi chế độ xem của bạn:

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

Đây cũng là một phương thức mở rộng mà bạn có thể sử dụng để danh sách thả xuống được thiết lập theo kiểu tương tự như cách bạn đã thực hiện các điều khiển khác của mình:

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

Ví dụ

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

0

Bạn đang đặt bộ sưu tập dưới dạng một mục trong từ điển ViewData và cố gắng truy xuất lại nó làm tài sản trên mô hình. Một sửa chữa đơn giản sẽ là tham chiếu nó giống như cách bạn đặt nó:

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

Ngoài ra, đoạn mã dưới đây sử dụng chế độ xem được gõ mạnh:

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

Sau đó, trong chế độ xem được đánh máy mạnh mẽ của bạn:

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

Tôi đã thử sử dụng mã trong ví dụ "sửa lỗi đơn giản" của bạn và gặp lỗi tương tự. Tôi nên đã đề cập rằng danh sách thả xuống cư trú trong Chế độ xem ok, nhưng tôi gặp lỗi này khi gửi biểu mẫu.
JBibbs

Bạn có thể đăng mã cho Bộ điều khiển hành động xử lý việc gửi biểu mẫu không?
Igor Zevaka

Chắc chắn, tôi sẽ thêm nó vào bài viết gốc. Cảm ơn vì sự giúp đỡ của bạn.
JBibbs

0

Nếu bạn dùng Html.DropDownList() phương pháp - lỗi tương tự có thể xảy ra, nếu mục ViewData / Viewbag của bạn không được đặt, như @Peto đã trả lời.

Nhưng nó có thể không được đặt trong trường hợp bộ điều khiển đặt mục chính xác, nhưng trong chế độ xem chính, bạn sử dụng cuộc gọi viw một phần với các giá trị ViewDataDipedia mới.

nếu bạn có @Html.Partial("Partianame", Model,new ViewDataDictionary() { /* ... */ })thì chế độ xem một phần của bạn sẽ không nhìn thấy ViewDataViewBagdữ liệu, hãy xóa new ViewDataDictionary()tham số


0

Để độc giả tương lai,

Tôi đã gặp vấn đề ngày hôm nay và không thể khắc phục nó. Rốt cuộc nó trở nên thực sự đơn giản. Tôi đã làm việc với một bảng + xem. Khi tôi cập nhật bảng (thêm một vài colums), tôi quên cập nhật (thả và tạo lại) chế độ xem, điều này gây ra sự cố cho tôi. Hy vọng nó sẽ giúp được ai đó.


0

Tôi đã gặp lỗi tương tự ngày hôm nay và giải pháp của tôi là làm cho mô hình "hợp lệ".

Trong trường hợp của tôi, sau khi người dùng gửi bằng cách nhấp vào "lưu", tôi đã nhận trạng thái mô hình: không hợp lệ nếu người dùng nhập "0", nhưng trạng thái mô hình sẽ hợp lệ nếu người dùng nhập "0,0".

Vì vậy, tôi ghi đè phương thức "IsValid" để trả về đúng ngay cả khóa người dùng "0".

Hy vọng nó giúp.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.