Search code examples
asp.net-web-api2odataasp.net-web-api-odata

ODataRoutePrefix not working for 3rd level


When I try to use a third level segment with [ODataRoutePrefix] attribute it throws an error like this:

The path template '[TEMPLATE]' on the action 'Get' in controller 'CONTROLLER-NAME' is not a valid OData path template. Found an unresolved path segment '[LAST-SEGMENT]' in the OData path template '[TEMPLATE]'.

Details

  • ODataRoutePrefix for the parent segment that works: [ODataRoutePrefix("lawsuits/{parentId}/depositsGuarantees")]
  • ODataRoutePrefix for the new controller that DOES NOT work: [ODataRoutePrefix("lawsuits/{parentId}/depositsGuarantees/{subResourceId}/customFields")]
  • Error message when starting up the API (config.EnsureInitialized()): The path template 'lawsuits/{parentId}/depositsGuarantees/{subResourceId}/customFields' on the action 'Get' in controller 'LawsuitDepositGuaranteeCustomFields' is not a valid OData path template. Found an unresolved path segment 'customFields' in the OData path template 'lawsuits/{parentId}/depositsGuarantees/{subResourceId}/customFields'.

Additional info

  • The action methods properly expect the parameters defined in the Route prefix. Example:
public IHttpActionResult Get(int parentId, int subResourceId)
{
    // [...]
}
  • Although it complained that "Found an unresolved path segment 'customFields'", the same segment works for other existing controllers with the prefix like the following: [ODataRoutePrefix("lawsuits/{parentId}/customFields")], which means there's a model registered on OData for the "customFields" segment.

Assemblies affected

OData WebApi lib 6.0.0


Solution

  • I've found what was the problem...

    The model for the depositsGuarantees segment was missing a collection property of the model registered for the customFields segment. In practice this property was missing :

    public IEnumerable<CustomFieldModel> CustomFields { get; set; }
    

    I still wonder if I should really use lawsuits/{parentId}/depositsGuarantees/{subResourceId}/customFields or just depositsGuarantees/{parentId}/customFields (even though depositsGuarantees is also a sub-resource), but this is more a conceptual discussion.