AspNetCoreOData
AspNetCoreOData copied to clipboard
Issues with dynamic property
- Dynamic property doesn't support non-primitive data types We are trying to build an odata data service to enable clients to store arbitrary json data. I define an open data type by adding the following field. It works well with primitive data types like string ect.
public IDictionary<string, object> DynamicProperties { get; set; }
However, when I try to post an item with the following dynamic property.
"SortKey": {
"Timestamp": "0001-01-01T00:00:00+00:00",
"KeyValue": 0
}
I got an exception below.
The given untyped value '{"Timestamp":"0001-01-01T00:00:00+00:00","KeyValue":0}' in payload is invalid. Consider using a OData type annotation explicitly.
Is there a way to support arbitrary json data and return them as-is on request?
- Filtering dynamic property always return empty result I posted some items with a dynamic property "type": 65. However, I always get empty result with $filter=cast(Type, 'Edm.Int32') eq 65.
I stepped into the source code. It seems like this check statement is causing the problem. It works well if I skip it under debugger.
https://github.com/OData/WebApi/blob/13938e80d0754f2e554f70c8e92fba1baeaf8318/src/Microsoft.AspNet.OData.Shared/Query/Expressions/ExpressionBinderBase.cs#L1370
Is this an known issue? Any comments are highly appreciated. Thanks!
@sunliangqin
- if want to use structural type for the dynamic property, please make sure that type in the model. Otherwise, we don't know how to deserialize it. Or if possible, you can put all "json value" into double quoted string.
- can $filter work without the "cast"? $filter=Type eq 65? In the payload, you can add "[email protected]": "#int32" to specify the type.
Thanks @xuzhg!
-
Unfortunately, the OData service we are trying to build serves as a data storage service. We need to allow clients to upload arbitrary json data. So there is no way for us to define types for them ahead of time. And we cannot change the json value to string due to some backward compatible reasons. However, it seems like this can be accomplished by providing a custom implementation of ODataResourceDeserializer & ODataResourceSerializer. Or is this something can be supported natively?
-
I specified the type using "[email protected]": "Emd.Int32" (#int32 didn't work for me. ModelState.IsValid is false). It worked for me after removing the "cast" in the query. It looks like it should be OK to use an extra cast here. Is this a bug?
Hi all, any plan to support non-primitive data types in DynamicProperties
?
@sunliangqin did you overcome this limit?
PS: I solved this by implementing a custom ODataResourceSerializer that overrides AppendDynamicProperties (you must register your own ODataSerializerProvider to get this to run for your MyODataEntity):
public class CustomDynamicPropsDataSerializer : ODataResourceSerializer
{
public CustomDynamicPropsDataSerializer(ODataSerializerProvider serializerProvider)
: base(serializerProvider)
{
}
public override void AppendDynamicProperties(
ODataResource resource,
SelectExpandNode selectExpandNode,
ResourceContext resourceContext)
{
if (resourceContext?.ResourceInstance is MyODataEntity entity)
{
var properties = new List<ODataProperty>();
foreach (var item in entity.Properties)
{
properties.Add(new ODataProperty
{
Name = item.Key,
Value = new ODataUntypedValue
{
RawValue = JsonConvert.SerializeObject(item.Value)
},
});
}
resource.Properties = resource.Properties.Concat(properties);
}
}
}