2009-05-07 12 views
5

Mam problem pojawiający się w formularzu, który próbuję opublikować. W scenariuszu, w którym formularz się nie sprawdza, wybieram standardową trasę wywoływania ModelState.AddModelError(), a następnie zwracam wynik widoku.ASP.Net MVC ModelState/Html.TextBox - problem z odpracowaniem

Chodzi o to, że HTML. * Helpery mają pobierać zaksięgowaną wartość podczas renderowania i zauważam, że moje pola tekstowe robią to TYLKO, jeśli umieściłem je na liście parametrów działania oddzwonienia, które powinno Wymagane jest widzenie, ponieważ niektóre formularze mają zdecydowanie za dużo pól, aby je wszystkie wymienić jako parametry.

Mój kod działanie jest grubsza:

[AcceptVerbs(HttpVerbs.Post)] 
public ActionResult EditDataDefinition(long? id, string name) 
{ 
    var dataDefinition = ... 

    // do some validation stuff 
    if (!ModelState.IsValid) 
    { 
     // manually set checkbox fields via ViewData seeing as this STILL doesn't work in MC 1.0 :P 
     // ... 
     return View(dataDefinition); 
    } 

} 

Teraz dataDefinition (co jest LINQ do podmiotu SQL) ma pole MinVolume, jest obsługiwane w widoku od tej linii:

Minimum: <%= Html.TextBox("MinVolume", null, new { size = 5 })%> 

Jednak gdy widok jest renderowany po nieudanym sprawdzaniu poprawności ModelState, wartość zapisana w nim na oryginalnej stronie, którą zamieściliśmy, nie jest zachowywana, O ile nie uwzględnię jej jako parametru w metodzie odświeżenia. Dosłownie, mogę "rozwiązać problem", wykonując to:

[AcceptVerbs(HttpVerbs.Post)] 
public ActionResult EditDataDefinition(long? id, string name, string minVolume) 

Z jakiegoś powodu, które wymusi zachowanie wartości pola. Wydaje mi się to głupie, ponieważ moja forma ma znacznie więcej wartości niż tylko to i nie powinienem dodawać parametru dla tego pola.

Wszelkie pomysły?

Odpowiedz

4

Czyżby kodzie:

<%= Html.TextBox("MinVolume", null, new { size = 5 })%> 

..has na null dla wartości domyślnej param? Może jeśli zmienisz wartość null na Model.MinVolume, ta wartość pozostanie. Tak:

<%= Html.TextBox("MinVolume", Model.MinVolume, new { size = 5 })%> 

Nie jestem pewien, czy akcja zwraca wartość MinVolume w modelu Tho.Jeśli tak, powyższe powinno zadziałać. W przeciwnym razie może być konieczne nieznaczne skorygowanie działania.

+0

Nie, podając wartość null należy określić, że istniejący kontekst modelu powinien być użyty do wysłania zapytania o wartość. Określenie MinVolume jest wyraźne i zmusiłoby tę wartość do użycia zamiast tego, co zostało wcześniej przesłane. –

+0

Niepoprawnie. Określenie MinVolume wyszukuje ViewDataDoctionary, a następnie ModelStateDictionary dla kolejnych postów. Więc jeśli Model.MinVolume powie 5 edycji, to określenie MinVolume umieści 5 w TextBox. Następnie, jeśli zostanie utworzony post (powiedzmy, że wartość 3), ale zostanie uznany za nieprawidłowy, wówczas TextBox pokaże 3 po raz drugi. Próbowałeś tego? Zazwyczaj określa się wartość NULL w widoku "Nowy" lub "Utwórz", aby początkowy wpis był pusty w polu, a kolejne posty utrzymywały wprowadzoną wartość. –

+0

To jest dokładnie ten sam sposób, w jaki to robię i działa za każdym razem. Nigdy nie widziałem nigdzie, że trzeba określić zero. Link do tego, gdzie widziałeś, byłby dobry. – sirrocco

3

Jaki jest klucz używany podczas ustawiania wartości w stanie ModelState w przypadku błędu? Kod ustawiający parametr wartości dla TextBox wygląda następująco:

