views:

604

answers:

2

This is a really strange behavior, and I've set up some demo code to try to figure out what's going on.

Basically have a a two actions and a single view. The first action sends an empty model to the view, the section action recieves the model, alters its contents and sends it back to the same view.

The wierdness is, in the view, the Model seems to have the updated values in it, but when I do an Html.TextBoxFor(x => x.PropertyNameHere) it renders a textbox with the unaltered value in it.

lol... I apologize in advance for the toilet humor, but it keeps the day from getting too boring. ;)

Does anyone have any idea what's going on here? Why is the output of TextBoxFor putting the old value in the value attribute?

Here's the code to replicate:

/Views/Demo/Index.aspx

<%@ Page Language="C#" Inherits="System.Web.Mvc.ViewPage<TestWeb.DemoModel>" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"&gt;
<html xmlns="http://www.w3.org/1999/xhtml" >
<head runat="server">
    <title>Demo</title>
</head>
<body>
    <div>
      <%using (Html.BeginForm("DemoSubmit", "Admin", FormMethod.Post)) { %>
        Foo: <%=Html.TextBoxFor(x => x.Foo)%> <%:Model.Foo %><br />
        Bar: <%=Html.TextBoxFor(x => x.Bar) %> <%:Model.Bar %><br />
        PoopSmith: <%=Html.TextBoxFor(x => x.PoopSmith) %> <%:Model.PoopSmith %><br />
        <button type="submit">Submit</button>
      <%} %>
    </div>
</body>
</html>

DemoModel.cs

namespace TestWeb {
    public class DemoModel {
        public string Foo { get; set; }
        public int Bar { get; set; }
        public string PoopSmith { get; set; }
    }
}

DemoController.cs

public class AdminController : Controller {

        public ActionResult Index() {
            var m = new DemoModel();
            return View(m);
        }

        public ActionResult DemoSubmit(DemoModel demo) {
            demo.Foo += "!!!";
            demo.Bar++;
            demo.PoopSmith += " has pooped.";
            return View("Index", demo);
        }
}

And here's the bizarre output:

Bizarre

+1  A: 

Default Html helper try to redisplay the data that is posted to them. They first use the value from posted data and if no posted data is available they take the data from the Model.

This is not what you want obviously, but still the most common usage: You display some data in formfields after receiving a get request. You post to an Update action. If you have errors you want to redisplay the form with the values you entered still available.

I have seen some people getting around this (I think by writing to ModelState), but my choice was always to not use the default helpers if they dont help me. Thats especially true for hidden fields: Most people get confused when they set a value to a hidden field but the value that is realy used is from the post. At least there is a question every other day about it on SO :-)

Forget the "Most people" and replace it with "Everybody".

http://stackoverflow.com/questions/2019131/asp-net-mvc-hidden-field-value-does-not-get-rendered-using-htmlhelper-hidden

http://blog.johnwest.com/post/ASPNET-MVC-Hidden-Form-Field-Bug.aspx

http://blogs.msdn.com/b/simonince/archive/2010/05/05/asp-net-mvc-s-html-helpers-render-the-wrong-value.aspx?utm_medium=Twitter&amp;utm_source=Shared

UPDATE Oh I found another one from today (You are not alone):

http://stackoverflow.com/questions/2924057/how-to-update-textbox-value

Malcolm Frexner
+1 LOL! Your search skills are superior to mine! That makes sense, thanks for the answer.
blesh
A: 

Do ModelState.Clear(); in your controller to prevent this happening.

Sander