I'm having an issue that I cannot figure out.
I try to deal ALWAYS with UTC DateTime at server side.
I have an AspNetCore Mvc application with an endpoint that accepts queries that may include DateTimes. I want Mvc to understand that these dates are already in UTC and not to transform them "again".
My system is in Spain, (UTC +2)
If I send an http request to my localhost server like this:
http://localhost:50004/api/Resources?appliesOn=2018-06-30T18:00:00.000Z
I want to have the deserialized datetime as UTC representing the same date as:
DateTime.SpecifyKind(new DateTime(2018, 6, 30, 18, 0, 0), DateTimeKind.Utc)
But I can see that Mvc always transforms the date 2018-06-30T18:00:00.000Z into two hours later: 2018-06-30 20:00:00
I have tried to tell Mvc to use UTC json serializer/deserializer but nothing changes:
services
.AddMvc()
.AddJsonOptions(options =>
{
options.SerializerSettings.DateTimeZoneHandling = DateTimeZoneHandling.Utc;
});
Is there a way to send query parameters in an http GET request already as a representation of UTC datetime? I understood a Date in ISO 8601, if it has a suffix Z it means "zero-offset" which should be interpreted already as UTC date time. Why Mvc is then transforming this and adding 2 hours offset?
Any clarification would be much appreciated!
PS: This is my endpoint, nothing special as you can see:
[HttpGet("")]
public IActionResult GetResources()
{
var displayUri = Request.GetDisplayUrl();
var requestUri = new Uri(displayUri);
var filter = _filteredRequestFactory.Create(requestUri);
var resources = _myProjection.GetResourcers(filter);
return Ok(resources);
}
Thanks to another question in StackOverflow I found out that the reason this happens is because AspNetCore Mvc deserializer does not even use Json.Net deserializer in a GET http request to deserialize the query parameters.
Therefore, the following request: http://localhost:50004/api/DateTests?date=2018-06-15T18:00:00.000Z
would be captured by my endpoint:
[HttpGet("")]
public IActionResult GetDate(DateTime date)
{
return Ok(date.ToString("o"));
}
and return the date in ISO 8601 format as follows: 2018-06-15T20:00:00.0000000+02:00
It deserializes the query parameter as if it was a local time date, and it applies the UTC + 2 (because the app is in Spain).
I needed a way to tell AspNet Core Mvc deserializer to understand that the query parameter that looks like a date, should be treated already as an UTC date and not modified it when deserializing.
The answer was to create a custom model binder and apply it either to that endpoint or globally.
I found a good implementation and after adding that model binder provider and model binder,
my endpoint now returns for the request with ?date=2018-06-15T18:00:00.000Z
:
2018-06-15T18:00:00.0000000
as a DateTime of UTC kind.
If I pass a ?date=2018-06-11T18:00:00+0100
it will be retrieved as a local time kind and the result would be:
2018-06-11T19:00:00.0000000+02:00
as desired