Odnośna część downloaded framework code.

string attemptedValue = (string)htmlHelper.GetModelStateValue(name, typeof(string)); 
tagBuilder.MergeAttribute("value", attemptedValue ?? ((useViewData) ? htmlHelper.EvalString(name) : valueParameter), isExplicitValue); 

Jak widać, jeśli wartość próby istnieje, zostanie ona wykorzystana - ale tylko wtedy, gdy ten sam klucz jest dostępny.

Wiem, że to działa, ponieważ mam akcję, która nie pobiera żadnych parametrów i pobiera wartości bezpośrednio z ValueProvider i używa AddModelError do wskazania błędów sprawdzania poprawności. Jestem pewien, że wartości w moich polach tekstowych zostaną zachowane.

EDYCJA: Aby zachować wartości, muszą one być w jakiś sposób powiązane z modelem. Jednym ze sposobów na to jest dodanie ich do listy parametrów. Innym sposobem jest użycie UpdateModel (z nazwami parametrów na białej liście lub bez białej listy). Trzecim sposobem jest jawne dodanie parametru do modelu, jak w odpowiedzi @ Jenea. Ponieważ pomocnik tylko ściąga ze stanu modelu, muszą tam być, aby zachować wartości. Nie wygląda na właściwości formularza żądania.

+0

To pole nie jest weryfikowany w ogóle - nie musi być na tym etapie. W związku z tym jest to po prostu "niewinny obserwator" w formie i oczekuje, że jego nowa wartość zostanie zachowana, jeśli jedno z pozostałych pól nie zachowuje się samo, co powoduje, że forma jest renderowana po raz drugi. –

+0

Zastanawiam się nagle, jeśli niepoprawnie przyjmuję założenie, że ModelState powinien próbować zachować wszystkie pola, które mają nazwy pasujące do Modelu. Być może to tylko zachowuje pola, które są przekazywane za pośrednictwem listy parametrów lub odwołania za pośrednictwem AddModelError? Jeśli tak jest, wydaje się to głupie, bo oczywiście chcę zachować wszystko w formie, a nie tylko konkretne przypadki. Z drugiej strony, MVC nadal i tak nie zachowuje pól checkbox ... –

0

Jak rozumiem rozwiązaniem jest:

[Transaction] 
[AcceptVerbs(HttpVerbs.Post)] 
public ActionResult EditDataDefinition(int id, FormCollection form) 
{ 
    T itemToUpdate = repository.Get(id); 
    UpdateModel(itemToUpdate, form.ToValueProvider()); 

    if (itemToUpdate.IsValid()) 
    { 
     repository.SaveOrUpdate(itemToUpdate); 
     return Json(ValidationResultToJson(itemToUpdate.ValidationResults())); 
    } 

    repository.DbContext.RollbackTransaction(); 
    return Json(ValidationResultToJson(itemToUpdate.ValidationResults())); 
} 

powodzenia!

6

O człowieku Właśnie poprawiłem swój projekt aplikacji. Problem występuje, ponieważ masz niestandardową weryfikację (ja też). Trzeba dodać po

ModelState.AddModelError() 

to

ModelState.SetModelValue("MinVolume", ValueProvider["MinVolume"]); 

Mając to musi być

Mimum:<%=Html.Textbox("MinVolume")%> 

Nadal nie wiem, dlaczego to działa, ale pracował dla mnie.

+0

oooh ... to może być odpowiedź! sprawdzi się rano, kiedy dostanę się do pracy. dzięki. –

+2

Działa, ponieważ dodaje wartość do modelu, z którego helper ściąga wartości. Użycie UpdateModel również by działało, czego używam i dlaczego moje wartości w polu tekstowym są zachowywane. – tvanfosson

0

Innym rozwiązaniem jest, jeśli wpiszesz widzenia:

<%var minVolume=Request["MinVolume"]??"";%> 
<%=Html.Textbox("MinVolume",minVolume,new {size=5})%> 
0

Proszę odnieść się do tego artykułu, aby zobaczyć różne sposoby obsługi odświeżenie strony w ASP.NET MVC

link text

+0

Dobry artykuł na początek. –