TextBoxFor value not updating after post

14,882

Solution 1

Use ModelState.Clear() before setting value

[AcceptVerbs(HttpVerbs.Post)]
public ActionResult Index(Repair r)
{
    ModelState.Clear(); //Added here
    r.Number = "New Value";
    return View(r);
}

Solution 2

When you post a model back to an ActionResult and return the same View, the values for the model objects are contained in the ModelState. The ModelState is what contains information about valid/invalid fields as well as the actual POSTed values. If you want to update a model value, you can do one of two things:

ModelState.Clear()

or

ModelState["Number"].Value = new ValueProviderResult("New Value", "New Value", CultureInfo.CurrentCulture)

Solution 3

From my dealings with the issue, I feel that this is by design bug in the framework. IMO:

@Html.TextBoxFor(x => x.Number) 

should NOT be taking the value from ModelState but rather directly from the model. At least this would be my expectation when I alter the model and return View(model).

ModelState.Clear() 

is not an answer because it sanitizes ModelState erasing ValidationSummary. Removing a key from ModelState is neither good because it removes ValidationSummary for that key.

ModelState["Number"].Value = 
new ValueProviderResult("New Value", "New Value", CultureInfo.CurrentCulture)

is correct but just too arcane. Thus, in such cases, my preference would be to use:

<input type="text" name="Number" id="Number" value="@Model.Number"/>

instead of

@Html.TextBoxFor(x => x.Number)  

Solution 4

If you find ModelState.Clear() to be too destructive, you can target only the item you are changing, while preserving the rest with ModelState.Remove()

[AcceptVerbs(HttpVerbs.Post)]
public ActionResult Index(Repair r)
{
    r.Number = "New Value";
    ModelState.Remove("Number");
    return View(r);
}

Also, it appears that it doesn't matter with either Remove() or Clear() whether you call that method before you update your model or after

Solution 5

Try this. You can put it in a base controller if you want. It's working well for me. It makes it so unobtrusive validation still works, yet values from the model show through properly as EXPECTED.

public class BaseController : Controller
{
    public override void OnActionExecuted(ActionExecutedContext context)
    {
        ModelState.ToList().Select(x => x.Value).ToList().ForEach(x => { x.AttemptedValue = null; x.RawValue = null; });

        // Do a bunch of stuff here if needed. Stuff like validation.
        base.OnActionExecuted(context);
    }
}
Share:
14,882

Related videos on Youtube

nishanth
Author by

nishanth

I code stuff

Updated on June 04, 2022

Comments

  • nishanth
    nishanth almost 2 years

    I have a simple strongly typed view, but I cant seem to update a textbox on my form after a post.

    Here is my model:

    public class Repair
      {
        public string Number { get; set; }      
      }
    

    And in my view is a TextBox:

       @Html.TextBoxFor(x => x.Number)
    

    I'm trying to update the textbox after a post to my controller:

     [AcceptVerbs(HttpVerbs.Post)]
            public ActionResult Index(Repair r)
            {
    
              r.Number = "New Value";
    
              return View(r);
    
            }
    

    Even though I'm setting Number to a new value, the text in the textbox does not change. What am I doing wrong?

  • nishanth
    nishanth over 10 years
    When trying to set the modelstate value, I get this error: Error 11 Cannot implicitly convert type 'string' to 'System.Web.Mvc.ValueProviderResult'
  • Tommy
    Tommy over 10 years
    @broke - updated it with the correct syntax. Here is the MSDN on the ValueProviderResult - msdn.microsoft.com/en-us/library/…. Thanks for the heads up!
  • bgx
    bgx almost 7 years
    If you don't use @Html.TextBoxFor() you have to also add all the validation attributes manually which is cumbersome
  • Storm Muller
    Storm Muller over 5 years
    This is the most complete answer IMO. ModelState.Clear() has so many side effects and they're not explained properly in the accepted answer.