控制WebAPI中DateTime参数的格式
本文关键字:格式 参数 DateTime WebAPI 控制 | 更新日期: 2023-09-27 18:08:06
所以我有一个用c#编写的WebAPI 2控制器,它在其他事情中接受DateTime类型的查询参数。这是一个API,它根据日期过滤器从数据存储返回所有值。比如,我们说:
public MyThing GetThing([FromUri]DateTime startTime)
{
// filter and return some results
}
我遇到了两个问题:
- 由于某些原因,尽管传入了ISO 8601 UTC格式(带Z)日期,WebAPI将其反序列化为本地DateTime而不是UTC。这显然是不可取的。我不确定如何修改管道,使其正确理解UTC-0日期时间。
- 我返回一个链接回到资源作为响应体的一部分,其中我使用UrlHelper对象(从父ApiController抽象类获得)link()方法来生成一个href。我正在传递我想要添加到路由的查询参数集合。无论出于何种原因,传递DateTime将其格式化为非iso8601格式。我找不到被控制的地方。我不想显式地使用ToString(),因为这不是通用的。
简而言之,我想弄清楚如何确保
- 通过FromUri查询参数传入的日期时间被正确理解为ISO8601,包括适当的时区偏移
- UrlHelper.Link()以通用强制的静态类型方式在输出URI字符串中生成符合iso8601的日期时间。
您可以使用modelbinder将传入的数据转换为您的模型。
GetThings([ModelBinder(typeof(UtcDateTimeModelBinder)), FromUri] DateTime dt){//do somthing}
public class UtcDateTimeModelBinder : IModelBinder
{
public object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext)
{
if (bindingContext == null)
{
throw new ArgumentNullException(nameof(bindingContext));
}
if (bindingContext.ModelMetadata.ModelType == typeof(DateTime))
{
var valueProviderResult = bindingContext.ValueProvider.GetValue(bindingContext.ModelName);
var str = valueProviderResult.AttemptedValue;
return DateTime.Parse(str).ToUniversalTime();
}
return null;
}
这样你就可以将它设置为DateTime的默认建模器。
ModelBinders.Binders.Add(typeof(DateTime), new UtcDateTimeModelBinder());
如果你想保持UTC偏移量,为什么不使用DateTimeOffset而不是DateTime ?下面是一些使用JSON序列化的代码:
Api控制器:public class ValuesController : ApiController
{
public object Get(DateTimeOffset dt)
{
return new {
Input = dt,
Local = dt.LocalDateTime,
Utc = dt.UtcDateTime
};
}
}
Razor View示例代码(假设你在MVC + Web api Visual studio模板中创建了默认的api路由)
<a href="@Url.RouteUrl("DefaultApi",new {httproute = "",controller = "values",dt = DateTimeOffset.UtcNow})">Utc Now</a>
呈现为:
<a href="/api/values?dt=06%2F26%2F2018%2009%3A37%3A24%20%2B00%3A00">Utc Now</a>
你可以用datetime offset来调用API:
2018-06-26T08:25:48Z: http://localhost:1353/api/values?dt=2018-06-26T08:25:48Z
{"Input":"2018-06-26T08:25:48+00:00","Local":"2018-06-26T10:25:48+02:00","Utc":"2018-06-26T08:25:48Z"}
2018-06-26T08:25:48+01:00: http://localhost:1353/api/values?dt=2018-06-26T08%3A25%3A48%2B01%3A00 (note that : and + must be url encoded)
{"Input":"2018-06-26T08:25:48+01:00","Local":"2018-06-26T09:25:48+02:00","Utc":"2018-06-26T07:25:48Z"}
发送的查询字符串参数值是UTC时间。所以,同样的会被翻译成基于本地时钟的时间你调用
ToUniversalTime()
,它被转换回UTC那么,问题到底是什么呢?如果问题是为什么会这样如果作为查询字符串发送,而不是在请求中发布时发生,这个问题的答案是ASP。. NET Web API绑定URI路径,查询字符串等使用模型绑定和主体使用参数绑定。对于后者,它使用媒体格式化器。如果你发送JSON,使用JSON媒体格式化器,它是基于JSON.NET的。
因为你指定了DateTimeZoneHandling。它使用Utc设置,你得到你想要的日期时间类型。顺便说一句,如果你改变此设置为DateTimeZoneHandling。本地的,然后你会看到相同的行为作为模型绑定。
意思是为了得到你想要的格式,你所需要做的就是调用ToUniversalTime()
方法。
1.
你应该检查你的参数'startTime'的时区(它应该是你的服务器/计算机的时区)。
Web API提供的DateTime是正确的,它只是取决于你的时区。
2。
创建一个Json DateTime序列化器以生成ISO8601格式的日期