Passing DateTimeOffset as WebAPI query string

2020-02-07 00:11发布

I've got a WebAPI action that looks like so:

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

But when I invoke this from a HttpClient instance, making a URL like:

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"

I get a 400 response back saying that the non-nullable parameter date does not exist.

I've also tried adding the [FromUri] attribute to the parameter but it still doesn't map through. If I change it to be DateTimeOffset? I can see it is left as null and looking at Request.RequestUri.Query the value is there, just not mapped.

Finally I tried not doing a WebUtility.UrlEncode and it made no different.

8条回答
混吃等死
2楼-- · 2020-02-07 00:45

Here is the easiest way for those who are looking for some kind of sync between client and server using datetime. I implemented that for mobile application. It is independent from the culture of the client. because my mobile app supports multiple cultures and it is boring to use formatting between those cultures. thanks that .net has a perfect functions called ToFileTime and FromFileTime

Server Controller Action:

[HttpGet("PullAsync")]
public async Task<IActionResult> PullSync(long? since = null, int? page = null, int? count = null)
{
    if (since.HasValue) 
        DateTimeOffset date = DateTimeOffset.FromFileTime(since.Value);    
}

Client Side

DateTimeOffset dateTime = DateTime.Now.ToFileTime();
var url= $"/PullAsync?since={datetime}&page={pageno}&count=10";
查看更多
Summer. ? 凉城
3楼-- · 2020-02-07 00:52

Answer

To send a DateTimeOffset to your API, format it like this after converting it to UTC:

2017-04-17T05:04:18.070Z

The complete API URL will look like this:

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

It’s important to first convert the DateTimeOffset to UTC, because, as @OffHeGoes points out in the comments, the Z at the end of the string indicates Zulu Time (more commonly known as UTC).

Code

You can use .ToUniversalTime().ToString(yyyy-MM-ddTHH:mm:ss.fffZ) to parse the DateTimeOffset.

To ensure your DateTimeOffset is formatted using the correct timezone always use .ToUniversalTime() to first convert the DateTimeOffset value to UTC, because the Z at the end of the string indicates UTC, aka "Zulu Time".

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);
查看更多
登录 后发表回答