Search code examples
asp.net-web-apiodataany

Enabling nested any queries on OData V4 endpoints with WebAPI


I'm trying to build a nested any query like this ...

~/Api/Calendar?$filter=Roles/any(r:r/User/any(u:u/Name eq 'Joe Bloggs'))

if I remove the inner any clause leaving me with ...

~/Api/Calendar?$filter=Roles/any(r:r/User/any())

... then the endpoint returns ...

{
    "error": {
        "code": "",
        "message": "The query specified in the URI is not valid. The Any/All nesting limit of '1' has been exceeded. 'MaxAnyAllExpressionDepth' can be configured on ODataQuerySettings or EnableQueryAttribute."
    }
}

... which I think lends some light on the problem but I actually have here.

So far I have tried to raise this limit with this during my context initialisation but it doesn't appear to be working ....

config.AddODataQueryFilter(new EnableQueryAttribute { MaxAnyAllExpressionDepth = 3 });

does anyone have any ideas how I can do this globally (i don't want to have to go to every get action on every controller and set the depth.

UPDATE:

So it turns out where I inherit from my own baseEntityController, on the actions I had the EnableQuery attribute which superceeded my global config change hense the reason my changes were not respected.

Simply removing the attribute from the actions themselves has all controllers that inherit from my base working with this new nested any and all limit, but i seem to now have the side effect that expands don't work any more ...

var query = new EnableQueryAttribute {
    MaxExpansionDepth = 8,
    PageSize = 100,
    MaxAnyAllExpressionDepth = 3,
    AllowedFunctions = System.Web.OData.Query.AllowedFunctions.All,
    AllowedLogicalOperators = System.Web.OData.Query.AllowedLogicalOperators.All,
    AllowedQueryOptions = System.Web.OData.Query.AllowedQueryOptions.All,
    AllowedArithmeticOperators = System.Web.OData.Query.AllowedArithmeticOperators.All,
    MaxTop = 1000
};
config.AddODataQueryFilter(query);

.. as you can see I tried throwing lots of extras in there but it's not having any of it!


Solution

  • The simplest way I found to do this and have everything work is to apply the attribute on the base controller actions, it therefore applied everything correctly to the actions on that controller or any of it's derived types.

    It wasn't my ideal but I couldn't find a way to get a global fix for this to work as part of initialising the odata context.

    Hopefully this will help someone out there.