So here's a binding behavior in ASP.NET MVC that I didn't really get until today: HtmlHelpers 
controls (like .TextBoxFor() etc.) don't bind to model values on Postback, but rather get their value directly out of 
the POST buffer from ModelState. Effectively it looks like you can't change 
the display value of a control via model value updates on a Postback operation.  To demonstrate here's an example. I have a small section in a document where I display an editable email address:    This is what 
the form displays on a GET operation and as expected I get 
the email value displayed in both 
the textbox and plain value display below, which reflects 
the value in 
the mode. I added a plain text value to demonstrate 
the model value compared to what's rendered in 
the textbox. 
The relevant markup is 
the email address which needs to be manipulated via 
the model in 
the Controller code. Here's 
the Razor markup:        <div class="fieldcontainer">
            <label>
                Email:   <small>(username and <a href="http://gravatar.com">Gravatar</a> image)</small>
            </label>
            <div>
                @Html.TextBoxFor( mod=> mod.User.Email, new {type="email",@class="inputfield"})                         @Model.User.Email 
            </div>
        </div>
 
So, I have this form and 
the user can change their email address. On postback 
the Post controller code then asks 
the business layer whether 
the change is allowed. If it's not I want to 
reset the email address back to 
the old value which exists in 
the database and was previously store. 
The obvious thing to do would be to modify 
the model. Here's 
the Controller logic block that deals with that:// did user change email?
if (!string.IsNullOrEmpty(oldEmail) && user.Email != oldEmail)
{
    if (userBus.DoesEmailExist(user.Email))
    {
        userBus.ValidationErrors.Add("New email address exists already. Please…");
        user.Email = oldEmail;
    }
    else
        // allow email change but require verification by forcing a login
        user.IsVerified = false;
}… model.user = user;
return View(model);
The logic is straight forward - if 
the new email address is not valid because it already exists I don't want to display 
the new email address 
the user entered, but rather 
the old one. To do this I change 
the value on 
the model which effectively does this:model.user.Email = oldEmail;
return View(model);
So when I press 
the Save button after entering in my new email address (
[email protected]) here's what comes back in 
the rendered view:
 
Notice that 
the textbox value and 
the raw displayed model value are different. 
The TextBox displays 
the POST value, 
the raw value displays 
the actual model value which are different. 
This means that MVC renders 
the textbox value from 
the POST data rather than from 
the view data when an Http POST is active.
Now I don't know about you but this is not 
the behavior I expected - initially. This behavior effectively means that I cannot modify 
the contents of 
the textbox from 
the Controller code if using HtmlHelpers for binding. Updating 
the model for display purposes in a POST has in effect - no effect.
(Apr. 25, 2012 - edited 
the post heavily based on comments and more experimentation) 
What should 
the behavior be?
After getting quite a few comments on this post I quickly realized that 
the behavior I described above is actually 
the behavior you'd want in 99% of 
the binding scenarios. You do want to get 
the POST values back into your input 
controls at all times, so that 
the data displayed on a form for 
the user matches what they typed. So if an error occurs, 
the error doesn't mysteriously disappear getting replaced either with a default value or some value that you changed on 
the model on your own. Makes sense.
Still it is a little non-obvious because 
the way you create 
the UI elements with MVC, it certainly looks like your are binding to 
the model value:@Html.TextBoxFor( mod=> mod.User.Email, new {type="email",@class="inputfield",required="required" })
and so unless one understands a little bit about how 
the model binder works this is easy to trip up. At least it was for me. Even though I'm telling 
the control which model value to bind to, that model value is only used initially on GET operations. After that ModelState/POST values provide 
the display value.
Workarounds
The default behavior should be fine for 99% of binding scenarios. But if you do need fix up values based on your model rather than 
the default POST values, there are a number of ways that you can work around this.
Initially when I ran into this, I couldn't figure out how to set 
the value using code and so 
the simplest solution to me was simply to not use 
the MVC Html Helper for 
the specific control and explicitly bind 
the model via HTML markup and @Razor expression:
<input type="text" name="User.Email" id="User_Email" value="@Model.User.Email" />
And this produces 
the right result. This is easy enough to create, but feels a little out of place when using 
the @Html helpers for everything else. As you can see by 
the difference in 
the name and id values, you also are forced to remember 
the naming conventions that MVC imposes in order for ModelBinding to work properly which is a pain to remember and set manually (name is 
the same as 
the property with . syntax, id replaces dots with underlines).
Use 
the ModelState
Some of my original confusion came because I didn't understand how 
the model binder works. 
The model binder basically maintains ModelState on a postback, which holds a value and binding errors for each of 
the Post back value submitted on 
the page that can be mapped to 
the model. In other words there's one ModelState entry for each bound property of 
the model. Each ModelState entry contains a value property that holds AttemptedValue and RawValue properties. 
The AttemptedValue is essentially 
the POST value retrieved from 
the form. 
The RawValue is 
the value that 
the model holds.
When MVC binds 
controls like @Html.TextBoxFor() or @Html.TextBox(), it always binds values on a GET operation. On a POST operation however, it'll always used 
the AttemptedValue to display 
the control. MVC binds using 
the ModelState on a POST operation, not 
the model's value.
So, if you want 
the behavior that I was expecting originally you can actually get it by clearing 
the ModelState in 
the controller code:ModelState.Clear();
This clears out all 
the captured ModelState values, and effectively binds to 
the model. Note this will produce very similar results - in fact if there are no binding errors you see exactly 
the same behavior as if binding from ModelState, because 
the model has been updated from 
the ModelState already and binding to 
the updated values most likely produces 
the same values you would get with POST back values.
The big difference though is that any values that couldn't bind - like say putting a string into a numeric field - will now not display back 
the value 
the user typed, but 
the default field value or whatever you changed 
the model value to.
This is 
the behavior I was actually expecting previously. But - clearing out all values might be a bit heavy handed. You might want to fix up one or two values in a model but rarely would you want 
the entire model to update from 
the model.
So, you can also clear out individual values on an as needed basis:if (userBus.DoesEmailExist(user.Email))
{
    userBus.ValidationErrors.Add("New email address exists already. Please…");
    user.Email = oldEmail;
    ModelState.Remove("User.Email");                    
}
This allows you to remove a single value from 
the ModelState and effectively allows you to replace that value for display from 
the model.
Why?
While researching this I came across a post from Microsoft's Brad Wilson who describes 
the default binding behavior best in a forum post:
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.
If you don't want 
the old values in 
the editor, clear out 
the Model State. That's where 
the old value is stored and pulled from 
the HTML helpers.
There you have it. It's not 
the most intuitive behavior, but in hindsight this behavior does make some sense even if at first glance it looks like you should be able to update values from 
the model. 
The solution of clearing ModelState works and is a reasonable one but you have to know about some of 
the innards of ModelState and how it actually works to figure that out.© Rick Strahl, West Wind Technologies, 2005-2012Posted in  ASP.NET  MVC  
Tweet
!function(d,s,id){var js,fjs=d.getElementsByTagName(s)[0];if(!d.getElementById(id)){js=d.createElement(s);js.id=id;js.src="//platform.twitter.com/widgets.js";fjs.parentNode.insertBefore(js,fjs);}}(document,"script","twitter-wjs");
  (function() {
    var po = document.createElement('script'); po.type = 'text/javascript'; po.async = true;
    po.src = 'https://apis.google.com/js/plusone.js';
    var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(po, s);
  })();