locked
A Bug? EditorFor and DisplayFor don't display same value - EditorFor out of date RRS feed

  • Question

  • User-1542195628 posted

    I came across a bizarre situation where I am incrementing a simple int value on a model and EditorFor was failing to display the updated value.  I was working in MVC 2 Preview 2 but downloaded and verified the same behavior in RC2.  Before I report this as a bug, I just wanted to see if there was any reason this should be considered correct behavior.

    To Reproduce:

    Create a new MCV 2 web application.

    Under Models, create the following model:


    namespace MvcApplication1.Models
    {
        public class TestModel
        {
            public int Value { get; set; }
        }
    }
    

    Under the Views/Home directory add create a view called Test.aspx containing the following markup:


    <%@ Page Title="" Language="C#" MasterPageFile="~/Views/Shared/Site.Master" Inherits="System.Web.Mvc.ViewPage<MvcApplication1.Models.TestModel>" %>
    <asp:Content ID="Content2" ContentPlaceHolderID="MainContent" runat="server">
        <%using(Html.BeginForm("Test", "Home")){%>
        <h2>Test</h2>
        Display: <%=Html.DisplayFor(m => m.Value) %>
        Edit: <%=Html.EditorFor(m => m.Value) %>
        <input type="submit" />
        <%} %>
    </asp:Content>


    In the HomeController add the following two methods:


            [AcceptVerbs(HttpVerbs.Get)]
            public ActionResult Test(int id)
            {
                return View(new TestModel { Value = id });
            }
    
            [AcceptVerbs(HttpVerbs.Post)]
            public ActionResult Test(TestModel model)
            {
                model.Value++;
                return View(model);
            }


    Finally, run the application and navigate to /Home/Test/1

    You should see output like:

    Display: 1 Edit: [1                                        ] [Submit Query]

    Hit submit and you will see output like:

    Display: 2 Edit: [1                                        ] [Submit Query]

    The model correctly incremented the value and DisplayFor correctly rendered the model.  However, EditorFor rendered the old value.  I didn't dig into why it did this but, at a guess it seems to be an issue with an out of date value in the ModelMetaData or similar.

    Thoughts?





    Thursday, February 18, 2010 10:14 AM

Answers

  • User197322208 posted

    <Disclaimer : I should look into source code Innocent>

    The difference between editor and display is that the editor is a textbox, and the textbox is POST-ed .

    So, I think that when POST-ed, the editor have the values from POST data(usually you do not change the users values on POST ... but put into the database...), and the display from the model ( because there are no POST-ed fields from where the values should come from)

    • Marked as answer by Anonymous Thursday, October 7, 2021 12:00 AM
    Thursday, February 18, 2010 4:52 PM
  • User-1032240251 posted

    The difference between editor and display is that the editor is a textbox, and the textbox is POST-ed .

    So, I think that when POST-ed, the editor have the values from POST data(usually you do not change the users values on POST ... but put into the database...), and the display from the model ( because there are no POST-ed fields from where the values should come from)

    This is correct. This behavior is identical to the MVC 1.0 behavior.

    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.

    • Marked as answer by Anonymous Thursday, October 7, 2021 12:00 AM
    Thursday, February 18, 2010 5:00 PM
  • User-1005219520 posted

    Awesome work ignatandrei

    Eilon says "The stuff in the EditorFor is using ModelState to shows its values, which takes precedence over ViewData."


    • Marked as answer by Anonymous Thursday, October 7, 2021 12:00 AM
    Thursday, February 18, 2010 10:18 PM
  • User-1032240251 posted

    To make sure I fully understand the implications here, would a good rule of thumb be that the controller should clear the model state once it has confirmed that the state is valid, in order to ensure that updated values get sent back to the browser?  The example I gave was very simple but the intended behavior is that when the user submits data, the changes are integrated with any changes made elsewhere to the record and that these integrated results be displayed.

    Yes, clearing the ModelState works.

    Personally, I prefer never to render success pages as the result of a POST operation, for caching and history reasons. If you were to Redirect at the end of a successful update operation -- even if you redirected to the exact same URL -- then you would also solve this problem, and get better caching and history behavior as well.

    • Marked as answer by Anonymous Thursday, October 7, 2021 12:00 AM
    Monday, February 22, 2010 10:56 AM

All replies

  • User-1542195628 posted

    In my effort to work around this issue I added the following hidden inputs to the above view.

        <%=Html.Hidden("Value") %> <!-- Renders old value -->
        <%=Html.Hidden("Value", Model.Value) %> <!-- Renders old value -->
        <%=Html.Hidden("Value", "Not a Number") %> <!-- Renders old value !! -->
        <%=Html.Hidden("Test", Model.Value) %>  <!-- Renders new value -->
        <%=Html.Hidden("Test", "Not a Number")%>  <!-- Renders "Not a Number" -->
    

    After running the modified code and clicking submit as described above, I viewed the source of the rendered HTML.  As indicated by the comments, Html.Hidden() ignored the second argument passed any time the first argument matched the name of a property on the model.   And like with EditorFor, it would also render the old value in these cases.

    Thursday, February 18, 2010 2:50 PM
  • User197322208 posted

    <Disclaimer : I should look into source code Innocent>

    The difference between editor and display is that the editor is a textbox, and the textbox is POST-ed .

    So, I think that when POST-ed, the editor have the values from POST data(usually you do not change the users values on POST ... but put into the database...), and the display from the model ( because there are no POST-ed fields from where the values should come from)

    • Marked as answer by Anonymous Thursday, October 7, 2021 12:00 AM
    Thursday, February 18, 2010 4:52 PM
  • User-1032240251 posted

    The difference between editor and display is that the editor is a textbox, and the textbox is POST-ed .

    So, I think that when POST-ed, the editor have the values from POST data(usually you do not change the users values on POST ... but put into the database...), and the display from the model ( because there are no POST-ed fields from where the values should come from)

    This is correct. This behavior is identical to the MVC 1.0 behavior.

    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.

    • Marked as answer by Anonymous Thursday, October 7, 2021 12:00 AM
    Thursday, February 18, 2010 5:00 PM
  • User-1005219520 posted

    Awesome work ignatandrei

    Eilon says "The stuff in the EditorFor is using ModelState to shows its values, which takes precedence over ViewData."


    • Marked as answer by Anonymous Thursday, October 7, 2021 12:00 AM
    Thursday, February 18, 2010 10:18 PM
  • User-1542195628 posted

    To make sure I fully understand the implications here, would a good rule of thumb be that the controller should clear the model state once it has confirmed that the state is valid, in order to ensure that updated values get sent back to the browser?  The example I gave was very simple but the intended behavior is that when the user submits data, the changes are integrated with any changes made elsewhere to the record and that these integrated results be displayed.

    Monday, February 22, 2010 6:47 AM
  • User-1032240251 posted

    To make sure I fully understand the implications here, would a good rule of thumb be that the controller should clear the model state once it has confirmed that the state is valid, in order to ensure that updated values get sent back to the browser?  The example I gave was very simple but the intended behavior is that when the user submits data, the changes are integrated with any changes made elsewhere to the record and that these integrated results be displayed.

    Yes, clearing the ModelState works.

    Personally, I prefer never to render success pages as the result of a POST operation, for caching and history reasons. If you were to Redirect at the end of a successful update operation -- even if you redirected to the exact same URL -- then you would also solve this problem, and get better caching and history behavior as well.

    • Marked as answer by Anonymous Thursday, October 7, 2021 12:00 AM
    Monday, February 22, 2010 10:56 AM