I have a .NET Core Web API using ODATA. To support a legacy requirement, I'd like to change the default format of DateTime members to something like "yyyy-MM-dd HH:mm:ss", then be able to override the format on individual members. I understand this is different from JsonConverter and may require a custom ODATA serializer, but I am not sure how to do so.
Asked
Active
Viewed 696 times
2 Answers
1
Since .NET 5.0 this has moved. You now add the ODataPayloadValueConverter on the options.AddRouteComponent
.AddOData(options =>
{
options.AddRouteComponents("odata", GetEdmModel(), action =>
{
action.AddSingleton(typeof(ODataPayloadValueConverter), new ODataByteArrayAsHexJsonConverter());
})
.Filter().Select().Expand().Count().OrderBy().SetMaxTop(50).SkipToken();
});
I've used it to replace the standard byte[] serializer (which uses base64 encoding), with an implementation that uses hex encoding instead.
public class ODataByteArrayAsHexJsonConverter : ODataPayloadValueConverter
{
public override object ConvertToPayloadValue(object value, IEdmTypeReference edmTypeReference)
{
if (value is byte[] byteValue)
{
return Helper.ConvertByteToHexString(byteValue);
}
else
{
return base.ConvertToPayloadValue(value, edmTypeReference);
}
}
public override object ConvertFromPayloadValue(object value, IEdmTypeReference edmTypeReference)
{
if (edmTypeReference.IsByte() && value is string stringValue)
{
return Helper.ConvertHexStringToByte(stringValue);
}
else
{
return base.ConvertFromPayloadValue(value, edmTypeReference);
}
}
}

jmahlitz
- 41
- 2
0
I found a good solution using ODataPayloadValueConverter. Below is the implementation for DateTime, but you could easily add other types as needed.
class MyPayloadValueConverter : ODataPayloadValueConverter
{
public override object ConvertToPayloadValue(object value, IEdmTypeReference edmTypeReference)
{
if (value is DateTime)
{
return String.Format("{0:yyyy-MM-dd HH:mm:ss}", value, CultureInfo.InvariantCulture);
}
else
{
return base.ConvertToPayloadValue(value, edmTypeReference);
}
}
public override object ConvertFromPayloadValue(object value, IEdmTypeReference edmTypeReference)
{
if (edmTypeReference.IsDate() && value is string)
{
return DateTime.Parse((string)value, CultureInfo.InvariantCulture);
}
else
{
return base.ConvertFromPayloadValue(value, edmTypeReference);
}
}
}
Wire up your converter in Startup.cs like this:
app.UseEndpoints(endpoints =>
{
...
endpoints.MapODataRoute("odata", "odata", action =>
{
action.AddService(Microsoft.OData.ServiceLifetime.Singleton, typeof(ODataPayloadValueConverter), pvc => new MyPayloadValueConverter());
});
});

John Reiner
- 15
- 6