将UTC DateTime传递给Web API HttpGet方法会产生本地时间

Rya*_*yan 41 datetime json model-binding asp.net-web-api

我正在尝试将UTC日期作为查询字符串参数传递给Web API方法.URL看起来像

/api/order?endDate=2014-04-01T00:00:00Z&zoneId=4
Run Code Online (Sandbox Code Playgroud)

方法的签名看起来像

[HttpGet]
public object Index(int zoneId, DateTime? endDate = null)
Run Code Online (Sandbox Code Playgroud)

日期即将到来,31/03/2014 8:00:00 PM但我希望它可以进入01/04/2014 12:00:00 AM

JsonFormatter.SerializerSettings看起来像这样

new JsonSerializerSettings
{
    ContractResolver = new CamelCasePropertyNamesContractResolver(),
    DateTimeZoneHandling = DateTimeZoneHandling.Utc,
    DateFormatHandling = DateFormatHandling.IsoDateFormat
};
Run Code Online (Sandbox Code Playgroud)

编辑#1:我注意到,当我发布2014-04-01T00:00:00Z它时,它将序列化为C#中的UTC DateTime类型.然而,我发现了一个endDate.Value.ToUniversalTime()改变它的工作,虽然我觉得奇怪的是它如何用于POST而不是GET.

Bad*_*dri 36

您要发送的查询字符串参数值2014-04-01T00:00:00Z是UTC时间.因此,相同的时间会转换为基于本地时钟的时间,如果您打电话ToUniversalTime(),它会转换回UTC.

那么,究竟是什么问题呢?如果问题是为什么发生这种情况如果作为查询字符串发送而不是在请求正文中发布时,该问题的答案是ASP.NET Web API使用模型绑定和正文使用绑定 URI路径,查询字符串等参数绑定.对于后者,它使用媒体格式化程序.如果发送JSON,则使用JSON媒体格式化程序,它基于JSON.NET.

由于您已指定DateTimeZoneHandling.Utc,因此它使用该设置,您可以获得所需的日期时间.顺便说一句,如果您将此设置更改为DateTimeZoneHandling.Local,则您将看到与模型绑定相同的行为.

  • 这应该不是答案.虽然它解释了发生了什么,但它没有提供问题的解决方案.OP表示他们希望时间以UTC身​​份进入,而不是以本地方式进入并转换为UTC.如果这是不可能的,那么你的答案就不会那么明确,如果是,你就不说这是如何实现的.我也有同样的问题.每次收到约会时我都不想调用ToUniversalTime().我想收到UTC时间.是否有一些自动执行此操作的反序列化设置? (9认同)

Sea*_*ett 26

如果您希望转换是透明的,那么您可以使用自定义TypeConverter:

public sealed class UtcDateTimeConverter : DateTimeConverter
{
    public override object ConvertFrom(ITypeDescriptorContext context, CultureInfo culture, object value)
    {
        return ((DateTime)base.ConvertFrom(context, culture, value)).ToUniversalTime();
    }
}
Run Code Online (Sandbox Code Playgroud)

并使用以下方式连接它:

TypeDescriptor.AddAttributes(typeof(DateTime), new TypeConverterAttribute(typeof(UtcDateTimeConverter)));
Run Code Online (Sandbox Code Playgroud)

然后将查询字符串参数实例化为DateTimeKind.Utc.

  • 有什么解决方案可以将此UtcDateTimeConverter添加到Web api中的startup.cs类的Register方法中?我没办法补课 (2认同)

Rya*_*yan 13

我最后只是使用该ToUniversalTime()方法作为参数进来.