Нет элемента ViewData типа 'IEnumerable<SelectListItem>', который имеет ключ 'xxx'
Есть несколько сообщений об этом в Переполнении стека, но ни один с ответом, который, кажется, решает проблему в моей текущей ситуации.
У меня есть страница с таблицей, в каждой строке есть несколько текстовых полей и выпадающий список. Все выпадающие списки должны использовать одни и те же данные SelectList, поэтому я настроил их следующим образом:
контроллер
ViewData["Submarkets"] = new SelectList(submarketRep.AllOrdered(), "id", "name");
Посмотреть
<%= Html.DropDownList("submarket_0", (SelectList)ViewData["Submarkets"], "(none)") %>
Я использовал именно эту настройку во многих местах, но по какой-то причине в этом конкретном представлении я получаю сообщение об ошибке:
Нет элемента ViewData типа "IEnumerable", который имеет ключ "submarket_0".
8 ответов
Итак, ответ был получен из некоторых других сообщений об этой проблеме, и это:
Если твой ViewData
содержит SelectList
с тем же именем, что и ваш DropDownList
то есть "submarket_0", помощник HTML автоматически заполнит ваш DropDownList
с этими данными, если вы не укажете 2-й параметр, который в данном случае является источником SelectList.
Что случилось с моей ошибкой было:
Поскольку таблица, содержащая раскрывающиеся списки, была в частичном представлении, а ViewData
был изменен и больше не содержал SelectList
Я ссылался, HtmlHelper
(вместо того, чтобы выдать ошибку) попытался найти SelectList с именем "submarket_0" во ViewData (GRRRR!!!), который он все еще не мог найти, а затем выдал ошибку об этом:)
Пожалуйста, поправьте меня, если я ошибаюсь
Старый вопрос, но вот еще одно объяснение проблемы. Вы получите эту ошибку, даже если у вас строго типизированные представления и вы не используете ViewData для создания выпадающего списка. Причина ошибки может стать ясной, когда вы посмотрите на источник MVC:
// If we got a null selectList, try to use ViewData to get the list of items.
if (selectList == null)
{
selectList = htmlHelper.GetSelectData(name);
usedViewData = true;
}
Так что если у вас есть что-то вроде:
@Html.DropDownList("MyList", Model.DropDownData, "")
А также Model.DropDownData
является нулевым, MVC просматривает ваши ViewData для чего-то с именем MyList
и выдает ошибку, если в ViewData нет объекта с таким именем.
У меня была та же ошибка, я думаю, проблема в том, что текст ошибки сбивает с толку, потому что он дает ложное имя ключа.
В вашем случае он должен сказать "Нет элемента ViewData типа" IEnumerable ", который имеет ключ" Подмаркет "".
Моей ошибкой была ошибка в коде представления (ваши "Субмаркет"), но текст ошибки заставил меня сойти с ума.
Я публикую этот ответ, потому что я хочу сказать людям, которые ищут эту ошибку, как и я, что проблема в том, что она не находит IENumerable, а в том, что его нужно искать (в данном случае "Submarkets"), не в том, что показано по ошибке ("submarket_0").
Принятый ответ очень интересен, но, как вы сказали, соглашение применяется, если вы не указали 2-й параметр, в данном случае он был указан, но переменная не была найдена (в вашем случае, потому что у viewdata этого не было, в моем случае, потому что Я неправильно написал имя вар)
Надеюсь это поможет!
Проблема в том, что после нажатия кнопки отправки происходит повторная запись. Таким образом, при публикации данных на кнопку отправки, нажмите еще раз написать, прежде чем возвращать View()
ViewData["Submarkets"] = new SelectList(submarketRep.AllOrdered(), "id", "name");
Проверьте пространство имен.
Вы можете назначить System.Web.Webpages.Html.SelectListItem в контроллере вместо System.Web.Mvc.SelectListItem.
Это тоже нормально; Например:
==> В файле "NumberController":
public ActionResult Create([Bind(Include = "NumberId,Number1,Number2,OperatorId")] Number number)
{
if (ModelState.IsValid)
{
...
...
return RedirectToAction("Index");
}
ViewBag.OperatorId = new SelectList(db.Operators, "OperatorId",
"OperatorSign", number.OperatorId);
return View();
}
==> В файле View (Create.cshtml):
<div class="form-group">
@Html.LabelFor(model => model.Number1, htmlAttributes: new { @class =
"control-label col-md-2" })
<div class="col-md-10">
@Html.EditorFor(model => model.Number1, new { htmlAttributes = new {
@class = "form-control" } })
@Html.ValidationMessageFor(model => model.Number1, "", new { @class =
"text-danger" })
</div>
</div>
Теперь, если мы удалим это утверждение:
ViewBag.OperatorId = new SelectList(db.Operators, "OperatorId", "OperatorSign", number.OperatorId);
из задней части следующего утверждения (в нашем контроллере):
return View();
мы увидим эту ошибку:
Нет элемента ViewData типа "IEnumerable", который имеет ключ "OperatorId".
* Так что будьте уверены в существовании этих утверждений. *
Для меня проблема, которая вызвала эту ошибку, возникла, когда я сохранял новую строку в базе данных, но поле было пустым. В дизайне таблицы базы данных это поле НЕ ПУСТО. Поэтому, когда я попытался сохранить новую строку с нулевым значением для ненулевого поля, Visual Studio выдал эту ошибку. Таким образом, я убедился, что поле было присвоено значение, и проблема была исправлена.
Причина не противоречит синтаксису, а не неправильному использованию объектов. Жизненный цикл объектов в ViewData, ViewBag и View Life Cycle короче, чем в сеансе. Данные, определенные в формирователях, будут потеряны после запроса-ответа (при попытке доступа после запроса-ответа вы получите исключения). Таким образом, формеры подходят для передачи данных между View и Controller, а последний - для хранения временных данных. Временные данные должны храниться в сеансе, чтобы к ним можно было обращаться много раз.
В моем случае я обнаружил, что ошибочно установил метод публикации как частный. после изменения приватного на публичный.
[HttpPost]
private async Task<ActionResult> OnPostRemoveForecasting(){}
изменить на
[HttpPost]
public async Task<ActionResult> OnPostRemoveForecasting(){}
Теперь работает нормально.
В моем случае произошел конфликт в пространствах имен, у меня есть:
using System.Web.Mvc;
а также
using System.Collections.Generic;
Я явно хочу использовать Mvc, поэтому я объявил это как:
new System.Web.Mvc.SelectList(...)