How do I update an OData entity and modify its navigation properties in one request?

Jeremy Bell picture Jeremy Bell · Sep 26, 2012 · Viewed 8.4k times · Source

I am trying to implement what I thought was a simple scenario using an OData service provided by WCF Data services (using the OData V3 application/json;odata=verbose payload format, for now. I may use the JSON Light format in the future). The basic scenario goes like this:

I have two entities:

class Person 
{ 
  public int ID { get; set; }
  public string Name { get; set; } 
  public virtual PersonCategory Category { get; set; }
}

class PersonCategory
{
  public int ID { get; set; }
  public string Description { get; set; }
  public virtual ICollection<Person> People { get; set; }
}

Now, I want to create a simple edit page for a Person. This edit page might have an input for the Name, and an input or drop-down for the Category of the Person.

So, the scenario goes:

  1. Code downloads the Person using $expand for the Category: GET /api.svc/People(1)?$expand=Category
  2. User edits both the person's Name property and their Category.
  3. Code for the page makes a single request to update that Person's Name and Category properties.

The key here is in "a single request". This is the part that I'm having trouble finding documentation for. I've seen examples where they split number 3 above into two requests. Something like this (I don't remember the exact format - I'm also not sure if you'd have to DELETE the Category link before doing the PUT):

PATCH /api.svc/People(1) with content: {"Name": "new name" }
PUT /api.svc/People(1)/$links/Category with content: { "url": "/api.svc/Categories(2)" }

But, I've also heard it said, but not demonstrated, that it's possible to implement this update as a single request with the change to the Category navigation property specified inline with the other changes to the Person entity. Could someone give me an example of how this might be done? Also, can you show me how it would be done with a many-to-many navigation property, as opposed to the one-to-many I've described above.

And finally, I'm currently using the verbose JSON format, V3. Would your answers to the questions above be different if I instead used the new JSON light format? If so, how?

Answer

Hans Malherbe picture Hans Malherbe · Oct 24, 2013

I found two ways to represent navigation properties inline:

application/json;odata=verbose - { "Name": "new name", "Category": { "__metadata": { "uri": "Categories(2)" }}}

application/json - { "Name": "new name", "[email protected]": "Categories(2)" }