-->

MVC 4 textbox not updating on postback

2019-07-31 07:32发布

问题:

I have a form that uses a modelview object that is not updating a textbox value on postback of submitting a form. On submitting a form, I edit the property of an object that is binded to a textbox. When the form comes back, the object property is still changed, but the textbox value does not change. It's like the textbox value is cached and will not change. How do I fix this?

Textbox default value: ""

Textbox code:

@Html.TextBoxFor(m => m.Project.tNumber, new { @readonly = "readonly", @class = "readonly" })

Object property:

[Display(Name = "T Number")]
[DisplayFormat(ConvertEmptyStringToNull = false)]
public string tNumber { get; set; }

Controller Action Method:

[Authorize(Roles = "Admin, OrderEntryManager")]
[HttpPost]
public ActionResult Verify(string submit, OrderEntryEdit model)
{
    MembershipUser user = Membership.GetUser(User.Identity.Name);
    int userId = WebSecurity.GetUserId(User.Identity.Name);
    if (userId > 0)
    {
        if (ModelState.IsValid)
        {
            string ButtCommand = submit;
            switch (ButtCommand)
            {
                case "Create Order":
                if (model.CreateOrder(userId))
                {
                    ViewBag.Status = "success";
                    ViewBag.Message = "The order has been created.";
                }
                else
                {
                    ViewBag.Status = "error";
                    ViewBag.Message = "There was a problem in trying to create this order.";
                }
                default:
                    ViewBag.Status = "error";
                    ViewBag.Message = "Unrecognized form action.";
            }
        }
    }
    else
    {
        ViewBag.Status = "error";
        ViewBag.Message = "Unrecognized user.";
    }
    return View("Verify", model);
}

ViewModel method:

public class OrderEntryEdit : OrderEntry
{
    public OrderEntryEdit()
    {
        base.Project = new Project();
        base.ShipTo = new ShipTo();
        base.SoldTo = new SoldTo();
        base.Unit = new List<Unit>();
    }
    //method simplified, but is reaching this method
    public Boolean CreateOrder(int adminUserId = 0)
    {
        this.Project.tNumber = "T123456";
        return true;
    }
}

Textbox value: ""

Edit: replacing the code for textbox with this:

<input type="text" readonly="readonly" class="readonly" value="@Model.Project.tNumber" />

has fixed the problem. Apparently, the textbox is being cached. In short, don't use razor syntax, good old html works fine. I hope this helps someone else!

回答1:

The editors like TextBoxFor, DropDownListFor, etc. use the ModelState values instead of the values from the model you passed to the view. The ModelState contains the values that the user submitted with the form.

You can clear out the entire ModelState by calling ModelState.Clear() in your action. Then the editors will use the values from your model instead.

This is a bit counterintuitive. The explanation on this thread finally made sense to me.

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.