OData V4 failing to properly serialize list of POCO(?)s containing a System.Object property

Victor Wilson

I'm writing an OData V4 service with Web API 2 using the currently available OData NuGet packages.

I have an Entity Set of class Foo like so:

class Foo {
    string SomePropertyUnrelatedToThePost {get; set;}
    ...
    IList<Bar> TheImportantPropertyList {get; set;}
}

Bar doesn't have too much going on:

class Bar {
    string Name {get; set;}
    int? Group {get; set;}
    object Value {get; set;}
}

In use, Bar#Value is never assigned anything other than basic values, but some are primitives and some are not: bool, byte, char, short, int, long, string, Decimal, DateTime...

I am registering the Foo set as the docs instruct, using an ODataConventionModelBuilder like so:

...
builder.EntitySet<Foo>("Foos"); 

and registering my Bar as a complex type with builder.ComplexType<Bar>(); does not seem to change the outcome here.

The problem is that when I return a Foo object in my ODataController, the JSON response does not include Bar#Value.

{
  ...
  "SomePropertyUnrelatedToThePost": "Foo was here",
  ...
  "TheImportantPropertyList": [
     {
        "Name": "TheAnswer",
        "Group": null
     },
     {
        "Name": "TheQuestion",
        "Group": null
     }
   ]
}

Adding to my confusion is the fact that I can manually serialize a Foo in my controller method like so:

var settings = GlobalConfiguration.Configuration.Formatters.JsonFormatter.SerializerSettings;//.CreateJsonSerializer();
var s = JsonSerializer.Create(settings);
...
var json = Encoding.Default.GetString(...);

to produce a properly serialized result:

{
  "SomePropertyUnrelatedToThePost": "Foo was here",
  ...
  "TheImportantPropertyList": [
     {
        "Name": "TheAnswer",
        "Value": 42,
        "Group": null
     },
     {
        "Name": "TheQuestion",
        "Value": "What is the airspeed velocity of an unladen swallow?",
        "Group": null
     }
   ]
}

Am I configuring OData incorrectly? Do I have some other core misunderstanding? As I wrote this question it occurred to me that if I changed my model to include the System.Type of the assigned Value property, I could write a custom serializer, but it seems like it shouldn't have to come to that.

Edit: When I'm manually serializing my Foo, I'm not using the default OData serializer, I'm using a new Newtonsoft JsonSerializer. The default OData serializer and deserializers simply do not like properties of type Object.

Victor Wilson

I got this going. This post helped. Being new to OData, it took a while to get through the documentation, as most of it is out of date.

In my WebApiConfig.cs, I used the new method of injecting an ODataSerializerProvider into OData:

config.MapODataServiceRoute("odata", "api/v1", b =>
               b.AddService(ServiceLifetime.Singleton, sp => builder.GetEdmModel())
                .AddService<ODataSerializerProvider>(ServiceLifetime.Singleton, sp => new MySerializerProvider(sp)));

MySerializerProvider:

internal sealed class MySerializerProvider : DefaultODataSerializerProvider
{
    private MySerializer _mySerializer;

    public MySerializerProvider(IServiceProvider sp) : base(sp)
    {
        _mySerializer = new MySerializer(this);
    }

    public override ODataEdmTypeSerializer GetEdmTypeSerializer(IEdmTypeReference edmType)
    {
        var fullName = edmType.FullName();

        if (fullName == "Namespace.Bar")
            return _mySerializer;            
        else
            return base.GetEdmTypeSerializer(edmType);            
    }        
}

In my custom serializer, I noted OData will not automatically convert a DateTime to a DateTimeOffset. MySerializer:

internal sealed class MySerializer : ODataResourceSerializer
{
  public MySerializer(ODataSerializerProvider sp) : base(sp) { }

  public override ODataResource CreateResource(SelectExpandNode selectExpandNode, ResourceContext resourceContext)
  {
      ODataResource resource = base.CreateResource(selectExpandNode, resourceContext);

      if (resource != null && resourceContext.ResourceInstance is Bar b)
          resource = BarToResource(b);

      return resource;
  }

