Nie ma elementu ViewData typu „IEnumerable <SelectListItem>”, który ma klucz „xxx”

87

Jest kilka postów na ten temat w Stack Overflow, ale żaden z odpowiedzią, która wydaje się rozwiązać problem w mojej obecnej sytuacji.

Mam stronę z tabelą, w każdym wierszu znajduje się kilka pól tekstowych i lista rozwijana. Wszystkie listy rozwijane muszą używać tych samych danych SelectList, więc skonfigurowałem je w następujący sposób:

Kontroler

ViewData["Submarkets"] = new SelectList(submarketRep.AllOrdered(), "id", "name");

Widok

<%= Html.DropDownList("submarket_0", (SelectList)ViewData["Submarkets"], "(none)") %>

Użyłem dokładnie tej konfiguracji w wielu miejscach, ale z jakiegoś powodu w tym konkretnym widoku pojawia się błąd:

Nie ma elementu ViewData typu „IEnumerable”, który ma klucz „submarket_0”.

Jimbo
źródło
1
Próbowałeś tego? <%= Html.DropDownList("submarket_0", ((SelectList)ViewData["Submarkets"]).Items, "(none)") %>DropDownList trwa IEnumerable<SelectListItem>.
LukLed
@LukLed - tak rzeczywiście w końcu znalazłem źródło błędu :) oraz informacje z kilku innych postów! Dzięki
Jimbo,
<%= Html.DropDownList("submarket_0", ViewData["Submarkets"] as IEnumerable<SelectListItem>, "(none)") %>
Arvis
Spotkałem się z tym dzisiaj i stwierdziłem, że drugi argument w moim pomocniku DropDownList był zerowy, zgodnie z poniższym odkryciem z @jonathansewell.
Ken Palmer

Odpowiedzi:

79

Ok, więc odpowiedź została zaczerpnięta z kilku innych postów dotyczących tego problemu i jest to:

Jeśli Twój ViewDatazawiera znak SelectListo tej samej nazwie, co Twój DropDownListnp. „Submarket_0”, pomocnik HTML automatycznie zapełni DropDownListte dane, jeśli nie określisz drugiego parametru, który w tym przypadku jest źródłem SelectList.

To, co stało się z moim błędem, to:

Ponieważ tabela zawierająca listy rozwijane była w częściowym widoku, a tabela ViewDatazostała zmieniona i nie zawiera SelectListjuż odnośnika, do którego się odwołałem,HtmlHelper (zamiast zgłaszać błąd) próbował znaleźć SelectList o nazwie „submarket_0” w ViewData (GRRRR! !!), którego NADAL nie mógł znaleźć, a następnie wyrzucił błąd :)

Proszę popraw mnie jeżeli się mylę

Jimbo
źródło
104
Pojawił się ten błąd, ponieważ moja kolekcja SelectListItems dla listy rozwijanej miała wartość null, co jest tym samym problemem, który miałeś, jak sądzę.
Jonathan Sewell
6
W przypadku innych osób, które mają do czynienia z tym problemem, tymczasowo zawiń listę rozwijaną w wartość zerową, np. @If (ViewData ["Submarkets"]! = Null). Jeśli widok zostanie następnie wyrenderowany bez zgłaszania błędu (i bez rozwijanej listy), zidentyfikujesz problem. W tym przypadku błąd „brak widoku danych” jest bardzo mylący.
GDB
Wpadłem na to, używając pliku Ajax.ActionLink. Po prostu dodaj SelectList Getdo tego, ActionMethodktóry zawiera wywołanie Ajax.
śmierdzą
Tak! Zmieniłem nazwę listy, którą przekazywałem do ViewData z kontrolera i nie zmieniłem jej w widoku. To naprawdę strasznie mylący komunikat o błędzie!
neminem
1
@JonathanSewell dziękuję, dziękuję, dziękuję! To był mój dokładny problem.
johnw182
29

Stare pytanie, ale oto inne wyjaśnienie problemu. Otrzymasz ten błąd, nawet jeśli masz mocno wpisane widoki i nie używasz ViewData do tworzenia listy rozwijanej. Przyczyna błędu może stać się jasna, gdy spojrzysz na źródło 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;
}

Więc jeśli masz coś takiego:

@Html.DropDownList("MyList", Model.DropDownData, "")

I Model.DropDownDatajest null, MVC przegląda Twoje ViewData w poszukiwaniu czegoś o nazwie MyListi zgłasza błąd, jeśli w ViewData nie ma obiektu o tej nazwie.

