Reputation: 135
I'm using Microsoft.AspNetCore.Odata 7.3
in Asp.net Web Api Core 3.1 project.
It turns out that the lib adds TimeZone of the server to DateTimes from Ef output.
Ef itself returns data with DateTimeKind.Unspecified
.
So I expected the odata lib just to omit the TimeZone shift because webApi services behave this way.
The question is how to make odata not to add TimeZone of the server or return everything in utc(Z-format).
Tried to set it via NewtonSoft serializerSettings, but it doesn't work for OData endpoints
services.AddOData();
services.AddMvc(options => {options.EnableEndpointRouting = false;});
services
.AddControllers()
.AddNewtonsoftJson(options =>
{
options.SerializerSettings.DateTimeZoneHandling = DateTimeZoneHandling.Utc;
});
Thanks for help!
Upd: Setting DateTimeKind to Utc on Ef level(via ValueConverter
s) allows server to convert datetime correctly to local.
But still the datetime is returned not in Z-format but with local TimeZone of server.
Upvotes: 13
Views: 3908
Reputation: 8683
In OData v8 you can specify the timezone when configuring:
program.cs
:
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddControllers().AddOData(options =>
{
// set to use utc, and return Z instead of +00:00
options.TimeZone = TimeZoneInfo.Utc;
options.AddRouteComponents("odata/", ODataModel.GetEdmModel())
.Filter()
...
An alternate way which seems to work is to use a DateTimeOffset
on the models instead of DateTime
, but that seemed too invasive.
I also added EF value converter which sets the Kind
when reading from the database, but this had no effect on the output of OData
.
Upvotes: 1
Reputation: 61
services.AddOData(options => options.TimeZone = TimeZoneInfo.Utc)
Upvotes: 4
Reputation: 161
I have a similar setup (also treated timestamp as UTC on EF layer) and ran into the same issue.
In my case I was able to fix it with the following extension method: https://learn.microsoft.com/en-us/previous-versions/aspnet/mt135699(v=vs.118)?redirectedfrom=MSDN
Example (Startup.cs)
app.UseEndpoints(endpoints =>
{
endpoints.MapControllers();
if (odataRoutePrefix != null && edmModel != null)
{
endpoints.EnableDependencyInjection();
endpoints.Filter().OrderBy().MaxTop(100).Count().Select();
endpoints.MapODataRoute("odata", odataRoutePrefix, edmModel);
endpoints.SetTimeZoneInfo(TimeZoneInfo.Utc);
}
});
Upvotes: 9