Елемент ViewData, який має ключ "МОЙ КЛЮЧ", має тип "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
Короткий зміст прийнятої відповіді: Переконайтеся, що ви заповнюєте список як в дістанні, так і після дії вашого контролера. Це легко забути зробити, а потім закінчити витрачати час на пошук складнішої помилки.
Адам Толлі

Відповіді:


208

У мене була така ж проблема, і нарешті я отримав відповідь ...

Проблема полягає в тому, що в дії POST після надсилання форми ModelState недійсний, або він виявляє помилку в спробі / catch, тому Вид повертається. Але цього разу Погляд не встановлений 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 для "знову заповнити його" ... У мене є досить надійна система для складання моїх моделей перегляду, але я зовсім забув її назвати. Таким чином, майно не було заселене, і я отримав це (досить неоднозначне) повідомлення незалежно від того, що я намагався.
Тім Медора

8
якщо ви отримаєте це ПЕРЕД дописом, це тому, що в SelectList немає нічого, щойно знайшли його.
Мартін

1
+1 Тому що я встановлював свій ViewBag методом Index, коли я дійсно викликав Html.Action до іншого методу дій !!
SwampyFox

Дякую. Було б добре, якби це було просто збережено, але я вважаю, що це був би не MVC "шлях".
Кейсі

якщо модель отримання буде визнана недійсною, то я прийду дані, подані користувачем, будуть збережені в db? Я також стикаюся з тією ж проблемою. я новачок. виправте мене, якщо я помиляюся.
Кушик Саха

87

Ви отримаєте цю помилку, якщо SelectList є нульовим.


3
Так, це звичайна помилка / нагляд, коли ви встановлюєте SelectList на GET, а потім відновлюєте до дії POST (очевидно), яка має ModelState.IsValid==falseтак, що ви повертаєте модель, return View(model) але не перенаселяйте джерело SelectList перед поверненням з POST. Оскільки немає ViewState ala WebForms, немає джерела для @Html.DropDownпомічника, щоб відновити вибір за допомогою. Ви повинні заповнити цей список джерел кожного разу, коли ви повернете представлення клієнту не лише в GET.
підйом

так, це було моєю проблемою. Забули заповнити список вибору під час отримання дзвінка. Дуже оманлива помилка. Чудовий пост.
Мет


1

Для майбутніх читачів, якщо ви використовуєте бритву, спробуйте змінити тип елемента вибору зі списку на IEnumerable.

З

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

До

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

0

Спробуйте додати рядок для імені вашого випадаючого списку в якості першого параметра і вийдіть елемент із своїх даних про перегляд:

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

Чи можете ви опублікувати код для дій контролера, який обробляє подання форми?
Ігор Зевака

Звичайно, я додам його до оригінальної публікації. Дякуємо за вашу допомогу.
JBibbs

0

Якщо ви використовуєте Html.DropDownList()метод - може виникнути та сама помилка, якщо елемент ViewData / Viewbag не встановлений, як @Peto відповів.

Але він може бути встановлений у разі неправильного встановлення елемента контролера, але в основному ви використовуєте частковий виклик viw з новими значеннями ViewDataDictionary.

якщо у вас @Html.Partial("Partianame", Model,new ViewDataDictionary() { /* ... */ })тоді ваш частковий вигляд не побачить ViewDataі не ViewBagвидалить дані, видаліть new ViewDataDictionary()параметр


0

Для майбутніх читачів,

Я зіткнувся з проблемою сьогодні і не зміг її вирішити. Зрештою, це виявилося дуже просто. Я працював із таблицею + видом. Коли я оновив таблицю (додав кілька стовпчиків), я забув оновити (відпустити та відтворити) подання, що спричинило проблему для мене. Сподіваюся, це комусь допоможе.


0

У мене сьогодні така ж помилка, і моє рішення - зробити модель "дійсною".

У моєму випадку після надсилання користувача, натиснувши кнопку «Зберегти», я отримав стан моделі: недійсний, якщо користувач вводить «0», але стан моделі буде дійсним, якщо вхід користувача «0,0».

Тому я переосмислюю метод "IsValid", щоб повернути справжній навіть ввійти користувачеві "0".

Сподіваюся, це допомагає.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.