@odata.bind and the v4 spec

Topics: ASP.NET Web API
Oct 17, 2014 at 8:20 AM
According to the OData v4 spec, I should be able to link to a related entity when I created an entity. For example, if I create something that should belong to group#5:

{
"Name": "This is a test",
"Group@odata.bind": "http://.../group(5)"
}

However, this doesn't seem to work. I think I'm right in saying it's not implemented? If so, is there somewhere where we can see what parts of the spec are implemented and those that aren't? It makes it very difficult to plan ahead when you come across these gaps as you go.

Related; if odata.bind isn't implemented, how best can I create an entity with these links? I've seen it suggested that I do it as a changeset (Create > CreateRef), but I can't do this if the property is marked as required.
Oct 21, 2014 at 9:11 AM
I don't mean to sound rude, but how is this discussion forum so dead? It seems like a fairly important technology for Microsoft and yet it's virtually impossible to get any responses to even the most basic of questions.
Oct 22, 2014 at 8:31 PM
Edited Oct 22, 2014 at 8:33 PM
I've been looking for this exact behaviour myself, and I can confirm that they have not implemented it - it has been mentioned on the forums previously (here), and looking at the code today I see there has been no attempt to implement the behaviour yet. Deep inserts appear to be supported (creating the Group as part of the insert of the related item), but the link to related entity functionality is intentionally left blank at this time.

I have no idea if anyone maintains a list of supported and unsupported functionality. The OData team's email has been down for a couple weeks, but when it's working they're generally able to answer questions about what's supported and what's not.

In the meantime, I built my own. Perhaps you will find this useful. I was able to create a custom ODataEntityDeserializer and override the ApplyNavigationProperty method. I introduced an "IResolver" interface which I implement on my controller, keeping my database calls isolated to the controller level. In the controller's Initialize() override, I simply store a reference to the controller in the Request.Properties[] collection. I pull it out again here and call my ResolveReference() function, which does the application-specific database lookup and assigns the found entity to the appropriate property on the entityResource object (the in-progress deserialization result).
    public class ODataEntityWithReferencesDeserializer : ODataEntityDeserializer
    {
        public ODataEntityWithReferencesDeserializer(
            ODataDeserializerProvider deserializerProvider)
            : base(deserializerProvider)
        {
        }

        public override void ApplyNavigationProperty(object entityResource,
            ODataNavigationLinkWithItems navigationLinkWrapper,
            IEdmEntityTypeReference entityType, ODataDeserializerContext readContext)
        {
            // The base behaviour is good for "deep inserts",
            // but intentionally skips references.
            base.ApplyNavigationProperty(entityResource,
                navigationLinkWrapper, entityType, readContext);

            var resolver = (IResolver)readContext.Request.Properties["MyResolver"];
            if (resolver == null)
            {
                return;
            }

            foreach (var childItem in navigationLinkWrapper.NestedItems)
            {
                var entityReferenceLink = childItem as ODataEntityReferenceLinkBase;
                if (entityReferenceLink != null)
                {
                    resolver.ResolveReference(entityResource,
                        navigationLinkWrapper.NavigationLink.Name,
                        entityReferenceLink.EntityReferenceLink.Url);
                }
            }
        }
    }
Hope this helps.
Dec 15, 2014 at 2:09 PM
Hello pschmiedge,

Thank you for the detailed answer, this is a huge help and eliminates the need of further researches and reverse-engineering :)

Do you know if this feature is on the product backlog? We would be able to align our features accordingly :)

Thank you for your kind help, have a nice day,
Robert Bonay
Dec 16, 2014 at 8:14 PM
Hi Robert,

I'm glad my code was able to help you solve a problem!

Unfortunately, I have no deep insight into what the OData backlog looks like - my insight about how much work has been done in the codebase that handles this particular problem was gleaned simply by browsing the source tree here on CodePlex while trying to solve the problem for myself. I took a look at the new issue log on the GitHub site they've set up, but it doesn't appear this issue has been raised there at this time.

Cheers,
Paul S.