6

How can I call HTTP GET using JSON parameters in content body?

I tried this:

HttpWebRequest.WebRequest.Create(_uri);
httpWebRequest.ContentType = "application/json";
httpWebRequest.Method = "GET";
httpWebRequest.Headers.Add("X-AUTH-TOKEN", _apiKey);

using(var streamWriter = new StreamWriter(httpWebRequest.GetRequestStream())) {
  string _json = "\"{\"filter\": {\"relation\": \"equals\", \"attribute\": \"state\", \"value\": \"CA\"  },  \"insights\": {\"field\": \"family.behaviors\",  \"calculations\": [\"fill_count\"]}}";

  streamWriter.Write(_json);
  streamWriter.Flush();
  streamWriter.Close();
}

var httpResponse = (HttpWebResponse) httpWebRequest.GetResponse();
using(var streamReader = new StreamReader(httpResponse.GetResponseStream())) {
  var result = streamReader.ReadToEnd();
}

but it throws an exception:

"Cannot send a content-body with this verb-type."

Drenmi
  • 8,492
  • 4
  • 42
  • 51
Donald
  • 551
  • 2
  • 6
  • 22
  • Use POST if you want to save and use PUT if you want to update in the httpWebRequest.Method – Rashedul.Rubel Jan 23 '19 at 04:16
  • You can tick it by setting method to POST, then write body, and then changing method back to GET. That works, but I DO NOT know if it actually sends the body after such dirty thing. You may need packet capture/access to server/test results to actually figure that out. – Max Jan 23 '19 at 04:40
  • Use POST as method type. And if you use HttpClient that would be better. As you would get async method out of the box and it is easy to use. – R.Sarkar Jan 24 '19 at 06:08
  • Possible duplicate of [Possible for HttpClient to send content or body for GET request?](https://stackoverflow.com/questions/43421126/possible-for-httpclient-to-send-content-or-body-for-get-request) – Ian Kemp May 09 '19 at 12:02

4 Answers4

6

If you use .NET core, the new HttpClient can handle this. Otherwise you can use System.Net.Http.WinHttpHandler package, but it has a ton of dependencies. See answer

https://stackoverflow.com/a/47902348/1030010

for how to use these two.

I can't use .NET core and I don't want to install System.Net.Http.WinHttpHandler. I solved it by using reflection, to trick WebRequest that it is legal to send body with a GET request (which is according to latest RFC). What I do is to set ContentBodyNotAllowed to false for HTTP verb "GET".

var request = WebRequest.Create(requestUri);

request.ContentType = "application/json";
request.Method = "GET";

var type = request.GetType();
var currentMethod = type.GetProperty("CurrentMethod", BindingFlags.NonPublic | BindingFlags.Instance).GetValue(request);

var methodType = currentMethod.GetType();
methodType.GetField("ContentBodyNotAllowed", BindingFlags.NonPublic | BindingFlags.Instance).SetValue(currentMethod, false);

using (var streamWriter = new StreamWriter(request.GetRequestStream()))
{
    streamWriter.Write("<Json string here>");
}

var response = (HttpWebResponse)request.GetResponse();

Note, however, that the attribute ContentBodyNotAllowed belongs to a static field, so when its value changes, it remains in effect for the rest of the program. That's not a problem for my purposes.

alfoks
  • 4,324
  • 4
  • 29
  • 44
  • As somebody who understands systems integration and the difficulties with proxies and third party servers flagging this type of transaction as a malformed request... I want to say thank you for this finding. If my own MicroServices are talking to each other and I want to put a Body into a GET... I should be allowed. I tested this and it works perfect. – Suamere Apr 27 '20 at 21:03
  • It's from "dirty hack" category, but IT WORKS! Thanks!!! – Mad Scientist Sep 02 '21 at 10:25
1

It is entirely possible, but you have to use the newer HttpClient class: https://stackoverflow.com/a/47902348/70345

Ian Kemp
  • 28,293
  • 19
  • 112
  • 138
0

GET will only receive it.

If you need to specify parameters, please include it in url.
Or you can send JSON BODY if POST or PUT.

HTTP request methods

HTTP defines a set of request methods to indicate the desired action to be performed for a given resource. Although they can also be nouns, these request methods are sometimes referred as HTTP verbs. Each of them implements a different semantic, but some common features are shared by a group of them: e.g. a request method can be safe, idempotent, or cacheable.

  • GET
    The GET method requests a representation of the specified resource. Requests using GET should only retrieve data.
  • HEAD
    The HEAD method asks for a response identical to that of a GET request, but without the response body.
  • POST
    The POST method is used to submit an entity to the specified resource, often causing a change in state or side effects on the server.
  • PUT
    The PUT method replaces all current representations of the target resource with the request payload.

In Addition:

I found this. Long discussion has been held.
HTTP GET with request body

What this means is that it is possible to send BODY with GET, but sending a payload body on a GET request might cause some existing implementations to reject the request (such as Proxy in the middle of the route).

Please be sure to read this article carefully as there are many other points to pay attention to.


By the way, it seems that you can send GET with body using the -i option of cURL command.

Curl GET request with json parameter

kunif
  • 4,060
  • 2
  • 10
  • 30
0

Even tho it is technically allowed to send a body with Get requests, Microsoft has decided for you that you cannot do that.

This can be seen in HttpWebRequest source code:

if (onRequestStream) {
// prevent someone from getting a request stream, if the protocol verb/method doesn't support it
    throw new ProtocolViolationException(SR.GetString(SR.net_nouploadonget));
}

So you need to change your verb to Put or Post or have some other workaround.

JohanP
  • 5,252
  • 2
  • 24
  • 34