If you have posted back a form to an MVC action method and want to update some of the bound viewModel properties in that action method before redisplaying the same view, you might run into a problem whereby your HTML helpers are displaying the values as posted at binding time, but not as they were after manipulation.
Just before calling the view statement or indeed in the razor markup itself you can set a breakpoint and verify your viewModel/model have the updated values but still the old values render. This is because MVC assumes that if you’re rendering a view in response to an HTTP POST then you’re likely to be redisplaying a form that has failed validation. Since some data entered by the user and posted back may not be compatible with the model (i.e. posting a decimal number back when the corresponding model property is int) and thus MVC can’t store them in the model it stores all binded values into ModelState and looks in that before the model when rendering a view using HTML helpers such as TextBoxFor.
Example of HTML helper using ModelState not the model to render its value
For example below we can see what was posted (1) and the value of the viewModel/Model when sending it to the view (2). As we are using Html.TextBoxFor however, the rendered data is still showing ‘John’ and ‘Smith’.
Clearing ModelState so the model values will be used
The fix for this is to clear either ModelState completely as in 4a or just clear the ModelState properties which are relevant as in 4b images below. After clearing ModelState we can see that the manually updated properties are now displayed.
I’m not sure how known this behaviour is or how many problems it causes developers but it’s one to watch out for anyhow.
Related Links
Rick Strahl’s ‘ASP.NET MVC Postbacks and HtmlHelper Controls ignoring Model Changes‘ blog post describes this behaviour and also has a section on the rationale of having MVC work this way.
Simon Ince’s article ‘ASP.NET MVC’s Html Helpers Render the Wrong Value!’ offers a number of alternative approaches that you could use rather than clearing ModelState such as not using html helpers and implementing the Post-Redirect-Get pattern.