TextBoxFor value not updating after post

2020-05-23 06:53发布

问题:

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?

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


回答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)



回答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)  


回答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



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