Description:
Open properties with null values are omitted from serialized output. Makes it impossible to distinguish unset open properties from properties set to null.
Minimal repro steps:
Create an open type. Make a service operation which returns an instance of that open type, with its dynamic property collection set to new Dictionary
Example (only NonNullProperty shows up in output):
// GET: odata/Stores
[EnableQuery]
public IQueryable
{
var retval = new Store
{
StoreID = 8,
StoreName = "My store",
DynamicProperties = new Dictionary
};
return new[] { retval }.AsQueryable();
}
Expected result:
Null properties become ODataNull type.
Actual result:
ODataEdmTypeSerializer.AppendDynamicProperties() skips over null-valued properties as if they don't exist. Output in screenshot:

Further technical details:
As best I can tell, the OData spec does not restrict the values of open properties, so it should be possible to have null-valued open properties.
Sorry, paste error excluded type parameters. Corrected:
// GET: odata/Stores
[EnableQuery]
public IQueryable GetStores()
{
var retval = new Store
{
StoreID = 8,
StoreName = "My store",
DynamicProperties = new Dictionary<string, object> { { "MyNullProperty", null }, { "MyNonNullProperty", 42 } }
};
return new[] { retval }.AsQueryable();
}
Thanks @MaxWilson for reporting the issue. Please feel free to submit a pull request on it.
@MaxWilson Skip the null dynamic property to serialize is by design. What's your scenario to have a null-dynamic property in the payload?
I do think you can set the value as null if you can't find the dynamic property in the payload. Please let us know your thought. thanks.
Scenario is letting end-users have a property bag for business data that actually shows everything that's in the bag (so that adding new properties doesn't take a dev cycle). Also, the fact that the OData spec says that open properties can be nullable, so I should think the scenario is also "implement behavior from the OData spec."
It's hard to be more specific about the scenario because OData scenarios are always kind of loose, but I'll talk to my PM and try to get a concrete scenario for you where null and missing are different things.
@MaxWilson please re-open it if you have further concern. Thanks.
I also have a scenario where a global OData action is returning tree structure of objects of various types, I use wrapper open type with dynamic properties to represent these variously typed objects and reflexively read properties from those objects into dynamic properties dictionary, now properties that are null are not serialized which is a disaster for the client, because the client does not know which properties to expect in which node of the tree serialized in the response.
I think a possibility to force serialization of null dynamic properties is needed in many valid cases and is not against the OData standard.
So after half day of digging found the solution by decompiling System.Web.OData
config.Properties.AddOrUpdate("System.Web.OData.NullDynamicPropertyKey", val=>true, (oldVal,newVal)=>true);
Most helpful comment
So after half day of digging found the solution by decompiling System.Web.OData
config.Properties.AddOrUpdate("System.Web.OData.NullDynamicPropertyKey", val=>true, (oldVal,newVal)=>true);