OData / odata.net

ODataLib: Open Data Protocol - .NET Libraries and Frameworks
https://docs.microsoft.com/odata
Other
686 stars 349 forks source link

CSDL Serialization: NullReferenceException when serializing 1:n NavigationProperties #832

Open codedebugrepeat opened 7 years ago

codedebugrepeat commented 7 years ago

CsdlWriter.TryWriteCsdl fails with NullReferenceException for the following Model:

<?xml version="1.0" encoding="utf-8"?>
<edmx:Edmx Version="4.0" xmlns:edmx="http://docs.oasis-open.org/odata/ns/edmx">
    <edmx:DataServices>
        <Schema Namespace="com.sap.gateway.default.iwbep.v4_gw_sample_basic.v0001" Alias="SAP__self" xmlns="http://docs.oasis-open.org/odata/ns/edm">
            <EntityType Name="SalesOrder">
                <Key>
                    <PropertyRef Name="SalesOrderID"/>
                </Key>
                <Property Name="SalesOrderID" Type="Edm.String" Nullable="false" MaxLength="10"/>
                <NavigationProperty Name="SO_2_SOITEM" Type="Collection(com.sap.gateway.default.iwbep.v4_gw_sample_basic.v0001.SOLineItem)" Partner="SOITEM_2_SO"/> 
            </EntityType>
            <EntityType Name="SOLineItem">
                <Key>
                    <PropertyRef Name="SalesOrderID"/>
                </Key>
                <Property Name="SalesOrderID" Type="Edm.String" Nullable="false" MaxLength="10"/>
                <NavigationProperty Name="SOITEM_2_SO" Type="com.sap.gateway.default.iwbep.v4_gw_sample_basic.v0001.SalesOrder" Nullable="false"/>
            </EntityType>
            <EntityContainer Name="Container">
                <EntitySet Name="SalesOrderList" EntityType="com.sap.gateway.default.iwbep.v4_gw_sample_basic.v0001.SalesOrder"/>
            </EntityContainer>
        </Schema>
    </edmx:DataServices>
</edmx:Edmx>

SalesOrder references a Collection of SOLineItems via NavigationProperty. SOLineItem has a NavigationProperty back to SalesOrder.

Serializing the corresponding IEdmModel with the following code throws a NullReferenceException:

CsdlWriter.TryWriteCsdl(model, writer, CsdlTarget.OData, out errors)

Stacktrace:

System.NullReferenceException: Object reference not set to an instance of an object.
   at Microsoft.OData.Edm.Csdl.Serialization.EdmModelCsdlSchemaWriter.WriteNavigationPropertyElementHeader(IEdmNavigationProperty member)
   at Microsoft.OData.Edm.Csdl.Serialization.EdmModelCsdlSerializationVisitor.BeginElement[TElement](TElement element, Action`1 elementHeaderWriter, Action`1[] additionalAttributeWriters)
   at Microsoft.OData.Edm.Csdl.Serialization.EdmModelCsdlSerializationVisitor.ProcessNavigationProperty(IEdmNavigationProperty element)
   at Microsoft.OData.Edm.EdmModelVisitor.VisitProperty(IEdmProperty property)
   at Microsoft.OData.Edm.EdmModelVisitor.VisitCollection[T](IEnumerable`1 collection, Action`1 visitMethod)
   at Microsoft.OData.Edm.Csdl.Serialization.EdmModelCsdlSerializationVisitor.ProcessEntityType(IEdmEntityType element)
   at Microsoft.OData.Edm.EdmModelVisitor.VisitCollection[T](IEnumerable`1 collection, Action`1 visitMethod)
   at Microsoft.OData.Edm.Csdl.Serialization.EdmModelCsdlSerializationVisitor.VisitEdmSchema(EdmSchema element, IEnumerable`1 mappings)
   at Microsoft.OData.Edm.Csdl.CsdlWriter.WriteSchemas()
   at Microsoft.OData.Edm.Csdl.CsdlWriter.WriteODataCsdl()
   at Microsoft.OData.Edm.Csdl.CsdlWriter.WriteCsdl()
   at Microsoft.OData.Edm.Csdl.CsdlWriter.TryWriteCsdl(IEdmModel model, XmlWriter writer, CsdlTarget target, IEnumerable`1& errors)

When I delete any one of the navigation properties, serialization works. On a side note, the serialize method uses the TryParse pattern and should never throw an exception. Instead, errors should be returned via the error out param.

Assemblies affected

Microsoft.OData.Edm 7.2.0

Reproduce steps

  1. Parse the XML above using: CsdlReader.TryParse(XmlReader.Create(metadata), out model, out errors)
  2. Now that you have a model, serialize it using CsdlWriter.TryWriteCsdl(model, writer, CsdlTarget.OData, out errors)

Expected result

TryWriteCsdl does not throw an Exception

Either: Serialization works Or: In case of errors, these should be in the out -parameter "errors" of TryWriteCsdl.

Actual result

TryWriteCsdl fails with a NullReferenceException. Errors out param is empty, serialization fails (nothing written).

Additional details

The appended XML is reduced to show the main cause. The original file where the error was first encountered can be found here: v4_gw_sample_basic.txt

rkoelbel commented 5 years ago

I would like to fix this. Should be easy actually: https://github.com/rkoelbel/odata.net/commit/c55400d201ce4ece20d50326f99564433830871c