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

北战南征 提交于 2019-12-19 02:49:26

问题


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 %>" />

回答1:


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.




回答2:


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).




回答3:


I had some code in the 'postback' that would remove invalid promo-codes and capitalize the response. Even if you update the model with the new value it won't be displayed because the ModelState value takes precedence (as others have already answered).

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

But if you have a case where this was happening and you don't want the old value persisted you need to do this:

ModelState.Remove("PromoCode"); 

or explicitly set the new value into modelstate (probably the better approach) :

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


来源:https://stackoverflow.com/questions/2581042/how-does-asp-net-mvc-remember-my-incorrect-values-on-postback

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!