Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How does asp.net MVC remember my incorrect values on postback?

This is working, but how???

I have a controller action for a post:

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

The Person object has a property BirthDate, type DateTime. When i enter some invalid data in the form, say 'blabla' which is obvious not a valid Datetime, it fills all the (other) Person properties with the correct data and the BirthDate property with a new blank DateTime. The bool isvalid has the value 'false'. So far so good.

Then i do this:

return View(p);

and in the view i have this:

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

Ant there it comes: i EXPECTED the model to contain the new, blank DateTime because i didn't put any new data in. Second, when the View displays something, it must be a DateTime, because Model.BirthDate can't hold anything but a DateTime. But to my surprise, it shows a textbox with the 'blabla' value! (and the red * behind it)

Which ofcourse is nice because the user can seee what he typed wrong, but how can that (blabla)string be transferred to the View in a DateTime field?

EDIT: The ModelState info helped me a lot here. I also notices that in MVC 2, that when you create your own Template for Html.EditorFor() you have to implement this behaviour yourself. I created a

DateTime.ascx 

in the /views/shared/EditorTemplates folder, and in there i had to check if there was a modelstate error for this property value, and if so, show the invalid data in stead of the Model data.

So in the view i use this:

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

and in the DateTime.ascx i use this:

<%
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 %>" />
like image 599
Michel Avatar asked Apr 05 '10 20:04

Michel


2 Answers

ModelState holds KeyValuePairs for every form element with the key being the field name and the value is what you put in the field. Then the Html Helpers look in ModelState and if you don't explicitly specify a value, they will pull the value from ModelState.

like image 122
Keith Rousseau Avatar answered Oct 21 '22 11:10

Keith Rousseau


The previously entered value is stored in the ModelState. When you have an error on the form, the helper pulls the value from the ModelState instead of using either values from the Model or the ones specifically supplied (under the hood, if you don't supply an explicit value it will default to the model value if there is one when there are no errors).

like image 42
tvanfosson Avatar answered Oct 21 '22 13:10

tvanfosson