  private ODataResource BarToResource(Bar b)
  {
      var odr = new ODataResource
      {
          Properties = new List<ODataProperty>
          {
              new ODataProperty
              {
                  Name = "Name",
                  Value = b.Name
              },
              new ODataProperty
              {
                  Name = "Value",
                  Value = b.Value is DateTime dt ? new DateTimeOffset(dt) : b.Value
              },
              new ODataProperty
              {
                  Name = "Group",
                  Value = b.Group
              },
          }
      };

      return odr;
  }
}

I realize this is a pretty specific question and answer but I hope someone finds it useful.

この記事はインターネットから収集されたものであり、転載の際にはソースを示してください。

侵害の場合は、連絡してください[email protected]

編集
0

コメントを追加

0

関連記事

分類Dev

How to serialize JSON string containing date and time property using DataContractJsonSerializer?

分類Dev

Injecting OData v4 into MVC 6

分類Dev

OData WebApi V4 .net - Custom Serialization

分類Dev

Create Serialize JSON List Type object from c# class

分類Dev

Find Object in List<object> by same property

分類Dev

Spring batch FlatFileItemWriter writing model containing a property of List type

分類Dev

Properly initialize log4j system

分類Dev

MapStruct Ignore a property inside a list inside a Object

分類Dev

Serialization of an abstract class with a list containing mixed subclassed object types

分類Dev

Mapping object which containing a list in request - Spring MVC

分類Dev

Binding a dictionary containing a list in MVC4

分類Dev

Boost serialize object as a json

分類Dev

Serialize (or Parse) a Protobuf Object

分類Dev

How do I serialize a list of objects with System.Runtime.Serialization.Json?

分類Dev

odata filtering based on the property of a relation

分類Dev

ODataのV4での双方向ナビゲーション

分類Dev

OData V4 $ expandの複数のオプション

分類Dev

Web API 2.2 OData V4 - Kendo Grid - customize Created IHttpActionResult

分類Dev

OData v4 webapiのオプションの関数引数

分類Dev

odata v4 Product({key})/ GenerateVariantsルートの設定ミス

分類Dev

elseif statement containing multiple expressions separated by -or failing

分類Dev

How to serialize interface default property?

分類Dev

asp.net odata web api $select failing for related entities

分類Dev

How to properly serialize bitmap in C#?

分類Dev

JavaEE way to serialize object to json

分類Dev

C# - Order by an Object's property in List<T>

分類Dev

Get index of object in Generic/List based on value of a property

分類Dev

AngularJS display different object property via select list

分類Dev

oData v4(6.1.0)は$ expandに$ filterをネストしました

Related 関連記事

  1. 1

    How to serialize JSON string containing date and time property using DataContractJsonSerializer?

  2. 2

    Injecting OData v4 into MVC 6

  3. 3

    OData WebApi V4 .net - Custom Serialization

  4. 4

    Create Serialize JSON List Type object from c# class

  5. 5

    Find Object in List<object> by same property

  6. 6

    Spring batch FlatFileItemWriter writing model containing a property of List type

  7. 7

    Properly initialize log4j system

  8. 8

    MapStruct Ignore a property inside a list inside a Object

  9. 9

    Serialization of an abstract class with a list containing mixed subclassed object types

  10. 10

    Mapping object which containing a list in request - Spring MVC

  11. 11

    Binding a dictionary containing a list in MVC4

  12. 12

    Boost serialize object as a json

  13. 13

    Serialize (or Parse) a Protobuf Object

  14. 14

    How do I serialize a list of objects with System.Runtime.Serialization.Json?

  15. 15

    odata filtering based on the property of a relation

  16. 16

    ODataのV4での双方向ナビゲーション

  17. 17

    OData V4 $ expandの複数のオプション

  18. 18

    Web API 2.2 OData V4 - Kendo Grid - customize Created IHttpActionResult

  19. 19

    OData v4 webapiのオプションの関数引数

  20. 20

    odata v4 Product({key})/ GenerateVariantsルートの設定ミス

  21. 21

    elseif statement containing multiple expressions separated by -or failing

  22. 22

    How to serialize interface default property?

  23. 23

    asp.net odata web api $select failing for related entities

  24. 24

    How to properly serialize bitmap in C#?

  25. 25

    JavaEE way to serialize object to json

  26. 26

    C# - Order by an Object's property in List<T>

  27. 27

    Get index of object in Generic/List based on value of a property

  28. 28

    AngularJS display different object property via select list

  29. 29

    oData v4(6.1.0)は$ expandに$ filterをネストしました

ホットタグ

アーカイブ