5
Vote

Incorrect type detected calling an unbound function with $filter

description

In my OData 4 endpoint, I have an unbound function called "GetActivityView" that returns an IQueryable:
[HttpGet]
[EnableQuery(AllowedQueryOptions = AllowedQueryOptions.All)]
[ODataRoute("GetActivityView")]
public IQueryable<ActivityView> GetActivityView(ODataActionParameters parameters)
{
    .... snip ....
}
It is defined in the route configuration as:
builder.Function("GetActivityView").ReturnsCollection<ActivityView>();
The metadata is correct, and the function operates correctly when called directly from Javascript:
      <Function Name="GetActivityView">
        <ReturnType Type="Collection(Namespace.DataAccess.Models.Views.ActivityView)" />
      </Function>

      .... snip ....

<FunctionImport Name="GetActivityView" Function="Namespace.GetActivityView" IncludeInServiceDocument="true" />

      .... snip ....
When I call this from the .NET client using the basic query, it operates correctly:
var activities = entities.GetActivityView().Execute();
This generates the following request returns the expected result:
GET http://myhost.test.internal/odata/GetActivityView() HTTP/1.1
OData-MaxVersion: 4.0;NetFx
Accept: application/json;odata.metadata=minimal
Accept-Charset: UTF-8
User-Agent: Microsoft ADO.NET Data Services
Host: myhost.test.internal
When I write the following query:
var activities = entities.GetActivityView().Where(a => !a.IsDeleted && a.OwnerId == me.Id);
it generates the following (correct) request and the server returns the correct (filtered) response:
GET http://myhost.test.internal/odata/GetActivityView()?$filter=not%20IsDeleted%20and%20OwnerId%20eq%2045700b30-4103-455e-9c2c-9115b46b6385 HTTP/1.1
OData-Version: 4.0;NetFx
OData-MaxVersion: 4.0;NetFx
Accept: application/json;odata.metadata=minimal
Accept-Charset: UTF-8
User-Agent: Microsoft ADO.NET Data Services
Host: myhost.test.internal
However, when the OData core tries to deserialize the message, I get the following exception:
Unhandled Exception: System.InvalidOperationException: The context URI 'http://m yhost.test.internal/odata/$metadata#Collection(Namespace.DataAccess.Models.
Views.ActivityView)' references the type 'Collection(Namespace.DataAccess
.Models.Views.ActivityView)'; however the expected type is 'Namespace.Dat
aAccess.Models.Views.ActivityView'. ---> Microsoft.OData.Core.ODataException: Th
e context URI 'http://myhost.test.internal/odata/$metadata#Collection(Namespace
.DataAccess.Models.Views.ActivityView)' references the type 'Collection(Namespace
.DataAccess.Models.Views.ActivityView)'; however the expected type i
s 'Namespace.DataAccess.Models.Views.ActivityView'.
at Microsoft.OData.Core.JsonLight.ODataJsonLightPropertyAndValueDeserializer.
UpdateExpectedTypeBasedOnContextUri(IEdmTypeReference expectedPropertyTypeRefere
nce)
at Microsoft.OData.Core.JsonLight.ODataJsonLightPropertyAndValueDeserializer.
ReadTopLevelPropertyImplementation(IEdmTypeReference expectedPropertyTypeReferen
ce, DuplicatePropertyNamesChecker duplicatePropertyNamesChecker)
at Microsoft.OData.Core.JsonLight.ODataJsonLightPropertyAndValueDeserializer.
ReadTopLevelProperty(IEdmTypeReference expectedPropertyTypeReference)
at Microsoft.OData.Core.JsonLight.ODataJsonLightInputContext.ReadProperty(IEd
mStructuralProperty property, IEdmTypeReference expectedPropertyTypeReference)
at Microsoft.OData.Core.ODataMessageReader.<>c__DisplayClass35.<ReadProperty>
b__34(ODataInputContext context)
at Microsoft.OData.Core.ODataMessageReader.ReadFromInput[T](Func2 readFunc,
ODataPayloadKind[] payloadKinds)
at Microsoft.OData.Core.ODataMessageReader.ReadProperty(IEdmTypeReference exp
ectedPropertyTypeReference)
at Microsoft.OData.Client.Materialization.ODataPropertyMaterializer.ReadWithE
xpectedType(IEdmTypeReference expectedClientType, IEdmTypeReference expectedRead
erType)
at Microsoft.OData.Client.Materialization.ODataMessageReaderMaterializer.Read
Implementation()
--- End of inner exception stack trace ---
at Microsoft.OData.Client.Materialization.ODataMessageReaderMaterializer.Read
Implementation()
at Microsoft.OData.Client.MaterializeAtom.MoveNextInternal()
at Microsoft.OData.Client.MaterializeAtom.MoveNext()
at System.Linq.Enumerable.<CastIterator>d__b1
1.MoveNext()
at System.Collections.Generic.List1..ctor(IEnumerable1 collection)
at System.Linq.Enumerable.ToList[TSource](IEnumerable`1 source)
at Sample.ODataClient.Program.Main(String[] args) in
c:\DEV\misc\SampleODataClient\Sample.ODataClient\Program.cs:line 54
It appears as though the response is (incorrectly) being routed through the ODataJsonLightPropertyAndValueDeserializer class. From looking at the source, it appears as though the correct class to be called is ODataJsonLightCollectionDeserializer. Is there a way I can force this? Or can I somehow configure the client to use full Json instead of JsonLight?

comments

DureSameen wrote Nov 29, 2014 at 12:16 PM

I facing same error, Any work around?

ldasilva wrote Mar 10, 2015 at 10:42 PM

Hi,

I've got the same error.

This error happen since the 2.2.0 update of the OData client T4. Go back to the 2.0.0 code for bound function generation method worked for me.

To Microsoft : it seems that there is an issue with the DataServiceContext.CreateFunctionQuery<T> method, that is used on the 2.2.0 version of the client T4 (CreateQuery was used before). The code of this method does not lead the materializer to identify the correct payload kind (property instead of collection). Hard to do more with only a reflection tool. Hope it'll help anyway.