O item ViewData que possui a chave 'MY KEY' é do tipo 'System.String', mas deve ser do tipo 'IEnumerable <SelectListItem>'


142

Estou tentando preencher uma lista suspensa de um banco de dados mapeado com Linq-2-SQL, usando o ASP.NET MVC 2, e continuo recebendo esse erro.

Estou tão confuso porque estou declarando uma variável do tipo IEnumerable<SelectListItem>na segunda linha, mas o erro me faz pensar que esse não é o caso. Eu sinto que isso deve ser muito simples, mas estou lutando. Qualquer ajuda é apreciada.

Aqui estão os bits interessantes do meu controlador:

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();
}

E aqui estão os bits interessantes da minha opinião:

<div class="editor-label">
   <%: Html.LabelFor(model => model.basetype) %>
</div>
<div class="editor-field">
   <%: Html.DropDownList("basetype") %>
   <%: Html.ValidationMessageFor(model => model.basetype) %>
</div>

Aqui está a ação POST ao enviar o formulário

// 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);
    }
}

Obrigado.


1
A lista suspensa aparece bem na exibição. Ele preenche o banco de dados como deveria, mas é quando eu publico o formulário que recebo esses erros.
— JBibbs

6
Resumo da resposta aceita: certifique-se de preencher a lista nas ações get e post do seu controlador. É fácil esquecer de fazer isso e acabar perdendo tempo procurando um bug mais complicado.
— Adam Tolley

Respostas:


208

Eu tive o mesmo problema, e finalmente consegui a resposta ...

O problema é que, na ação POST, após o envio do formulário, o ModelState não é válido ou está detectando um erro na tentativa / captura, portanto a Visualização é retornada. Mas desta vez a View não está ViewData["basetype"]configurada corretamente.

Você precisa preenchê-lo novamente, provavelmente com o mesmo código usado antes, então repita isso:

var db = new DB();
IEnumerable<SelectListItem> basetypes = db.Basetypes.Select(
    b => new SelectListItem { Value = b.basetype, Text = b.basetype });
ViewData["basetype"] = basetypes;

antes do return View(meal)no [HttpPost]método.

exatamente isso resolverá seu problema:

[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);
    }
}

Sei que essa pergunta é muito antiga, mas vim aqui hoje com o mesmo problema, para que outros possam vir aqui mais tarde ...


8
+1 para "preenchê-lo novamente" ... Eu tenho um sistema bastante robusto para compor meus modelos de exibição, mas esqueci completamente de chamá-lo. Assim, a propriedade não foi preenchida e eu recebi essa mensagem (bastante ambígua), não importa o que eu tentasse.
— Tim Medora

8
se você receber isso ANTES de um post, é porque não há nada no SelectList, apenas o encontrou.
— Martin Martin

1
+1 Porque eu estava definindo meu ViewBag no método Index quando estava realmente chamando um Html.Action para outro método de ação !!
— SwampyFox

Obrigado. Seria bom se fosse preservado, mas suponho que não seria o "caminho" do MVC.
— Casey

se o modelo está ficando inválido, então eu venho os dados enviados pelo usuário serão salvos no banco de dados? Eu também estou enfrentando o mesmo problema. eu sou um novato. corrija-me se eu estiver errada.
— Koushik Saha #

87

Você receberá esse erro se o SelectList for nulo.


3
Sim, esse é um erro / supervisão comum quando você configura o SelectList em um GET e, em seguida, envia para uma ação POST (obviamente) que possui um, ModelState.IsValid==falseassim você retorna o modelo, return View(model) mas não repovoa sua origem do SelectList antes de retornar do POST. Como não há WebForms do ViewState ala, não há fonte para o @Html.DropDownauxiliar reconstruir a seleção. Você precisa preencher essa lista de fontes Toda vez que retornar a exibição para o cliente, não apenas no GET.
— Rism

Sim, este foi o meu problema. Esqueceu de preencher o selectList na chamada de recebimento. Erro muito enganador. Ótimo post.
— Matt


1

Para futuros leitores, se você estiver usando navalha, tente alterar o tipo de item da lista de seleção de List para IEnumerable.

De

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

Para

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

0

Tente adicionar uma sequência para o nome da sua lista suspensa como o primeiro parâmetro e retire o item dos seus dados de exibição:

 <%= Html.DropDownList("SomeDropdownName", (IEnumerable<SelectListItem>)ViewData["basetype"]) %>

Aqui também está um método de extensão que você pode usar para que a lista suspensa seja configurada em um estilo semelhante ao de seus outros controles:

        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);
    }

Por exemplo

<%= Html.DropDownList(x => x.BaseType, (IEnumerable<SelectListItem>)ViewData["basetype"], "")%>

0

Você está configurando a coleção como um item no dicionário ViewData e tentando recuperá-la como propriedade no modelo. Uma correção simples seria referenciá-lo da mesma maneira que você o define:

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

Como alternativa, o código abaixo usa uma exibição fortemente tipada:

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 });
    }

Em seguida, na sua exibição fortemente digitada:

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

Eu tentei usar o código no seu exemplo de "correção simples" e obtive o mesmo erro. Eu deveria ter mencionado que a lista suspensa é preenchida no modo de exibição ok, mas eu recebo esse erro ao enviar o formulário.
— JBibbs

Você pode publicar o código da Ação do Controlador que lida com o envio do formulário?
— Igor Zevaka 04/08/10

Claro, vou adicioná-lo à postagem original. Obrigado pela vossa ajuda até agora.
— JBibbs

0

Se você usar Html.DropDownList() método - o mesmo erro poderá ocorrer, se o item ViewData / Viewbag não estiver definido, como o @Peto respondeu.

Mas pode não estar definido corretamente no caso de um item definido do controlador, mas na visualização principal você usa a chamada parcial do viw com novos valores de ViewDataDictionary.

se você tem @Html.Partial("Partianame", Model,new ViewDataDictionary() { /* ... */ })então a sua visão parcial não vai ver ViewDatae ViewBagdados, remova new ViewDataDictionary()o parâmetro


0

Para futuros leitores,

Hoje me deparei com o problema e não consegui consertá-lo. Afinal, tornou-se realmente simples. Eu estava trabalhando com uma tabela + vista. Quando atualizei a tabela (adicionei algumas colunas), esqueci de atualizar (descartar e recriar) a exibição, o que causou o problema para mim. Espero que ajude alguém.


0

Recebi o mesmo erro hoje e minha solução é tornar o modelo "válido".

No meu caso, após o envio do usuário, clicando em "Salvar", obtive o estado do modelo: inválido se o usuário digitar "0", mas o estado do modelo será válido se o usuário digitar "0.0".

Então, eu substituo o método "IsValid" para retornar a verdadeira entrada de usuário "0".

Espero que ajude.

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.