Lucent Fox
Lucent Fox

Reputation: 1795

Create, Update, Delete Child Entities With .net WebAPI

To update an entity, I'm using http PUT, passing the updated object as the request body:

PUT /api/flareform/3

{
    "JobId" : "12-12-4004",
    "Id" : 3,
    "Tasks" : [
      {
        "Hazard" : "Clumsyness",
        "Id" : 2,
        "FlareFormId" : 3,
        "Task" : "Hammering",
        "Control" : "Make Someone Else Hold the Nail"
      },
      {
        "Hazard" : "Nails",
        "Id" : 3,
        "FlareFormId" : 3,
        "Task" : "Walking",
        "Control" : "Keep area clean."
      }
    ],
    "PercentComplete" : null,
    "Time" : "3pm",
    "Initials" : "JD"
}

This is working correctly if I update a simple property of the object, like the Initials. Is it possible/how do I update, add, delete Tasks. Can do it through this object? What I'd like to do is just pass an updated array of Tasks and have it update/delete/add everything:

PUT /api/flareform/3

{
    "JobId" : "12-12-4004",
    "Id" : 3,
    "Tasks" : [
      {
        "Hazard" : "NewAndImprovedValue",
        "Id" : 2,
        "FlareFormId" : 3,
        "Task" : "NewAndImprovedValue",
        "Control" : "NewAndImprovedValue"
      },
      {
        "Hazard" : "SomeNewItemThatDidntExistBefore",
        "FlareFormId" : 3,
        "Task" : "NoteTheMissingId",
        "Control" : "ShouldAddThisOne"
      }
    ],
    "PercentComplete" : null,
    "Time" : "3pm",
    "Initials" : "JD"
}

Upvotes: 2

Views: 3189

Answers (2)

Lucent Fox
Lucent Fox

Reputation: 1795

Here's more or less what I ended up using. I'm trying to write this in a more generic way so that I don't have to copy/paste this code for each child property that needs to be updatable...

    // PUT api/FlareForm/5
    public HttpResponseMessage PutFlareForm(int id, FlareForm flareform)
    {
        if (!ModelState.IsValid)
        {
            return Request.CreateErrorResponse(HttpStatusCode.BadRequest, ModelState);
        }

        if (id != flareform.Id)
        {
            return Request.CreateResponse(HttpStatusCode.BadRequest);
        }


        List<int> previousIds = db.FlareForms.AsNoTracking().FirstOrDefault(ff => ff.Id == id).Tasks.Select(t => t.Id).ToList();
        List<int> currentIds = flareform.Tasks.Select(t => t.Id).ToList();
        List<int> deletedIds = previousIds
            .Except(currentIds).ToList();


        foreach (var deletedId in deletedIds)
        {
            FlareFormTask task = db.FlareFormTasks
                .Single(od => od.FlareFormId == flareform.Id && od.Id == deletedId);

            db.Entry(task).State = EntityState.Deleted;
        }

        foreach (var task in flareform.Tasks)
        {
            if (task.Id == 0)
            {
                task.FlareFormId = flareform.Id;
                db.Entry(task).State = EntityState.Added;
            }
            else
            {
                db.Entry(task).State = EntityState.Modified;
            }
        }


        db.Entry(flareform).State = EntityState.Modified;

        try
        {
            db.SaveChanges();
        }
        catch (DbUpdateConcurrencyException ex)
        {
            return Request.CreateErrorResponse(HttpStatusCode.NotFound, ex);
        }

        return Request.CreateResponse(HttpStatusCode.OK);
    }

Upvotes: 1

Sn&#230;bj&#248;rn
Sn&#230;bj&#248;rn

Reputation: 10792

Your Json object looks okay. I believe the culprit to be your DAL. As saving child entities isn't as straight forward as one should think.

I'm assuming your Tasks are in a one to many relationship with the main object. If so you'll need to manually detect any changes (added, deleted or modified) and apply them.

This tutorial should get you started: http://www.entityframeworktutorial.net/update-one-to-many-entities-in-entity-framework.aspx

Upvotes: 2

Related Questions