将DateTimeOffset作为WebAPI查询字符串传递

Aar*_*ell 10 .net c# asp.net-web-api

我有一个WebAPI动作,如下所示:

[Route("api/values/{id}")]
public async Task<HttpResponseMessage> Delete(string id, DateTimeOffset date) {
    //do stuff
}
Run Code Online (Sandbox Code Playgroud)

但是当我从一个HttpClient实例调用它时,创建一个如下的URL:

string.Format("http://localhost:1234/api/values/1?date={0}", System.Net.WebUtility.UrlEncode(DateTimeOffset.Now.ToString()));
// -> "http://localhost:1234/api/values/1?date=17%2F02%2F2015+7%3A18%3A39+AM+%2B11%3A00"
Run Code Online (Sandbox Code Playgroud)

我得到一个400回复,说date不可存在的参数不存在.

我也尝试将该[FromUri]属性添加到参数中,但它仍然没有映射.如果我将其更改为DateTimeOffset?我可以看到它保留为null并且查看Request.RequestUri.Query值是否存在,只是没有映射.

最后,我尝试不做一个WebUtility.UrlEncode,它没有任何不同.

Bra*_*ick 12

回答

要将DateTimeOffsetAPI 发送到您的API,请将其格式化为:

2017-04-17T05:04:18.070Z

完整的API URL如下所示:

http://localhost:1234/api/values/1?date=2017-04-17T05:45:18.070Z

通过以这种方式对其进行格式化,我可以将Z参数传递给我.ToUniversalTime().ToString(yyyy-MM-ddTHH:mm:ss.fffZ)使用Azure Mobile Services创建的参数.

您可以使用.ToUniversalTime()解析DateTimeOffset.

DateTimeOffset currentTime = DateTimeOffset.UtcNow;
string dateTimeOffsetAsAPIParameter = currentDateTimeOffset.ToUniversalTime().ToString("yyyy-MM-ddTHH:mm:ss.fffZ");
string apiUrl = string.Format("http://localhost:1234/api/values/1?date={0}", dateTimeOffsetAsAPIParameter);
Run Code Online (Sandbox Code Playgroud)

  • 请注意,格式化为 `yyyy-MM-ddTHH:mm:ss.fffZ` 会强制将日期格式化为字符串 **没有时区偏移**......在本例中这很好,因为值是 `DateTimeOffset。 UtcNow` 但如果您要使用非 UTC 值,则此格式将不代表实际日期。 (2认同)

Jac*_*ond 12

当前接受的答案会丢弃时区信息,这在某些情况下很重要。以下保持时区并且不会丢失任何精度。它还可以在构建查询字符串时保持代码简洁。

public static string UrlEncode(this DateTimeOffset dateTimeOffset)
{
     return HttpUtility.UrlEncode(dateTimeOffset.ToString("o"));
}
Run Code Online (Sandbox Code Playgroud)

  • 这*绝对*是正确的答案。其他答案没有解决a)偏移量应该是“Z”(对于UTC)或“+xx:xx”(对于非UTC)的想法,以及b)+xx:xx偏移量的问题由于“+”,URL 不友好 (3认同)

Suk*_*and 5

问题是偏移量部分中的+(加号)字符,我们应该对其进行编码。

如果偏移量是-(负)则不需要编码

+(plus)的编码值为% 2B 因此2021-05-05T18:00:00+05:00应作为2021-05-05T18:00:00%2B05:00传递

http://localhost:1234/api/values/1?date=2021-05-05T18:00:00%2B05:00
Run Code Online (Sandbox Code Playgroud)

如果偏移量是- (减号)那么

http://localhost:1234/api/values/1?date=2021-05-05T18:00:00-05:00
Run Code Online (Sandbox Code Playgroud)


小智 2

400 响应消息准确地描述了该问题,尽管它本来可以更清楚。由属性定义的路由仅需要一个参数id,但 Delete 方法需要另一个名为date的参数。

如果要使用查询字符串提供此值,则需要使用“DateTimeOffset?”将该参数设置为可为空,这也会将其转换为可选参数。如果日期是必填字段,请考虑将其添加到路线中,例如:

[Route("api/values/{id}/{date}")]
Run Code Online (Sandbox Code Playgroud)

好吧,忽略我上面输入的内容,这只是格式问题。Web API 很难确定解析给定值所需的区域性,但如果您尝试在查询字符串中使用 JSON 格式传递 DateTimeOffset(例如 2014-05-06T22:24:55Z),那么应该可以工作。

  • 我如何在日期时间中也指定时区 (5认同)