How to have WebApi querystring parameter binding keep UTC dates?

大憨熊 提交于 2019-12-08 21:53:47

问题


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.


回答1:


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



来源:https://stackoverflow.com/questions/26553122/how-to-have-webapi-querystring-parameter-binding-keep-utc-dates

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!