Não há item ViewData do tipo 'IEnumerable <SelectListItem>' com a chave 'xxx'

87

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

Jimbo
fonte
1
Você tentou isso? <%= Html.DropDownList("submarket_0", ((SelectList)ViewData["Submarkets"]).Items, "(none)") %>DropDownList leva IEnumerable<SelectListItem>.
LukLed
@LukLed - foi assim que encontrei a origem do erro :), bem como informações de alguns outros posts! Obrigado
Jimbo
<%= Html.DropDownList("submarket_0", ViewData["Submarkets"] as IEnumerable<SelectListItem>, "(none)") %>
Arvis
Encontrei isso hoje e descobri que o segundo argumento em meu auxiliar DropDownList era nulo, de acordo com a descoberta abaixo de @jonathansewell.
Ken Palmer

Respostas:

79

Ok, então a resposta foi derivada de alguns outros posts sobre este problema e é:

Se ViewDatacontiver um SelectListcom o mesmo nome de seu, DropDownListou seja, "submarket_0", o helper Html o preencherá automaticamente DropDownListcom 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 ViewDatatinha sido alterada e não continha mais o que SelectListeu tinha referenciado, o HtmlHelper(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

Jimbo
fonte
104
Recebi este erro porque minha coleção de SelectListItems para a lista suspensa era nula, que é o mesmo problema que você teve, eu acho.
Jonathan Sewell
6
Para outras pessoas que enfrentam esse problema, envolva temporariamente sua lista suspensa em uma verificação nula, por exemplo, @if (ViewData ["Submarkets"]! = Null). Se a visualização renderizar sem gerar um erro (e sem sua lista suspensa), você terá identificado seu problema. O erro "nenhum item de dados de visualização" é muito enganoso neste caso.
GDB
Corri para isso usando um Ajax.ActionLink. Basta adicionar o SelectList Getao ActionMethodque contém a chamada Ajax.
fedor
Sim! Eu mudei o nome da lista que estava passando para o ViewData do controlador, e não mudei na visão. Essa é uma mensagem de erro terrivelmente confusa!
neminem
1
@JonathanSewell obrigado, obrigado, obrigado! Este era exatamente o meu problema.
johnw182
29

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 nome MyListe lança um erro se não houver nenhum objeto em ViewData com esse nome.

Hawkke
fonte
1
Olá, este é meu problema também, O que faremos se a lista for nula! você pode sugerir algo,
transformador
4
@transformer A coisa mais fácil a fazer seria definir Model.DropDownData como uma lista vazia em vez de nula. Se isso não for possível, você pode alterar sua marcação de navalha para verificar se a lista é nula e, em caso afirmativo, renderizar uma lista de seleção vazia.
hawkke
15

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!

Peto
fonte
9

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");
rakesh
fonte
3

Verifique o namespace.

Você pode atribuir System.Web.Webpages.Html.SelectListItem no Controlador, em vez de System.Web.Mvc.SelectListItem .

MovGP0
fonte
1

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

Morteza
fonte
0

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.

Thuy
fonte
0

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.

Mohammed Sabbir
fonte
0

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.

sdfs
fonte
-1

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(...)
Soluções IndieTech
fonte
1
A menos que meus olhos me enganam, não há SelectListno System.Collections.Generic.
Erik Philips