Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

ASP.NET MVC rendering model not the way I expect

Tags:

c#

asp.net-mvc

Today I faced a problem and I'm not able to get weather I understand something wrong about ASP.NET MVC (and possibly MVC in general) or I miss something about it's implementation.

So, I have a simple model hierarchy:

public class Child
{
    public Child(int notId, bool isSelected, string text)
    {
        NotId = notId;
        IsSelected = isSelected;
        Text = text;
    }

    public Child(){}

    // naming: just to make sure I do not mess with some
    // conventional infrastructure
    public int NotId { get; set; }
    public bool IsSelected { get; set; }
    public string Text { get; set; }
}

public class Parent
{
    public List<Child> Children { get; set; } 
}

Here is my HomeController's Edit actions:

[HttpGet]
public ActionResult Edit()
{
    var parent = new Parent
                    {
                        Children = new List<Child>
                                {
                                    new Child(1, true, "a"),
                                    new Child(2, false, "b")
                                }
                    };
    return View(parent);
}

[HttpPost]
public ActionResult Edit(Parent parent)
{
    parent.Children = new List<Child>
                        {
                            new Child(4, false, "c"),
                            new Child(5, true, "d")
                        };
    return View(parent);
}

Hese is my Edit.aspx view:

<!-- Standart HTML elements ommited --> 
<% Html.BeginForm(); %>
<% for (var i = 0; i < Model.Children.Count; i++){%>
<div>
    <%=Html.LabelFor(m => m.Children[i].IsSelected)%>
    <%=Html.EditorFor(m => m.Children[i].IsSelected)%> <!-- lamda -->
    <%=Html.CheckBoxFor(m => m.Children[i].IsSelected)%> <!-- lamda -->
    <%=Html.CheckBox("A", Model.Children[i].IsSelected)%> <!-- simple -->
</div>
<% } %>

<input type="submit" value="Submit" />
<% Html.EndForm();%>

The point is that in Edit (HttpGet) method I create Parent instance with two child Child elements having their IsSelected properties set to true and false respectively. After form is submitted in Edit (HttpPost) method I give my Parent object a new children collection of two Child elements with their IsSelected properties set to false and true respectively (that is opposite from HttpGet method) and call View() method to render my model.

But what I get after submit is checkboxes, rendered with Html.EditorFor() and Html.CheckBoxFor() do not changes their state. It looks like Html.EditorFor() and Html.CheckBoxFor() methods take data NOT from my model but from a posted form data.

Could someone please explain me what is going on here and why ASP.NET MVC refuses to render my model? Workarounds? Fixes to my code?

Thanks in advance.

P.S. I noticed this behavior in MVC2 and thought this was some kind of a bug, but when I tested this with MVC3 it did the same thing.

like image 940
Ramunas Avatar asked Nov 04 '22 13:11

Ramunas


1 Answers

But what I get after submit is checkboxes, rendered with Html.EditorFor() and Html.CheckBoxFor() do not changes their state. It looks like Html.EditorFor() and Html.CheckBoxFor() methods take data NOT from my model but from a posted form data.

That's exactly what they do and that's by design. Html helpers first look at modelstate when binding values and then the model. If you want to change this behavior you could remove all the items from model state that you intend to modify in your controller action:

[HttpPost]
public ActionResult Edit(Parent parent)
{
    ModelState.Remove("Children");
    parent.Children = new List<Child>
    {
        new Child(4, false, "c"),
        new Child(5, true, "d")
    };
    return View(parent);
}
like image 65
Darin Dimitrov Avatar answered Nov 11 '22 14:11

Darin Dimitrov