Existem alguns posts sobre isso no Stack Overflow, mas nenhum com uma resposta que pareça resolver o problema na minha situação atual.
Eu tenho uma página com uma tabela, cada linha possui vários campos de texto e uma lista suspensa. Todos os menus suspensos precisam usar os mesmos dados SelectList, então eu os configurei da seguinte maneira:
Controlador
ViewData["Submarkets"] = new SelectList(submarketRep.AllOrdered(), "id", "name");
Visão
<%= Html.DropDownList("submarket_0", (SelectList)ViewData["Submarkets"], "(none)") %>
Usei exatamente essa configuração em muitos lugares, mas por algum motivo nesta visualização em particular, recebo o erro:
Não há nenhum item ViewData do tipo 'IEnumerable' com a chave 'submarket_0'.
<%= Html.DropDownList("submarket_0", ((SelectList)ViewData["Submarkets"]).Items, "(none)") %>
DropDownList levaIEnumerable<SelectListItem>
.<%= Html.DropDownList("submarket_0", ViewData["Submarkets"] as IEnumerable<SelectListItem>, "(none)") %>
Respostas:
Ok, então a resposta foi derivada de alguns outros posts sobre este problema e é:
Se
ViewData
contiver umSelectList
com o mesmo nome de seu,DropDownList
ou seja, "submarket_0", o helper Html o preencherá automaticamenteDropDownList
com esses dados se você não especificar o segundo parâmetro que, neste caso, é a SelectList de origem.O que aconteceu com meu erro foi:
Como a tabela contendo as listas suspensas estava em uma visualização parcial e
ViewData
tinha sido alterada e não continha mais o queSelectList
eu tinha referenciado, oHtmlHelper
(em vez de lançar um erro) tentou encontrar a SelectList chamada "submarket_0" no ViewData (GRRRR! !!) que AINDA não conseguiu encontrar e, em seguida, gerou um erro nisso :)Por favor me corrija se eu estiver errado
fonte
Ajax.ActionLink
. Basta adicionar oSelectList
Get
aoActionMethod
que contém a chamada Ajax.Pergunta antiga, mas aqui está outra explicação para o problema. Você obterá esse erro mesmo se tiver modos de exibição fortemente tipados e não estiver usando ViewData para criar sua lista suspensa. O motivo do erro pode ficar claro quando você olha a fonte do 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; }
Então, se você tem algo como:
@Html.DropDownList("MyList", Model.DropDownData, "")
E
Model.DropDownData
é nulo, o MVC procura em seu ViewData por algo com o nomeMyList
e lança um erro se não houver nenhum objeto em ViewData com esse nome.fonte
Tive o mesmo erro, acho que o problema é que o texto do erro é confuso , pois está dando um nome de chave falso.
No seu caso, deve dizer "Não há nenhum item ViewData do tipo 'IEnumerable' com a chave" Submercados "".
Meu erro foi um erro de ortografia no código de exibição (seus "Submercados"), mas o texto do erro me deixou louco.
Posto esta resposta porque quero dizer às pessoas que procuram este erro, como eu estava, que o problema é que não está encontrando o IENumerable, mas na var que se supõe que deve procurar ("Submercados" neste caso), não no mostrado com erro ("submarket_0") .
A resposta aceita é muito interessante, mas como você disse a convenção é aplicada se você não especificar o 2º parâmetro, neste caso ele foi especificado, mas o var não foi encontrado (no seu caso porque o viewdata não o tinha, no meu caso porque Escrevi incorretamente o nome var)
Espero que isto ajude!
fonte
O problema é que a postagem de volta acontece no clique do botão de envio. Assim, ao postar dados em enviar, clique novamente em escrever antes de retornar Visualizar ()
ViewData["Submarkets"] = new SelectList(submarketRep.AllOrdered(), "id", "name");
fonte
Verifique o namespace.
Você pode atribuir System.Web.Webpages.Html.SelectListItem no Controlador, em vez de System.Web.Mvc.SelectListItem .
fonte
Isso também está bom; Por exemplo:
==> No arquivo "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(); }
==> No arquivo de visualização (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>
Agora, se removermos esta declaração:
ViewBag.OperatorId = new SelectList(db.Operators, "OperatorId", "OperatorSign", number.OperatorId);
do verso da seguinte declaração (em nosso controlador):
return View();
veremos este erro:
Não há item ViewData do tipo 'IEnumerable' com a chave 'OperatorId'.
* Portanto, certifique-se da existência dessas declarações. *
fonte
Para mim, o problema que causou esse erro surgiu quando eu estava salvando uma nova linha no banco de dados, mas um campo era nulo. No design da tabela de banco de dados, esse campo NÃO é NULL. Portanto, quando tentei salvar uma nova linha com um valor nulo para o campo não nulo, o Visual Studio gerou este erro. Portanto, certifiquei-me de que o campo recebeu um valor e que o problema foi corrigido.
fonte
No meu caso, descobri que defini o método post como privado por engano. depois de mudar privado para público.
[HttpPost] private async Task<ActionResult> OnPostRemoveForecasting(){}
mudar para
[HttpPost] public async Task<ActionResult> OnPostRemoveForecasting(){}
Agora funciona bem.
fonte
A causa não é contrária à sintaxe, e não ao uso impróprio de objetos. O ciclo de vida de objetos em ViewData, ViewBag e View Life Cycle é mais curto do que na sessão. Os dados definidos nos formulários serão perdidos após uma solicitação-resposta (se tentar acessar após uma solicitação-resposta, você obterá exceções). Portanto, os formadores são apropriados para a passagem de dados entre o View & Controller, enquanto o último para armazenar dados temporários. Os dados temporários devem ser armazenados na sessão para que possam ser acessados várias vezes.
fonte
No meu caso, houve um conflito nos namespaces, eu:
using System.Web.Mvc;
e
using System.Collections.Generic;
Desejo explicitamente usar o Mvc, então declarei-o como:
new System.Web.Mvc.SelectList(...)
fonte
SelectList
noSystem.Collections.Generic
.