Josh
Josh

Reputation: 815

How to POST an entity complete with navigational relationship in Web API OData?

I'm using ASP.NET Web API with OData. I'm trying to POST a Child entity, which has a relationship to a Parent (the parent already exists). When I post the entity (using WCF data service client and SetLink), I can see via Fiddler that it is adding a <link...href=[address of parent]> into the body of the request. This exact same request works against our WCF data service version of the service (we are migrating to Web API). However, this does not seem to translate anything into the Post method on the controller in Web API.

When posting the child to ChildController, how can I access the Parent's ID from the Post action on ChildController? I know the value is there in the request, but how can I get ahold of this value? The Child cannot be created without a Parent. Do I need to modify the controller action signature? Maybe there is some attribute I can use somewhere? From an API perspective, I would like to avoid adding ParentId directly to the Child entity if possible.

public class ChildController
{
    public HttpActionResult Post([FromBody]Child child)
    {
        //child.Parent is null here, but all other 
        //properties of Child are populated.
        //How can I get the Parent's ID from the POST request??
    }
}

public class Child
{
    public int Id { get; set; }
    public string Name { get; set; }
    public Parent Parent { get; set; }
}

public class Parent
{
    public int Id { get; set; }
    public IEnumerable<Children> Children { get; set; }
}

EDIT: Here is my request. I changed some of the names to protect the innocent (replaced host name, and entity names with parent/child):

POST https://localhost/MyWebService/Child HTTP/1.1
Content-Type: application/atom+xml
DataServiceVersion: 1.0;NetFx
MaxDataServiceVersion: 3.0;NetFx
Accept: application/atom+xml,application/xml
Accept-Charset: UTF-8
User-Agent: Microsoft ADO.NET Data Services

Host: localhost
Content-Length: 1048
Expect: 100-continue

<?xml version="1.0" encoding="utf-8"?>
<entry xmlns="http://www.w3.org/2005/Atom" xmlns:d="http://schemas.microsoft.com/ado/2007/08/dataservices" xmlns:m="http://schemas.microsoft.com/ado/2007/08/dataservices/metadata">
<category term="MyWebService.Entities.Child" scheme="http://schemas.microsoft.com/ado/2007/08/dataservices/scheme" />
<link rel="http://schemas.microsoft.com/ado/2007/08/dataservices/related/Parent" type="application/atom+xml;type=entry" title="Parent" href="https://localhost/MyWebService/Parents(1L)" />
<id />
<title /><updated>2014-05-30T16:07:28Z</updated><author><name /></author>
<content type="application/xml">
<m:properties>
<d:Content>content</d:Content>
<d:CreatedDate m:type="Edm.DateTime">0001-01-01T00:00:00</d:CreatedDate>
<d:Description>desc</d:Description>
<d:Enabled m:type="Edm.Boolean">true</d:Enabled>
<d:Id m:type="Edm.Int64">0</d:Id><d:TabName>tname</d:TabName>
</m:properties>
</content>
</entry>

Upvotes: 3

Views: 1325

Answers (1)

zoe
zoe

Reputation: 889

In order to post an entity from navigation link, you need to define your action in Parent Controller. Here is the code snippet:

public class ParentController
{
    public HttpActionResult PostToChildren(int key, [FromBody]Child child)
    {
        var parent = parents.single(p=>p.Id == key);
        if(parent != null)
        {
            parent.Children.Add(child);
            ChildController.Children.Add(child);
            return StatusCode(HttpStatusCode.NoContent);
        }
        else
            return BadRequest();
    }
}

Upvotes: 2

Related Questions