hawkke
źródło
1
Cześć, to też mój problem, co zrobimy, jeśli lista jest pusta! czy możesz coś zasugerować
transformator
4
@transformer Najłatwiejszą rzeczą do zrobienia byłoby ustawienie Model.DropDownData na pustą listę zamiast na null. Jeśli nie jest to możliwe, możesz zmienić znaczniki maszynki do golenia, aby sprawdzić, czy lista jest pusta, a jeśli tak, wyrenderuj pustą listę wyboru.
hawkke
15

Miałem ten sam błąd, myślę, że problem polega na tym, że tekst błędu jest mylący , ponieważ podaje fałszywą nazwę klucza.

W twoim przypadku Powinien być napisany „Nie ma elementu ViewData typu„ IEnumerable ”, który ma klucz„ Submarkets ””.

Mój błąd polegał na błędnej pisowni w kodzie widoku (w „Podrynkach”), ale tekst błędu doprowadził mnie do szału.

Piszę tę odpowiedź, ponieważ chcę powiedzieć ludziom szukającym tego błędu tak jak ja, że ​​problem polega na tym, że nie znajduje on IENumerable, ale w var, w którym ma go szukać (w tym przypadku "Submarkets"), nie w tym, który został błędnie wyświetlony („submarket_0”) .

Zaakceptowana odpowiedź jest bardzo interesująca, ale jak powiedziałeś, konwencja jest stosowana, jeśli nie określisz drugiego parametru, w tym przypadku został on określony, ale var nie został znaleziony (w twoim przypadku, ponieważ viewdata go nie ma, w moim przypadku ponieważ Błędnie wpisałem nazwę var)

Mam nadzieję że to pomoże!

Peto
źródło
9

Problem polega na tym, że przesyłanie zwrotne następuje po kliknięciu przycisku przesyłania. Więc podczas publikowania danych po przesłaniu kliknij ponownie napisz przed powrotem Widok ()

ViewData["Submarkets"] = new SelectList(submarketRep.AllOrdered(), "id", "name");
rakesh
źródło
3

Sprawdź przestrzeń nazw.

Możesz przypisać System.Web.Webpages.Html.SelectListItem w kontrolerze zamiast System.Web.Mvc.SelectListItem .

MovGP0
źródło
1

To też jest w porządku; Na przykład:
==> W pliku „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();
}

==> W pliku widoku (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>

Teraz, jeśli usuniemy to stwierdzenie:

ViewBag.OperatorId = new SelectList(db.Operators, "OperatorId", "OperatorSign", number.OperatorId);

z tyłu następującego oświadczenia (w naszym kontrolerze):

return View();

zobaczymy ten błąd:

Nie ma elementu ViewData typu „IEnumerable”, który miałby klucz „OperatorId”.

* Więc upewnij się, że takie stwierdzenia istnieją. *

Morteza
źródło
0

U mnie problem, który spowodował ten błąd, pojawił się, gdy zapisywałem nowy wiersz do bazy danych, ale pole było puste. W projekcie tabeli bazy danych to pole NIE ma wartości NULL. Kiedy więc próbowałem zapisać nowy wiersz z wartością null dla pola innego niż null, program Visual Studio zgłosił ten błąd. W ten sposób upewniłem się, że pole ma przypisaną wartość, a problem został rozwiązany.

Czw
źródło
0

W moim przypadku stwierdziłem, że omyłkowo ustawiłem metodę wpisywania jako prywatną. po zmianie prywatnego na publiczny.

[HttpPost]
private async Task<ActionResult> OnPostRemoveForecasting(){}

zmień na

[HttpPost]
public async Task<ActionResult> OnPostRemoveForecasting(){}

Teraz działa dobrze.

Mohammed Sabbir
źródło
0

Przyczyna nie jest sprzeczna ze składnią, a nie niewłaściwym użyciem obiektów. Cykl życia obiektów w ViewData, ViewBag i View Life Cycle jest krótszy niż w sesji. Dane zdefiniowane w wzorcach zostaną utracone po odpowiedzi na żądanie (jeśli spróbujesz uzyskać dostęp po odpowiedzi na żądanie, otrzymasz wyjątki). Tak więc te pierwsze są odpowiednie do przekazywania danych między View & Controller, a drugie do przechowywania danych tymczasowych. Tymczasowe dane powinny być przechowywane w sesji, aby można było uzyskać do nich wielokrotny dostęp.

sdfs
źródło
-1

W moim przypadku wystąpił konflikt w przestrzeniach nazw, mam:

using System.Web.Mvc;

i

using System.Collections.Generic;

Wyraźnie chcę użyć Mvc, więc zadeklarowałem to jako:

new System.Web.Mvc.SelectList(...)
Rozwiązania IndieTech
źródło
1
Chyba mnie wzrok nie myli, nie ma SelectListw System.Collections.Generic.
Erik Philips,