Używam modelu, który zawiera listę jako właściwość. Zapełniam tę listę elementami pobranymi z SQL Server. Chcę, aby lista była ukryta w widoku i przekazana do akcji POST. Później mogę chcieć dodać więcej elementów do tej listy za pomocą jQuery, co sprawia, że tablica nie nadaje się do późniejszego rozszerzenia. Zwykle używałbyś
@Html.HiddenFor(model => model.MyList)
aby zrealizować tę funkcję, ale z jakiegoś powodu lista w POST jest zawsze pusta.
Bardzo proste pytanie, czy ktoś wie, dlaczego MVC tak się zachowuje?
c#
asp.net
asp.net-mvc-3
hidden-field
Anton Smith
źródło
źródło
<input />
s?MyList
zawiera?HiddenFor
jest używany tylko dla jednego wejścia naraz.Model.MyList
? Może być konieczne ręczne wykonanie serializacji / deserializacji na liście.Odpowiedzi:
Właśnie natknąłem się na ten problem i rozwiązałem go, wykonując następujące czynności:
Używając for zamiast foreach, powiązanie modelu będzie działać poprawnie i pobierze wszystkie ukryte wartości z listy. Wydaje się, że jest to najprostszy sposób rozwiązania tego problemu.
źródło
@Html.HiddenFor(model => Model.ToGroups[i].RowId)
@Html.EditorFor(model => Model.ToGroups[i].Id)
następnie@Html.EditorFor(model => Model.ToGroups[i].Description)
przy następnym - zarówno w pętli for. Kontroler był w stanie odwzorować to na listę modeli z tymi polami. Aby upewnić się, że żaden z nich nie pojawi się na ekranie, po prostu otocz go<div style="display: none;"></div>
for
-loop na to:for(int i = 0; i < Model.Departments.Count(); i++)
HiddenFor nie jest jak DisplayFor lub EditorFor. Nie będzie działać z kolekcjami, tylko z pojedynczymi wartościami.
Możesz użyć pomocnika Serialize HTML dostępnego w projekcie MVC Futures do serializacji obiektu do ukrytego pola lub będziesz musiał sam napisać kod. Lepszym rozwiązaniem jest po prostu serializacja jakiegoś identyfikatora i ponowne pobranie danych z bazy danych po ogłoszeniu zwrotnym.
źródło
To trochę hack, ale jeśli
@Html.EditorFor
lub@Html.DisplayFor
pracujesz na twojej liście, jeśli chcesz się upewnić, że jest wysłana w żądaniu postu, ale nie jest widoczna, możesz po prostu zmienić jej styl na użycie,display: none;
aby ją ukryć, np .:źródło
A co z używaniem Newtonsoft do deserializacji obiektu do łańcucha json, a następnie wstaw go do swojego pola ukrytego, np. ( Model.DataResponse.Entity.Commission to lista prostych obiektów „CommissionRange”, jak zobaczysz w JSON)
Renderuje jako:
W moim przypadku robię trochę rzeczy JS, aby edytować json w ukrytym polu przed wysłaniem z powrotem
W moim kontrolerze ponownie używam Newtonsoft do deserializacji:
źródło
Html.HiddenFor
jest przeznaczony tylko dla jednej wartości. Będziesz musiał w jakiś sposób serializować swoją listę przed utworzeniem ukrytego pola.Na przykład, jeśli twoja lista jest typu string, możesz połączyć ją w listę oddzieloną przecinkami, a następnie podzielić listę po wysłaniu z powrotem do kontrolera.
źródło
Właśnie dowiedziałem się (po kilku godzinach prób wyjaśnienia, dlaczego wartości modelu nie wracają do kontrolera), że ukryte dla powinny być zgodne z EditorFor.
O ile nie robię czegoś innego źle, to właśnie znalazłem. Nie popełnię ponownie błędu.
W kontekście modelu zawierającego listę innej klasy.
To NIE zadziała:
Gdzie to BĘDZIE ......
źródło
Zacząłem przekopywać się w kodzie źródłowym
HiddenFor
i myślę, że przeszkoda, którą widzisz, polega na tym, że twój złożony obiektMyList
nie jest niejawnie konwertowany na typstring
, więc struktura traktuje twojąModel
wartość jakonull
i renderujevalue
atrybut pusty.źródło
Możesz rzucić okiem na to rozwiązanie .
Umieść tylko HiddenFor wewnątrz EditorTemplate.
I w swoim Widoku umieść to:
@Html.EditorFor(model => model.MyList)
Powinno działać.
źródło
W obliczu tego samego problemu. Bez pętli for wysłał tylko pierwszy element listy. Po wykonaniu iteracji pętli for może zachować pełną listę i pomyślnie wysyłać.
źródło
Inną opcją byłoby:
źródło
foreach
Pętli zamiastfor
pętli może być nieco roztworu czyszczącego.źródło
Innym możliwym sposobem rozwiązania tego problemu byłoby nadanie każdemu obiektowi z listy identyfikatora, a następnie użycie
@Html.DropDownListFor(model => model.IDs)
i wypełnienie tablicy, która przechowuje identyfikatory.źródło
może późno, ale stworzyłem metodę rozszerzenia dla ukrytych pól z kolekcji (z prostymi elementami typu danych):
Więc oto jest:
Użycie jest tak proste, jak:
źródło