odata.net icon indicating copy to clipboard operation
odata.net copied to clipboard

No ways to set instance annotation for top-level collection value

Open xuzhg opened this issue 1 year ago • 3 comments

Short summary (3-5 sentences) describing the issue.

Assemblies affected

Which assemblies and versions are known to be affected e.g. OData .Net lib 7.x

Reproduce steps

Customer can query a collection value from service as:

~/odata/customers/1/data

The response should be able to include the instance annotations, for example:

{
     "@odata.context": ...,
     "@NS.Annotation": "x",
     "value": [1,2,3]
}

However, no matter 'ODataCollectionStart' or 'ODataCollectionValue' doesn't allow to specify the instance annotations.

Expected result

{
     "@odata.context": ...,
     "@NS.Annotation": "x",
     "value": [1,2,3]
}

Actual result

{
     "@odata.context": ...,
     "value": [1,2,3]
}

Additional detail

Optional, details of the root cause if known. Delete this section if you have no additional details to add.

xuzhg avatar Jun 10 '24 18:06 xuzhg

I would have expected the way to do that would be to WriteStart(ODataResourceSet), followed by WritePrimitive() for each primitive value, where the instance annotations were part of the ODataResourceSet.

mikepizzo avatar Jun 11 '24 16:06 mikepizzo

This seems to work:

                var writer = msgReader.CreateODataResourceSetWriter();
                var collection = new ODataResourceSet();
                collection.SetSerializationInfo(new ODataResourceSerializationInfo
                {
                    IsFromCollection = true,
                    ExpectedTypeName = "Edm.Int32"
                });
                collection.InstanceAnnotations.Add(new ODataInstanceAnnotation("NS.Annotation", new ODataPrimitiveValue("x")));
                writer.WriteStart(collection);
                writer.Write(new ODataPrimitiveValue(1));
                writer.Write(new ODataPrimitiveValue(2));
                writer.Write(new ODataPrimitiveValue(3));
                writer.WriteEnd();

mikepizzo avatar Jun 11 '24 17:06 mikepizzo

This seems to work:

                var writer = msgReader.CreateODataResourceSetWriter();
                var collection = new ODataResourceSet();
                collection.SetSerializationInfo(new ODataResourceSerializationInfo
                {
                    IsFromCollection = true,
                    ExpectedTypeName = "Edm.Int32"
                });
                collection.InstanceAnnotations.Add(new ODataInstanceAnnotation("NS.Annotation", new ODataPrimitiveValue("x")));
                writer.WriteStart(collection);
                writer.Write(new ODataPrimitiveValue(1));
                writer.Write(new ODataPrimitiveValue(2));
                writer.Write(new ODataPrimitiveValue(3));
                writer.WriteEnd();

That's related to 'DISCUSSION'.

Shall we treat the any kind of collection of 'ODataResourceSet'?

Does it mean we don't need the 'ODataCollectionSerializer'?

So far, Web API OData use 'https://github.com/OData/AspNetCoreOData/blob/main/src/Microsoft.AspNetCore.OData/Formatter/Serialization/ODataCollectionSerializer.cs#L99' to write the top-level collection value.

xuzhg avatar Jun 11 '24 17:06 xuzhg