Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to have WebApi querystring parameter binding keep UTC dates?

I am sending in my querystring a UTC date, e.g.

&EndDate=2000-01-02T03%3a04%3a05.0060000Z

And my controller parameter binds it in a complex object, e.g.

    public async Task<DocumentsRequest> GetEchoFromUriDocumentsAsync(
                                            [FromUri] DocumentsRequest request)
    {
        return request; 
    }

What I've managed to figure out is that my object after parameter binding, changes my UTC date to a local date + offset. Here is a snippet of my test case

    [TestMethod]
    public void Should_generate_querystring_and_parameter_bind_correctly()
    {

        DocumentsRequest request = DocumentRequestBuilder.DocumentsRequest();
        string queryString = ReflectionQueryStringConverter.ToQueryString(request);

        string baseUrl = "http://baseUrl/Test/EchoFromUriDocuments";
        string uri = baseUrl + queryString;
        HttpResponseMessage response = _client.GetAsync(uri).Result;
        string outputString = response.Content.ReadAsStringAsync().Result;

        JsonSerializer<DocumentsRequest> serializer = 
            new JsonSerializer<DocumentsRequest>();
        DocumentsRequest output = serializer.DeserializeFromString(outputString);

        output.EndDate.Should().Be(request.EndDate);
 }

The above is failing because the output is:

2000-01-01T19:04:05.006-08:00

But, the json serialization then truncates the offset and assumes it is UTC date... and as you can see, the dates don't match up post-round-trip.

There is a similar question here, but not really an answer (the poster answered is own question)

Passing UTC DateTime to Web API HttpGet Method results in local time

What is the correct solution to resolve this issue? I think the issue is that I want the parameter binding to parse the querystring as UTC a date. Is TypeConverter the way to go? Anyone have a complete sample of how to do that? Would I have to use the TypeConverter on all attribute on all my classes with DateTime? I was hoping for a global configuration of sorts.

Thanks.

like image 457
Raymond Avatar asked Oct 24 '14 17:10

Raymond


People also ask

How do I pass a date in query string?

string dateTime = Request. QueryString["DateStarted"]; DateTime dt = Convert. ToDateTime(dateTime); Response.

How do we do parameter binding in Web API?

When Web API calls a method on a controller, it must set values for the parameters, a process called binding. By default, Web API uses the following rules to bind parameters: If the parameter is a "simple" type, Web API tries to get the value from the URI.

How do you pass date parameters?

Answer. The passing of Date parameters is done in a very specific format, based on the International Date formatting standard. For any Cognos software , parameters specified in the URL for a date / time parameter, should not include a value for milliseconds, and this value should be set to zero.


1 Answers

I've solved similar issue by using DateTimeOffset class instead of DateTime. Please look to this answer:

DateTime vs DateTimeOffset

DateTimeOffset class stores your time zone information in additional field. So, you should change your data model class DocumentsRequest and use DateTimeOffset.

Next, you should synchronize your WebAPI formatter with the browser. I use Newtonsoft.Json library with the following settings:

var jsonSettings = new JsonSerializerSettings
{
    // Note the ISO format
    DateFormatHandling = DateFormatHandling.IsoDateFormat,
    DefaultValueHandling = DefaultValueHandling.Include,
    TypeNameHandling = TypeNameHandling.Auto
}

And I registered this settings in the WebAPI registration class:

public static class WebApiConfig
{
    public static void Register(HttpConfiguration config)
    {
        ...

        config.Formatters.Remove(config.Formatters.XmlFormatter);
        config.Formatters.JsonFormatter.SerializerSettings = jsonSettings;
    }
}

And, on the browser's side use ISO date time format:

ISO date time format in WWW

like image 93
omikad Avatar answered Oct 09 '22 20:10

omikad