0

I have an MVC project and I have a case where i need to update a parent and multiple child entities at the same time. In the post action I am receiving "an attempt was made to remove a relationship between x and x however one of the relationship's foreign keys" which is strange, all I'm doing is update, I'm not droping any entity whatsoever. I am using Linq to SQL and MVC3. The pseudocode is like the following:

@model Project.Models.ParentModel

...

@using (Html.BeginForm()) {
@Html.Label("Parent property")
@Html.EditorFor(model => model.ParentProperty)

@foreach (var child in Model.Childs)
{
Html.RenderPartial("_EditChild", child)
// Which is nothing more than a label and an editor for a property like:
// @model Project.Models.ChildModel
// @Html.Label("Child property")
// @Hteml.EditorFor(model => model.ChildProperty)
}

...

}

The Action looks like:

public ActionResult Edit(int id, FormCollection collection)
{

var parent = new Parent();
TryUpdateModel(Parent()); // which updates the parent and the child properties correctly
dataContext.SubmitChanges();

}

Can anybody explaing this behavior. Once again, I'm not removing or dropping any child entities!

Amiram Korach
  • 13,056
  • 3
  • 28
  • 30
Mentor
  • 485
  • 1
  • 5
  • 18
  • I had some problems with editing in a partial view. Can you try without the partial view (editors directly within the foreach instead of the partial rendering)? – Nathalie Kellenberger Aug 30 '12 at 08:57
  • I have tried it with template editors but the same error! – Mentor Aug 30 '12 at 08:59
  • I have also tried this solution http://stackoverflow.com/questions/8894442/mvc-razor-view-nested-foreachs-model but the model binder wont bind the child entities. – Mentor Aug 30 '12 at 09:00

1 Answers1

0

The binding over a list can be pretty nasty, I had some problems with it myself. I modified my list editing code to work with childs and tested it, it worked and the data is correctly bound and visible in the post action:

@model MvcApplication2.Models.Parent

@using (Html.BeginForm())
{
    <table>
        @{
                <tr>
                    <td>
                        @Html.TextBoxFor(m => m.Text)
                        @Html.HiddenFor(m => m.ID)
                    </td>
                </tr>
                for (int i = 0; i < Model.Children.Count; i++)
                {
                            <tr>
                                <td>
                                    @Html.TextBoxFor(x => x.Children[i].Title)
                                    @Html.HiddenFor(x => x.Children[i].ID)
                                </td>
                            </tr>
                }
        }
    </table>
    <div class="button">
        <input class="submit" type="submit" name="btnSave" id="btnSave" value="Save" />
    </div>
}

Controller for my test looks like this:

[HttpGet]
public ActionResult EditingChildren()
{
    Parent parent = new Parent() { Text = "" };
    parent.Children = new List<Child>();
    parent.Children.Add(new Child() { Title = "" });
    parent.Children.Add(new Child() { Title = "" });
    parent.Children.Add(new Child() { Title = "" });
    return View(parent);
}

[HttpPost]
public ActionResult EditingChildren(Parent parent)
{
    // save parent with children
}

Editing my post about saving data back with linq to sql:

If you are not binding the ID on the view, it will be left empty in the object in the post method. That gives you troubles saving back the data. I usally bind therefore the ID to an hidden field so it will not be empty any more (view code above edited and added HiddenFor beneath TextBoxFor).

Have also a look about updating data with linq to sql on this website:

http://davedewinter.com/2009/04/07/linq-to-sql-updating-entities/ (under Attach an Entity, Change Properties, Update)

and this post: enter link description here

Community
  • 1
  • 1
  • Can you show me how you handle the update in the POST action? I use TryUpdateModel() method most of the time, but in this case it makes Child IDs 0 – Mentor Aug 30 '12 at 13:43
  • To save the object you have to use the Attach() method on the parent linq to sql object and then SubmitChanges() – Nathalie Kellenberger Aug 30 '12 at 14:52
  • This wont work because entities already exist in the database! – Mentor Aug 30 '12 at 16:21
  • I usally bind the ID property on the view in a hidden field for it will be posted back. I have edited my post, hope it helps. – Nathalie Kellenberger Aug 31 '12 at 06:02
  • Yep thats what I've done but no luck. Strangely though, even it does not update EntitySet correctly, it does to a List. So i had to do it the ugly way, iterate in the list and get rows from DB to update the properties. – Mentor Aug 31 '12 at 08:39