Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C# odata action with complex type collection fails

Tags:

c#

odata

odatalib

I need to call a server that exposes an action. This action has either a string of a collection of complex types or a collection of complex types as parameters. I need to call either.

Metadata is:

either:

<Action Name="BulkChange" IsBound="true">
<Parameter Name="bindingParameter" Type="Collection(PropertyCore.InspectionDuty)"/>
<Parameter Name="Comment" Type="Edm.String" Unicode="false"/>
<Parameter Name="Changes" Type="Collection(PropertyCore.InspectionDutyChange)"/>
</Action>

With the following complex type:

<ComplexType Name="InspectionDutyChange">
<Property Name="Operation" Type="Operations.Operations" Nullable="false"/>
<Property Name="Identity" Type="Edm.Guid" Nullable="false"/>
<Property Name="IsDisabled" Type="Edm.Boolean" Nullable="false"/>
<Property Name="SeriesStart" Type="Edm.DateTimeOffset"/>
<Property Name="Interval" Type="Common.Interval"/>
<NavigationProperty Name="Module" Type="PropertyCore.Module"/>
<NavigationProperty Name="Equipment" Type="PropertyCore.Equipment"/>
<NavigationProperty Name="OperatorTask" Type="PropertyCore.OperatorTask"/>
</ComplexType>

Or, alterantively:

<Action Name="BulkChange" IsBound="true">
<Parameter Name="bindingParameter" Type="Collection(PropertyCore.InspectionDuty)"/>
<Parameter Name="Updates" Type="PropertyCore.InspectionDutyChanges"/>
</Action>

with the complex types defined as

<ComplexType Name="InspectionDutyChanges">
<Property Name="Comment" Type="Edm.String"/>
<Property Name="Changes" Type="Collection(PropertyCore.InspectionDutyChange)"/>
</ComplexType>

<ComplexType Name="InspectionDutyChange">
<Property Name="Operation" Type="Operations.Operations" Nullable="false"/>
<Property Name="Identity" Type="Edm.Guid" Nullable="false"/>
<Property Name="IsDisabled" Type="Edm.Boolean" Nullable="false"/>
<Property Name="SeriesStart" Type="Edm.DateTimeOffset"/>
<Property Name="Interval" Type="Common.Interval"/>
<NavigationProperty Name="Module" Type="PropertyCore.Module"/>
<NavigationProperty Name="Equipment" Type="PropertyCore.Equipment"/>
<NavigationProperty Name="OperatorTask" Type="PropertyCore.OperatorTask"/>
</ComplexType>

I see no way to work around that as we must support multiple updates in one run.

Exceptions I get all point to serious shortcomings in odata.net.

First variant:

    Microsoft.OData.ODataException: Unsupported primitive type.
A primitive type could not be determined for an instance of type 'Api.Odata.InspectionDutyChange'.
    
    Result StackTrace:
    at Microsoft.OData.ValidationUtils.ValidateIsExpectedPrimitiveType(Object value,
IEdmPrimitiveTypeReference valuePrimitiveTypeReference,
IEdmTypeReference expectedTypeReference)
    at Microsoft.OData.JsonLight.ODataJsonLightValueSerializer.WritePrimitiveValue(Object value,
IEdmTypeReference actualTypeReference,
IEdmTypeReference expectedTypeReference)
    at Microsoft.OData.JsonLight.ODataJsonLightCollectionWriter.WriteCollectionItem(Object item,
IEdmTypeReference expectedItemType)
    at Microsoft.OData.ODataCollectionWriterCore.InterceptException(Action action)
at Microsoft.OData.TaskUtils.GetTaskForSynchronousOperation(Action synchronousOperation)
    --- End of stack trace from previous location where exception was thrown ---

and second variant:

Microsoft.OData.ODataException: The parameter 'Updates' is of Edm type kind 'Complex'. You cannot call WriteValue on a parameter that is not of Edm type kinds 'Primitive', 'Enum' or 'Complex'.
    
Stack trace:

Result StackTrace:
at Microsoft.OData.ODataParameterWriterCore.VerifyCanWriteValueParameter(Boolean synchronousCall, String parameterName, Object parameterValue)
at Microsoft.OData.ODataParameterWriterCore.WriteValueAsync(String parameterName, Object parameterValue)

I can make a workaround for one update - but that is not usable in general.

We use the Odata Client, but this is not an issue with the client. The stack trace points to limitations in the Odata.Net stack. Which also is slow to make updates. Alternatives I will have to create the HTTP request for those calls manually.

Update: there is no workaround. It looks like until this gets fixed in the Odata.Net libraries, we have to stick to a standard REST API and manually construct the payload. Every complex type fails, and I can not decompose the last level as it contains navigation properties. I can not recompose the references. I'm using a custom deserializer already because that is another not supported scenario in the Odata.Net. Unless someone has a workaround, this action is The Odata compatible, but the Odata.net incompatible.

like image 723
TomTom Avatar asked Nov 08 '22 00:11

TomTom


1 Answers

I assume you are using Simple.Odata.client. This library has not been updated since a change was made in OData core to consider complex types same as entity types because complex types have navigation properties just like entity types. The change description can be found here:ODataComplexValue The issue has also been addressed in the GitHub issue: Complex type collection writer . I would therefore advise you to use Microsoft.OData.Client which is up to date and works.

like image 142
Paul Ojwang' Odero Avatar answered Nov 14 '22 22:11

Paul Ojwang' Odero