2010-04-05 14 views
6

To działa, ale jak?Jak asp.net MVC zapamiętuje moje nieprawidłowe wartości na poczcie zwrotnej?

Mam działania kontrolera na stanowisko:

[AcceptVerbs(HttpVerbs.Post)] 
public ActionResult Edit(Person person) 
{ 
    bool isvalid = ModelState.IsValid; 
    etc. 

Przedmiotem osoba ma urodzenia rzeczowych typu DateTime. Po wprowadzeniu niektórych nieprawidłowych danych w formularzu, powiedz "blabla", co jest oczywiste, nie jest prawidłową datą, wypełnia on wszystkie właściwości (inne) osoby poprawnymi danymi i właściwością BirthDate z nową pustą datą. Wartość bool jest nieprawidłowa ma wartość "false". Jak dotąd tak dobrze.

Wtedy to zrobić:

return View(p); 

iw widoku mam to:

<%= Html.TextBox("BirthDate", String.Format("{0:g}", Model.BirthDate)) %> 
<%= Html.ValidationMessage("BirthDate", "*") %> 

Ant tam chodzi: Spodziewałem model zawiera nową, pustą DateTime bo nie zrobił Nie dodawaj żadnych nowych danych. Po drugie, gdy widok wyświetla coś, musi to być DateTime, ponieważ Model.BirthDate nie może pomieścić niczego innego niż DateTime. Ale ku mojemu zdziwieniu pokazuje pole tekstowe z wartością "blabla"! (i czerwony * za nim)

Który z nich jest przyjemny, ponieważ użytkownik widzi, co wpisał błędnie, ale w jaki sposób ten ciąg (blabla) może zostać przeniesiony do pola Widok w polu DataTime?

EDIT: Informacje o ModelState bardzo mi pomogły. Też zauważyłem, że w MVC 2, że kiedy tworzysz swój własny Szablon dla Html.EditorFor() musisz sam zaimplementować to zachowanie. stworzyłem

DateTime.ascx 

w widokach/udostępnionego folderu// EditorTemplates i tam miałem, by sprawdzić, czy nie było błędów ModelState dla tej wartości nieruchomości, a jeśli tak, to pokazują nieprawidłowe dane w zastępstwie dane modelu.

Więc w widoku używać to:

<%= Html.LabelFor(model => model.DateOfBirth) %> 

aw DateTime.ascx używam to:

<% 
bool invalidData = false; 
string propertyName = ViewData.ModelMetadata.PropertyName; 

ModelState ms = ViewData.ModelState[propertyName]; 
if (ms != null) 
{ 
    invalidData = ms.Errors.Count > 0; 
} 
string valueToshow = invalidData ? ViewData.ModelState[propertyName].Value.AttemptedValue : String.Format("{0:g}", Model); 
%> 
<input class="text-box single-line" id="<%= propertyName %>" name="<%= propertyName %>" type="text" value="<%= valueToshow %>" /> 

Odpowiedz

10

ModelState posiada KeyValuePairs dla każdego elementu formularza z kluczem jest nazwa pola a wartość jest tym, co umieszczasz w polu. Następnie Pomocnicy HTML wyglądają w ModelState i jeśli nie określisz jawnie wartości, będą pobierać wartość z ModelState.

+0

Dzięki, nie teraz pomocnicy zrobili więcej niż analizowanie wartości w modelu. – Michel

4

Poprzednio wprowadzona wartość jest przechowywana w obiekcie ModelState. Kiedy masz błąd w formularzu, helper pobiera wartość z ModelState zamiast używać wartości z Modelu lub specjalnie podanych (pod maską, jeśli nie podasz jawnej wartości, domyślnie będzie to model wartość, jeśli istnieje, gdy nie ma błędów).

+0

+1 za odpowiedź, Keith był nieco szybszy, mam nadzieję, że nie masz nic przeciwko zaznaczeniu jego jako odpowiedzi – Michel

+0

Myślę, że ta odpowiedź jest poprawna, a Keitha nie jest dokładnie w porządku. Odpowiedź Keitha mówi, że ModelState jest używany, jeśli nie podajesz jawnie wartości; w tej odpowiedzi stwierdza się, że parametr ModelState jest używany w przypadku wystąpienia błędu, niezależnie od tego, czy wartość została jawnie określona. Wzorzec do wywołania kontrolera GET po kontrolerze POST, gdy występuje błąd modelu, działa tylko dlatego, że dane widoku modelu modelu zawsze przesłoniły wszystko, co kodowałeś w kontrolerze GET. –

1

Mam "kod zwrotny", który usunie nieprawidłowe kody promocyjne i zamieni odpowiedź na wielką. Nawet jeśli zaktualizujesz model o nową wartość, nie będzie on wyświetlany, ponieważ wartość ModelState ma pierwszeństwo (tak jak inni już odpowiedzieli).

<%= Html.TextBox("PromoCode", Model.PromoCodes) %> 

Ale jeśli masz przypadek, w którym to się dzieje, i nie chcesz, stara wartość utrzymywała trzeba to zrobić:

ModelState.Remove("PromoCode"); 

lub jawnie ustawić nową wartość do ModelState (prawdopodobnie lepsze podejście):

ModelState.SetModelValue("PromoCode", 
     new ValueProviderResult(newValue, newValue, CultureInfo.CurrentCulture)); 
+0

+1 za dodanie. – Michel

Powiązane problemy