Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Using HttpClient to Send Dates in URL Using AttributeRouting

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.

like image 766
Jammer Avatar asked Aug 05 '13 21:08

Jammer


People also ask

Why do we use HttpClient?

Why Do We Need HttpClient? The front-end of applications communicate with back-end services to get or send the data over HTTP protocol using either XMLHttpRequest interface or fetch API . This communication is done in Angular with the help of HttpClient .

What is HttpClient in Web API?

HttpClient is used to send an HTTP request, using a URL. HttpClient can be used to make Web API requests from the console Application, Winform Application, Web form Application, Windows store Application, etc.


2 Answers

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.

like image 122
Jammer Avatar answered Sep 21 '22 19:09

Jammer


: 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
like image 30
Andrew West Avatar answered Sep 21 '22 19:09

Andrew West