Update of an object and related records with Backbone.js and .NET MVC
December, 24th 2011 | .NET
As previously mentioned, I'm working with Backbone.js.
In particular, I had the need to send to the server-side module, powered by .NET MVC, a complex JSON data structure, as follows:
Invoice: {
...
InvoiceDetails: [{
...
}, {
...
}, ...]
}
By posting data to the service for insert, no problem: everything works fine.
[ActionName("Index")]
[HttpPost]
public JsonResult Post(Invoice invoice)
{
db.Invoices.AddObject(invoice);
db.SaveChanges();
return Json(invoice);
}
The update function was, in the first instance, implemented as follows:
[ActionName("Index")]
[HttpPut]
public JsonResult Put(Invoice invoice)
{
db.Invoices.Attach(invoice);
db.ObjectStateManager.ChangeObjectState(invoice, EntityState.Modified);
db.SaveChanges();
return Json(invoice);
}
The operation, however, was different from what we can image. The only changed record, in fact, was the record of the class Invoice. The InvoiceDetails remained unchanged.
This is because, as shown in the official documentation, the method ChangeObjectState acts only on the object passed as a parameter and not on those related to it.
Changing the state of an object does not affect related objects in the object graph..So I realized the logic to respond to my needs.
To be honest I'm not entirely satisfied by this solution but it is very effective.
In any case I might decide to act differently but I think the following code can be useful to other developers and I thought I'd share it:
[ActionName("Index")]
[HttpPut]
public JsonResult Put(Invoice invoice)
{
Invoice originalInvoice = db.Invoices.Single(i => i.Id == invoice.Id);
db.ApplyCurrentValues<invoice>("Invoices", invoice);
IEnumerable<int> invoiceDetailsId = invoice.InvoiceDetails.Select(i => i.Id);
IEnumerable<invoicedetail> invoiceDetailsToDelete = originalInvoice.InvoiceDetails.Where(i => !invoiceDetailsId.Contains(i.Id));
foreach (InvoiceDetail invoiceDetail in invoiceDetailsToDelete.ToList())
{
db.ObjectStateManager.ChangeObjectState(invoiceDetail, EntityState.Deleted);
}
IEnumerable<int> originalInvoiceDetailsId = originalInvoice.InvoiceDetails.Select(i => i.Id);
IEnumerable<invoicedetail> invoiceDetailsToAdd = invoice.InvoiceDetails.Where(i => !originalInvoiceDetailsId.Contains(i.Id));
foreach (InvoiceDetail invoiceDetail in invoiceDetailsToAdd.ToList())
{
originalInvoice.InvoiceDetails.Add(invoiceDetail);
}
IEnumerable<invoicedetail> invoiceDetailsToUpdate = invoice.InvoiceDetails.Where(i => originalInvoiceDetailsId.Contains(i.Id));
foreach (InvoiceDetail invoiceDetail in invoiceDetailsToUpdate.ToList())
{
db.ApplyCurrentValues<invoicedetail>("InvoiceDetails", invoiceDetail);
}
db.SaveChanges();
return Json(originalInvoice);
}