3

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>
Josh
  • 805
  • 10
  • 22

1 Answers1

2

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();
    }
}
zoe
  • 849
  • 6
  • 7
  • Thanks. My main question is: how can I do this with a post directly to ChildController? This is a refactor so I am trying to maintain existing web service behavior. – Josh Jun 02 '14 at 15:13
  • Hi Josh, can you share your request url and body? If you don't want do post to ParentController, why is there a navigation link? Or is child.Parent.Id what you want? – Feng Zhao Jun 03 '14 at 01:18
  • Hi @Feng, I updated above with the request. I don't mind a post to Parent as an additional point of entry, however it would be nice to maintain the existing ability to post to Child as a top-level entity. This is happening in a couple of different places in our API, and it would be nice to avoid a refactor of the API consumer, and it would be nice to have the ability in general I guess. In answer to your other question, yes, child.Parent.Id is definitely what I am trying to get ahold of, so that I can create the entity and tie it to the appropriate parent. Thanks in advance for any ideas! – Josh Jun 03 '14 at 16:24