Search code examples
jsonasp.net-web-apijson.netodata

WebAPI v2 - JSON Serialization for OData expand causes $type to be incorrect


I have just updated an MVC4/WebApi v1 application to MVC5 + WebAPI2..

Seems like after this upgrade the Json.Net serializer will no longer include the proper $type for requests that make use of OData $expand method. see below for an example of what i mean...

CORRECT:

request: http://url.com/api/Studies/277/Sites

response:

{
$id: "1"
$type: "LGCYDAPI.Domain.Model.StudySiteWithContacts, LGCYDAPI.Domain.Model"
Contacts: [
{
$id: "2"
$type: "LGCYDAPI.Domain.Model.ContactRelatedToSite, LGCYDAPI.Domain.Model"
ContactID: -38445
}],
SiteID: 38445
}

INCORRECT:

request: http://url.com/api/Studies/277/Sites?$expand=Contacts

response:

{
$id: "1"
$type: "System.Collections.Generic.Dictionary`2[[System.String, mscorlib],[System.Object, mscorlib]], mscorlib"
Contacts: [
{
$id: "2"
$type: "System.Collections.Generic.Dictionary`2[[System.String, mscorlib],[System.Object, mscorlib]], mscorlib"
ContactID: -38445
}],
SiteID: 38445}

Along with MVC and WebAPI assemblies, I updated JSON.NET from 5.0.6 to 6.0.3 which I thought was the problem.. however, i reverted back to v5 and it didn't fix the problem so I'm back on v6. Also updated OData nugets - my current versions are Microsoft.Data.OData=5.6.0 and Microsoft.AspNet.WebApi.OData=5.1.2.

JSON Serializer Settings:

pConfiguration.Formatters.JsonFormatter.SerializerSettings.ReferenceLoopHandling = ReferenceLoopHandling.Serialize;
        pConfiguration.Formatters.JsonFormatter.SerializerSettings.PreserveReferencesHandling = PreserveReferencesHandling.Objects;
        pConfiguration.Formatters.JsonFormatter.SerializerSettings.TypeNameHandling = TypeNameHandling.Objects;

        pConfiguration.Formatters.JsonFormatter.SerializerSettings.Converters.Add(new Newtonsoft.Json.Converters.StringEnumConverter());

Solution

  • The $type in response payload is for the actual object to be serialized.

    With $expand applied on the result, the structure of returned object is changed from LGCYDAPI.Domain.Model.StudySiteWithContacts to SelectExpandWrapper.

    So you can't get your expected Sites type with $expand applied.

    For SelectExpandWrapper structure, check this:

    https://aspnetwebstack.codeplex.com/wikipage?title=%24select%20and%20%24expand%20support