OData / WebApi

OData Web API: A server library built upon ODataLib and WebApi
https://docs.microsoft.com/odata
Other
854 stars 475 forks source link

Support annotations in $select/$expand #2333

Open ificator opened 3 years ago

ificator commented 3 years ago

With this commit Microsoft.OData.Core added support for annotations in $select/$expand, however this capability is not yet exposed for services utilizing Microsoft.AspNet.OData.

Current behaviour

The query string parsing done by Microsoft.OData.Core succeeds as expected, however the processing of the parsed segments fails in Microsoft.AspNet.OData:

"message": "The last segment 'AnnotationSegment' of the select or expand query option is not supported.",
"type": "Microsoft.OData.ODataException",
"stacktrace": "
   at Microsoft.AspNet.OData.Query.Expressions.SelectExpandPathExtensions.GetFirstNonTypeCastSegment(ODataPath path, Func`2 middleSegmentPredicte, Func`2 lastSegmentPredicte, IList`1& remainingSegments)
   at Microsoft.AspNet.OData.Query.Expressions.SelectExpandPathExtensions.GetFirstNonTypeCastSegment(ODataSelectPath selectPath, IList`1& remainingSegments)
   at Microsoft.AspNet.OData.Query.Expressions.SelectExpandBinder.ProcessSelectedItem(PathSelectItem pathSelectItem, IEdmNavigationSource navigationSource, IDictionary`2 currentLevelPropertiesInclude)
   at Microsoft.AspNet.OData.Query.Expressions.SelectExpandBinder.GetSelectExpandProperties(IEdmModel model, IEdmStructuredType structuredType, IEdmNavigationSource navigationSource, SelectExpandClause selectExpandClause, IDictionary`2& propertiesToInclude, IDictionary`2& propertiesToExpand, ISet`1& autoSelectedProperties)
   at Microsoft.AspNet.OData.Query.Expressions.SelectExpandBinder.ProjectElement(Expression source, SelectExpandClause selectExpandClause, IEdmStructuredType structuredType, IEdmNavigationSource navigationSource)
   at Microsoft.AspNet.OData.Query.Expressions.SelectExpandBinder.GetProjectionLambda(SelectExpandQueryOption selectExpandQuery)
   at Microsoft.AspNet.OData.Query.Expressions.SelectExpandBinder.Bind(Object entity, SelectExpandQueryOption selectExpandQuery)
   at Microsoft.AspNet.OData.Query.Expressions.SelectExpandBinder.Bind(Object entity, ODataQuerySettings settings, SelectExpandQueryOption selectExpandQuery)
   at Microsoft.AspNet.OData.Query.SelectExpandQueryOption.ApplyTo(Object entity, ODataQuerySettings settings)
   at Microsoft.AspNet.OData.Query.ODataQueryOptions.ApplySelectExpand[T](T entity, ODataQuerySettings querySettings)
   at Microsoft.AspNet.OData.Query.ODataQueryOptions.ApplyTo(Object entity, ODataQuerySettings querySettings)
   at Microsoft.AspNet.OData.EnableQueryAttribute.ApplyQuery(Object entity, ODataQueryOptions queryOptions)
   at Microsoft.AspNet.OData.EnableQueryAttribute.ExecuteQuery(Object responseValue, IQueryable singleResultCollection, IWebApiActionDescriptor actionDescriptor, Func`2 modelFunction, IWebApiRequestMessage request, Func`2 createQueryOptionFunction)
   at Microsoft.AspNet.OData.EnableQueryAttribute.OnActionExecuted(Object responseValue, IQueryable singleResultCollection, IWebApiActionDescriptor actionDescriptor, IWebApiRequestMessage request, Func`2 modelFunction, Func`2 createQueryOptionFunction, Action`1 createResponseAction, Action`3 createErrorAction)"

Open questions

In order to scope the required work it would help to have clarity on the following questions:

  1. How do annotations in $select/$expand relate to include-annotations? e.g. must include-annotations=* or include-annotations=ns.foo be specified for $select=@ns.foo to work? or are these two distinct mechanisms for defining returned annotations?
  2. Should property annotations be supported - e.g. property@ns.foo? At a glance it seems like the Microsoft.OData.Core change does NOT support this... should it?
mikepizzo commented 3 years ago

1) Annotations in $select/$expand are returned regardless of what is specified in include-annotations. From URL Conventions:

Annotations requested in $select MUST be included in the response; $select overrules the include-annotations preference (see [OData-Protocol]) for the explicitly requested annotations. Additional annotations matching the preference can be included even if not requested via $select. The Preference-Applied response header only reflects the set of annotations included due to the include-annotations preference and not those only included due to $select.

2) According to the ABNF, property annotations are not supported:

annotationInQuery = AT [ namespace "." ] termName [ HASH annotationQualifier ]

For complex-typed properties, you can include the annotation in the nested $select. Seems like a hole in the protocol, though, for instance annotations on non-structured properties (primitive, enum, collection-valued properties).