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.
Create a custom type converter as follows:
In your startup sequence, such as
WebApiConfig.Register
, add this type converter dynamically to theDateTimeOffset
struct:You can now just pass
DateTimeOffset
values in the compact form of ISO8601, which omits hyphens and colons that interfere with the URL:Note that if you have fractional seconds, you may need to include a trailing slash in the url.
You could also put it in the querystring if you like:
Use the ISO 8601 datetime format specifier:
or
To achieve this, I'm using
The current accepted answer throws away the time zone information, which in some cases is important. The following maintains the time zone and doesn't lose any precision. It also keeps your code succinct when building a query string.
Best way to find out is to ask the WebAPI to generate the expected URL format itself:
When a call to /offset is made the response will return a 302 to a url that contains the 'date' parameter in the querystring. It will look something like this:
I could not find an overload of DateTimeOffset.ToString() that would generate a string value in that format except for explicitly defining the format in a string format:
Hope that helps.
The problem is being described exactly by the 400 response message, although it could have been more clear. The route, as defined by the attribute, only expects a parameter id, but the Delete method expects another parameter called date.If you want to provide this value using the query string, you'll need to make that parameter nullable, by using "DateTimeOffset?", which would also transform it into an optional parameter. If the date is a required field, consider adding it to the route, like:
OK, ignore what I typed above, it's just a formatting problem. Web API has trouble figuring out the culture needed to parse the given value, but if you try to pass on DateTimeOffset using a JSON format in the query string, like 2014-05-06T22:24:55Z, that should work.