OData function returning a collection of entities fails with PowerQuery

3.2k Views Asked by At

I got this error while using PowerQuery on a OData service I’m currently developing:

When writing a JSON response, a user model must be specified and the entity set and entity type must be passed to the ODataMessageWriter.CreateODataEntryWriter method or the ODataFeedAndEntrySerializationInfo must be set on the ODataEntry or ODataFeed that is being written.

This occurs when invoking from PowerQuery a bound function that returns a collection of entities. When invoked from a web browser, the response is (JSON format):

{
    "@odata.context": "http://localhost:8080/ODataPrototype/ODataPrototype.svc/$metadata#Collection(Demo.ODataPrototype.Count)",
    "value": [
        {
            "RowCount": 1
        },
        {
            "RowCount": 2
        },
        {
            "RowCount": 3
        },
        {
            "RowCount": 4
        }
    ]
}

I use the Olingo V4 library. A stripped down version of my metadata would be:

<edmx:Edmx xmlns:edmx="http://docs.oasis-open.org/odata/ns/edmx" Version="4.0">
  <edmx:DataServices>
    <Schema xmlns="http://docs.oasis-open.org/odata/ns/edm" Namespace="Demo.ODataPrototype">
      <EntityType Name="Instance">
        <Key>
          <PropertyRef Name="Id" />
        </Key>
        <Property Name="Id" Type="Edm.Int32" />
        <Property Name="Name" Type="Edm.String" />
        <Property Name="Description" Type="Edm.String" />
        <Property Name="Tag" Type="Edm.String" />
        <Property Name="Xid" Type="Edm.Int64" />
        <Property Name="Properties" Type="Collection(Demo.ODataPrototype.Property)" />
      </EntityType>
      <EntityType Name="Count">
        <Property Name="RowCount" Type="Edm.Int32" />
      </EntityType>
      <ComplexType Name="Property">
        <Property Name="Name" Type="Edm.String" />
        <Property Name="Value" Type="Edm.String" />
      </ComplexType>
      <Function Name="GetData" EntitySetPath="Instance/Demo.ODataPrototype.Count" IsBound="true">
        <Parameter Name="Instance" Type="Demo.ODataPrototype.Instance" />
        <Parameter Name="From" Type="Edm.DateTimeOffset" />
        <Parameter Name="To" Type="Edm.DateTimeOffset" />
        <ReturnType Type="Collection(Demo.ODataPrototype.Count)" />
      </Function>
      <EntityContainer Name="Container">
        <EntitySet Name="Instances" EntityType="Demo.ODataPrototype.Instance"></EntitySet>
        <EntitySet Name="Count" EntityType="Demo.ODataPrototype.Count" />
      </EntityContainer>
    </Schema>
  </edmx:DataServices>
</edmx:Edmx>

Would anyone know what I'm missing?

1

There are 1 best solutions below

0
On

I found the solution. The context in my JSON response defines the result as a collection of type IVserver.ODataPrototype.Count:

"@odata.context": "http://localhost:8080/ODataPrototype/ODataPrototype.svc/$metadata#Collection(IVserver.ODataPrototype.Count)"

But PowerQuery needs an entityset:

"@odata.context": "http://localhost:8080/ODataPrototype/ODataPrototype.svc/$metadata#Count"

The EntitySet "Count" must be declared in the EntityContainer.

To get the EntitySet in the @odata.context, an entityset must be set when building the ContextURL. Example:

final ContextURL contextURL = ContextURL.with().entitySet(responseEdmEntitySet).selectList(selectList).serviceRoot(baseURI).build();

And, the methods asCollection() and type() must not be called.