Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Html.TextBoxFor does not show updated value in POST action

Tags:

asp.net-mvc

In my view I have

      <%:Html.LabelFor(model => model.IPAddress)%>

    <div class="editor-field">
        <%:Html.TextBoxFor(model => model.IPAddress)%>
        <%:Html.ValidationMessageFor(model => model.IPAddress)%>
    </div>

In my controller(post method), I have this

[HttpPost]
public ActionResult Manipulation(MyModel model){
  //I change modele here
  if(something)
    model.IPAddress="100.100.100.100";
  return View(model);
}

So, my question is: When I change model, the TextBoxFor does not change his value. TextBoxFor get his value when I get from get method to the post, and later I cannot change value of TextBoxFor. I debug, and my model have new value, but TextBoxFor does not show new value.

Can you help me?

like image 596
cashmere Avatar asked Feb 03 '11 13:02

cashmere


1 Answers

Mr Grok had a similar problem this site. He had already found the ModelState.Clear() solution, but was wanting an explanation of why it worked. The highest ranked answer on the linked site proposed that the behavior of the html helper is a bug, for which ModelState.Clear() is a workaround. However, bradwils at this site says that the behavior is by design, and gives the following explanation:

The reason we use the posted value for editors rather than the model value is that the model may not be able to contain the value that the user typed. Imagine in your "int" editor the user had typed "dog". You want to display an error message which says "dog is not valid", and leave "dog" in the editor field. However, your model is an int: there's no way it can store "dog". So we keep the old value.

If you don't want the old values in the editor, clear out the Model State. That's where the old value is stored and pulled from the HTML helpers.

Despite the fact that it’s by design, this is very unexpected behavior for the developer, and it is unfortunate that interaction with the ModelState is required for a common programming need.

Furthermore, clearing the entire ModelState might cause unexpected issues in other areas (I think with respect to validation on unrelated model fields). So many thanks to Peter Gluck (responding in a comment within Mr Grok’s page) for proposing the more limited ModelState.Remove(“key”), and to Toby J for developing a more convenient method that works when you’re not sure what the key should be if the model property is nested. I also like Toby’s method because it doesn’t depend on a string as input.

That method, with minor changes, follows:

/// <summary>
/// Removes the ModelState entry corresponding to the specified property on the model. Call this when changing
/// Model values on the server after a postback, to prevent ModelState entries from taking precedence.
/// </summary>
/// <param name="model">The viewmodel that was passed in from a view, and which will be returned to a view</param>
/// <param name="propertyFetcher">A lambda expression that selects a property from the viewmodel in which to clear the ModelState information</param>
/// <remarks>
/// Code from Tobi J at https://stackoverflow.com/questions/1775170/asp-net-mvc-modelstate-clear
/// Also see comments by Peter Gluck, Metro Smurf and Proviste
/// Finally, see Bradwils http://forums.asp.net/p/1527149/3687407.aspx.  
/// </remarks>
public static void RemoveStateFor<TModel, TProperty>(
    this ModelStateDictionary modelState, 
    TModel model,
    Expression<Func<TModel, TProperty>> propertyFetcher
) {
    var key = ExpressionHelper.GetExpressionText(propertyFetcher);

    modelState.Remove(key);
}
    
like image 66
pwilcox Avatar answered Sep 29 '22 11:09

pwilcox