I\'m having some problems getting a date range query accepted by my WebAPI. As as far as I can tell from everything I\'ve read this should be working but I still get
:
is a reserved character in the URL but it's acceptable in a query string. So if it works for your routing you could simply use:
[System.Web.Http.HttpGet]
[GET("range")]
public HttpResponseMessage Get(DateTime start, DateTime end)
and your URL request can look like this:
http://localhost:51258/plots/range?start=2013-07-29T21:58:39&end=2013-08-05T21:58:39
After doing a lot of reading it appears that it is possible to do what I was attempting to do but it requires relaxing a lot of useful security measures in order to do so. Since there is a simple workaround it just doesn't make sense to relax these measures in light of increased security risks.
The error I was getting at the API was:
A potentially dangerous Request.Path value was detected from the client (:)
Obviously this is the colon characters used to separate the elements of the time portion of the DateTime
string. So I have made the following changes.
My Api action method now looks like this:
[System.Web.Http.HttpGet]
[GET("range?{startDate:datetime}&{endDate:datetime}")]
public HttpResponseMessage Get(DateTime startDate, DateTime endDate)
The dates are now defined as part of the query string rather than parts of the path itself.
To handle the creation of the query string I also have the following extension method:
public static string ToQueryString(this NameValueCollection source, bool removeEmptyEntries)
{
return source != null ? "?" + String.Join("&", source.AllKeys
.Where(key => !removeEmptyEntries || source.GetValues(key).Any(value => !String.IsNullOrEmpty(value)))
.SelectMany(key => source.GetValues(key)
.Where(value => !removeEmptyEntries || !String.IsNullOrEmpty(value))
.Select(value => String.Format("{0}={1}", HttpUtility.UrlEncode(key), value != null ? HttpUtility.UrlEncode(value) : string.Empty)))
.ToArray())
: string.Empty;
}
Which is used in my client code like this:
var queryStringParams = new NameValueCollection
{
{"startDate", start.ToString(_dateService.DefaultDateFormatStringWithTime)},
{"endDate", end.ToString(_dateService.DefaultDateFormatStringWithTime)}
};
var response = httpClient.GetAsync(ApiRootUrl + "plots/range" + queryStringParams.ToQueryString(true)).Result;
The date service in my application simply provides the default date formatting string and uses this pattern:
"yyyy-MM-ddTHH:mm:ss"
The complete URI that is produced from this looks like:
http://localhost:51258/plots/range?startDate=2013-07-30T21%3A48%3A26&endDate=2013-08-06T21%3A48%3A26
Hope this helps someone else in the future.