Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

OData POST entity creation with expand

Tags:

post

odata

expand

I'm attempting to create an instance of an entity and two child entities at the same time.

If I post the following JSON to the /user_objects resource it happily creates the parent user_object entity and the linked User_object_attribute entity. The only problem is that I can't seem to expand the result set to include the new user_object_attribute so I effectively have the most uptodate version of the user_object but I have to then go and read from the OData service i.e. another server hit in order to retrieve the user_object_attributes.

Upon returning I have the id that would go neatly into the child user_object_attribute object but what if the child had a further server-side generated field like created_date? Then I still have to hit the OData repo again?

I've tried the correct $expand query ?$expand=user_objects_attributes and while the creation succeeds I still am not returned the expanded result set.

Would anyone have any idea if this is possible? Or is it a case that it isn't because hte only way to do it would be to return all the child user_object_attributes?

{
   "annotator_id":1,
   "content_type":"content_type",
   "created_date":"2013-02-15T17:20:09.191",
   "guid":"GUID",
   "size_kb":100,
   "title":"Title",
   "updated_date":null,
   "url":"URL",
   "user_object_id":0,
   "user_objects_attributes":[
      {
         "attribute_id":0,
         "name":"name191",
         "user_object_id":0,
         "value":"value191"
      }
   ]
}

Thanks, Mark.

like image 830
Mark Gargan Avatar asked Feb 15 '13 17:02

Mark Gargan


2 Answers

Looking at the OData V3 specification here:

In version 1.0 and version 2.0, if the insert succeeds in full, the server MUST return a response with a 201 (Created) status code and a response body that conforms to the syntax specified in InsertEntity Request (section 2.2.7.1.1). The response body MUST contain the values of the inserted resource after the server has executed all its server-specific data processing rules (validation, and so on). The server MAY alter the values of the resource received from the client before the resource is inserted on the server.

In version 3.0, the response MAY have a 204 status code, as specified in [RFC2616], based on the client preference (see Prefer (section 2.2.5.9)) on the InsertEntity Request.

Not super clear what a server should do... return just the top level created entity, or that entity and all of it's expanded links as well.

I'm not surprised that $expand would have no effect on POST (or any CUD requests). WCF DS probably ignores it if it isn't a query. And by the spec, this is probably correct.

Quite frankly, I think with WCF DS Server you can't get anything else back. In V3 you either get a 201 with your entity (only), or a 204 no content if you specify the header saying that you want no content.

Whether that is OData compliant or not... not totally sure :-). Regardless, I don't think you can get what you want on the WCF DS stack at this point in time.

like image 182
Ian Michael Williams Avatar answered Oct 21 '22 19:10

Ian Michael Williams


I was able to return navigation properties after a POST to create a new entity using OData v4's $expand query option without issues.

Make sure your method is decorated with [EnableQuery] and you call Include with the name of the navigation property.

For example:

[EnableQuery]
public IHttpActionResult Post(user_object user)
{
    if (!this.ModelState.IsValid)
    {
        return this.BadRequest(this.ModelState);
    }

    this.db.user_objects.Add(user);
    this.db.SaveChanges();

    user = this.db.user_objects.Include("user_objects_attributes").Single(x => x.user_object_id == user.user_object_id));

    return this.Created(user);
}

The POST URL query string should include ?$expand=user_objects_attributes.

Also see:
https://github.com/OData/WebApi/issues/356

like image 37
Rami A. Avatar answered Oct 21 '22 18:10

Rami A.