Search code examples
asp.net-web-apiodata

How do I expose a navigation property over OData 4 and WebApi 2.2?


I have a navigation property on a model, Site.Locality and although its foreign key is serialized and available to consumers (Site.LocalityName) I'd like the locality itself to be available from:

~/Site('A')/Locality

How is this done in OData v4 over WebApi 2.2?


Solution

  • On your controller for the Site entity, add the following action:

    // Implies that the controller has [ODataRoutePrefix("Sites")]
    
    [ODataRoute("({name})/Locality")]
    public async Task<Locality> GetLocality([FromODataUri] string name)
    {
        // Add try-catch or null 404 handling.
    
        var site = await this.Repository.GetAsync(new[] { name });
    
        return site.Locality;
    }
    

    Obviously, place your own DAL code in there, this is just an example.

    It's very clear to see that this is achieved through nothing more complex than a simple route and action on your controller.

    That said, there is some mapping happening under the hood. For example, you couldn't just expose any arbitrary navigation property:

    [ODataRoute("({name})/Wangachop")]
    public string GetWangachop([FromODataUri] string name)
    {
        return "Wangaaa!";
    }
    

    Would yield:

    The path template 'Sites({name})/Wangachop' on the action 'GetWangachop' in controller 'Sites' is not a valid OData path template. Found an unresolved path segment 'Wangachop' in the OData path template 'Sites({name})/Wangachop'.