Search code examples
c#asp.netodata

.NET ODataController class to return collection of type strutcurally unrelated to type for controller


I have a class, MyClassController that inherits from ODataController. I've been able to use the "automagic" routing for access to properties of scaler collections types using, e.g., /path/to/MyClass(100)/SomeProperty. I now need to return a collection of a class that's structurally unrelated to MyClass (i.e., there are no references connecting the two classes) but logically, there's a relationship between the two. I'd like to be able to do something like GETting /path/to/MyClass(100)/RelatedThings/. How can I set that up? I'm setting up MyClass and its related classes using ODataConventionModelBuilder.EntitySet<> in the Application_Start.

I'm using Microsoft.OData.Core 6.13.0 (OData 4.0).

edit: I left out some details from this question that I didn't realize were relevant about some of the design decisions I'd made elsewhere in the application, so I accepted the answer that best solves this problem without taking those details into account. I ended up making a bound OData function in the MyClass controller that returned the related things. I found if I didn't include the namespace or a trailing slash, the HTTP requested yielded error. That is, /path/to/MyClass(100)/Default.RelatingThings/ works. I'm looking into ways to removing the need for the trailing slash and the namespace. (edit: Call config.EnableUnqualifiedNameCall(true) when setting up your OData routing; see https://stackoverflow.com/a/35156885/1102726.)


Solution

  • Your OData routes do not have to match the relationships in your storage schema; i.e., the lack of a structural relationship is irrelevant. Just add a property to MyClass similar to the following:

    public ICollection<Thing> RelatedThings { get; set; }
    

    Then define an action method for the property:

    public IQueryable<Thing> GetRelatedThings([FromODataUri] int key)
    {
        // Fill-in data access logic.
    }
    

    You won't be to request /path/to/MyClass(100)?$expand=RelatedThings, but you will be able to request /path/to/MyClass(100)/RelatedThings as you desire.