Элемент ViewData с ключом MY KEY относится к типу System.String, но должен иметь тип IEnumerable <SelectListItem>.

143

Я пытаюсь заполнить раскрывающийся список из базы данных, сопоставленной с 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);
    }
}

Спасибо.

JBibbs
источник
1
Выпадающий список отображается в представлении нормально. Он заполняется из базы данных должным образом, но когда я публикую форму, я получаю эти ошибки.
JBibbs
6
Сводка принятого ответа: убедитесь, что вы заполняете список как в действиях get, так и в действиях вашего контроллера. Легко забыть об этом, а затем потратить время на поиск более сложной ошибки.
Адам Толли

Ответы:

208

У меня была такая же проблема, и наконец я получил ответ ...

Проблема в том, что в действии POST после отправки формы ModelState недействителен или обнаруживает ошибку в try / catch, поэтому возвращается View. Но на этот раз View 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.
Кейси
если модель становится недействительной, то данные, отправленные пользователем, будут сохранены в базе данных? Я тоже столкнулся с той же проблемой. я новичок. поправьте меня, если я ошибаюсь.
Koushik Saha
87

Вы получите эту ошибку, если SelectList имеет значение null.

Бен
источник
3
Да, это распространенная ошибка / недосмотр, когда вы настраиваете SelectList на GET, а затем отправляете обратно в действие POST (очевидно), у которого есть ModelState.IsValid==falseтак, чтобы вы возвращали модель, return View(model) но не повторно заполняли свой источник SelectList перед возвратом из POST. Поскольку нет ViewState или WebForms, у @Html.DropDownпомощника нет источника, с помощью которого можно было бы перестроить выборку. Вы должны заполнять этот список источников КАЖДЫЙ раз, когда возвращаете представление клиенту, а не только в GET.
rism
да, это была моя проблема. Забыл заполнить список selectList при вызове get. Очень вводящая в заблуждение ошибка. Отличный пост.
Мэтт
1

Для будущих читателей, если вы используете razor, попробуйте изменить тип элемента списка выбора с List на IEnumerable.

Из

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

Чтобы

@Html.DropDownListFor(m => m.id, ViewBag.SomeList as IEnumerable<SelectListItem>)
sxyplex
источник
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"], "")%>
CRice
источник
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>
Игорь Зевака
источник
Я пробовал использовать код из вашего примера "простого исправления" и получил ту же ошибку. Я должен был упомянуть, что раскрывающийся список заполняется в View ok, но я получаю эту ошибку, когда отправляю форму.
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".

Надеюсь, это поможет.

Рэй Чанг
источник