开发者

Why is a value that I update in my model inside an MVC3 controller not rendered on the client?

开发者 https://www.devze.com 2023-02-26 00:37 出处:网络
I have a controller action UpdateCustomer(CustomerDto customer) that returns a PartialViewResult with a model that is also a CustomerDto:

I have a controller action UpdateCustomer(CustomerDto customer) that returns a PartialViewResult with a model that is also a CustomerDto:

[HttpPost]
public PartialViewResult UpdateCustomer(CustomerDto customer)
{
    CustomerDto updatedCustomer = _customerService.UpdateCustomer(customer);
    updatedCustomer.Name = "NotThePostedName";
    return PartialView("CustomerData", updatedCustomer);
}

In my view, I have the following line:

@Html.TextBoxFor(model => model.Name)

So far, so good. In my view I do an asynchronous post to this action method, the model binder does its work and I can update a customer in the database. Then I want to render the updated customer to the client. For example, I'd like to change the customer name in my controller. However, wh开发者_运维百科at gets rendered is always the properties from the posted customer, not the properties from updatedCustomer.

I decided to include the MVC3 source code in my project to see what really happens. It appears to be a feature (bug?) of MVC3 that it always takes the value from ViewData.ModelState instead of the value from ViewData.Model.

This happens at lines 366-367 of System.Web.Mvc.Html.InputExtensions:

string attemptedValue =
    (string) htmlHelper.GetModelStateValue(fullName, typeof(string));
tagBuilder.MergeAttribute("value",
    attemptedValue ?? ((useViewData)
        ? htmlHelper.EvalString(fullName)
        : valueParameter), isExplicitValue);

As you can see, attemptedValue comes from ModelState. It contains the old value for CustomerDto.Name (the value that was posted to the controller action).

If this is a feature, why does it work this way? And is there a way to work around it? I would expect that if I update my model, the update gets rendered, not the old value I posted.


Well yes it's a feature (ModelState is always checked before actual Model), you can clear the ModelState, or update just the value you need:

ModelState["Name"].Value = updatedCustomer.Name;
0

精彩评论

暂无评论...
验证码 换一张
取 消