1

Is it possible to force the way DateTimes are displayed in OData while keeping all functionnalities of IQueryable<> ?

Actually, I created a basic endpoint exposing data from my Database. One of the property is a DateTime and is displayed like that :

"MyDate": "2017-01-07T00:00:00",

However, I'd like to display it with another DateTime format, like dd/MM/yyyy

I tried this promising answer but my property has still the same undesired format when I call my endpoint with Postman.

How to force DateTime format in OData, while preserving OData filtering on this column and let the client decides to query, for example, all data with MyDate>= n days ?

AlexB
  • 7,302
  • 12
  • 56
  • 74
  • Why do you want a different format? – mjwills Jun 15 '20 at 13:21
  • Displaying dates is not what OData is for. OData is for transmitting data. ASP.NET MVC (since that's in your tags) is for taking the data that OData transmits and displaying it. – Heretic Monkey Jun 15 '20 at 13:31
  • Outputing ISO standard dates is better, but one reason this was necessary for me was backwards compatibility. If you have an ASP.NET4 API you want to move to ASP.NET Core, but don't want to change the output date format to ISO because it would break clients, you need to do this. @OverGril answer works – Daniel May 19 '23 at 15:26

2 Answers2

2

I am adding my solution here as this was my first hit on Google. I ran into the same issue, and tried the same solution with no success. Note that this answer is based on an Asp.NET Core Web Api.

I based my answer on WebAPI OData Datetime serialization

but the way they added the Custom payload value converter doesn't seem applicable anymore.

You have to create a class derived from ODataPayloadValueConverter on which you override the ConvertToPayloadValue function:

namespace [YOUR_NAMESPACE_HERE];

using Microsoft.OData;
using Microsoft.OData.Edm;

public class CustomODataPayloadConverter : ODataPayloadValueConverter
{
    public override object ConvertToPayloadValue(object value, IEdmTypeReference edmTypeReference)
    {
        if (edmTypeReference.PrimitiveKind() == EdmPrimitiveTypeKind.DateTimeOffset)
        {
            var dateTimeOffset = (DateTimeOffset)value;
            return dateTimeOffset.ToString("dd/MM/yyyy");
        }
    
        return base.ConvertToPayloadValue(value, edmTypeReference);
    }
}

You add the payload value converter in the Action<IServiceCollection> which is the 3rd parameter in ODataOptions.AddRouteComponents.

builder.AddOData(options =>
{
    options.AddRouteComponents("api/v1", modelBuilder.GetEdmModel(), actions => 
    {
        actions.AddSingleton(typeof(ODataPayloadValueConverter), new CustomODataPayloadConverter());
    });
});

I am accessing the ODataOptions inside IMVCBuilder.AddOData which in turn is an extension method.
using Microsoft.AspNetCore.OData;
Which is found in the 'Microsoft.AspNetCore.OData.Mvc' NuGet package.

My Postman response:

{
    "@odata.context": "http://localhost:5267/api/v1/$metadata#ENTITY_NAME",
    "value": [
        {
            "Id": "98aa1283-f17f-4d12-8e51-59a4ead2a23e",
            "myDateTime": "28/09/2022"
        }
    ]
}

where myDateTime is ofcourse, a DateTime.

OverGril
  • 21
  • 2
0

However, I'd like to display it with another DateTime format, like dd/MM/yyyy

Then do not display it directly. The date format in odata is defined in the specs do your code knows what to expect and can then format it for public consumption IF it desires to show it. The whole concept of a standard is that people consuming it know what to expect. In particular - if you write your classes manually to consume them you do something wrong, the idea behind odata is that a code generator generates the client code, and it need to know waht to parse (into a javascript odata class).

Odata is NOT supposed to necessariyl be presented directly to the user. The date format is part of the standard. If you change it, it is not odata.

Oh, and another note: The datetime foramt you see there is actually a standard for which Javascript has methods and libraries to manipulate them. WHich is another reason you WANT this. Your custom format is something you have to write all the libraries for yourself.

TomTom
  • 61,059
  • 10
  • 88
  • 148