5

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 400 Bad Request responses.

My API route looks like this:

    [System.Web.Http.HttpGet]
    [GET("range/{start:datetime}/{end:datetime}")]
    public HttpResponseMessage Get(DateTime start, DateTime end)

I'm using the AttributeRouting library and according to this page the URL I'm requesting should be fine.

My request URL looks like this:

http://localhost:51258/plots/range/2013-07-29T21:58:39/2013-08-05T21:58:39

I have this set on the controller RoutePrefix("plots") which is where the plots bit of the URL route comes from.

If I strip the times off the DateTime objects everything works fine but I need the times passed.

8
  • It might be because that isn't a standard DateTime format in C#. The date part is fine, and so is the time, however the T in between them makes it non standard. I would try replacing it with a space. If that works then you'll know what needs to be done. Commented Aug 5, 2013 at 21:11
  • I've added the T since it didn't work with a space or an encoded space either. According to Mike Wasson (in the page link) the addition of the T is legal and should be working. Commented Aug 5, 2013 at 21:19
  • Have you added the regex he mentioned (in the link) to your DateTime? Then only dates in the form "yyyy-mm-dd" will match. Commented Aug 5, 2013 at 21:28
  • No, I've kept it as simple as possible until I get this basic implementation working. Commented Aug 5, 2013 at 21:30
  • I just visited my routes.axd page on the API and tried to execute a request http://localhost:51258/plots/range/2013-07-29T21:58:39/2013-07-29T21:58:39 and got this error A potentially dangerous Request.Path value was detected from the client (:). So it seems that : might actually be an illegal character ... Commented Aug 5, 2013 at 22:02

2 Answers 2

7

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.

Sign up to request clarification or add additional context in comments.

Comments

1

: 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

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.