Html.TextBoxFor does not show updated value in POST action

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);
}
    

Instead of using model binding, id suggest using a tryupdate call.

[HttpPost]
public ActionResult Manipulation(FormCollection formCollection)
{
  MyModel model = new MyModel();

  if(TryUpdate(Model))
  {
      enter code here
  }

  if(somthing)
  model.IPAddress="100.100.100.100";
  return View(model);
}

Check out my answer to another post for the general structure i use. Its never failed me before and i believe it covers all bases when updating models from user input.

asp.net mvc controller post best practices


Try:

ModelState.Clear();
return View(model);

If not result! return a JSON Result and then update by javascript

Tags:

Asp.Net Mvc