Reputation: 1061
Currently to send a parameterized GET request to an API interface I am writing the following code:
api/master/city/filter?cityid=1&citycode='ny'
But I see that there is a limit on the URL length of 2,083 characters.
To avoid this I would like to send the parameters in json format in the content body for a GET request.
However, I see that none of the Get methods for the HttpClient allow for a content body to be sent. For the POST I could see there is a method within HttpClient named PostAsync that allows for a content body.
Is there a way to send parameters for a GET request not in the URL in order to avoid the URL length limit?
Upvotes: 76
Views: 215824
Reputation: 29919
Please read the caveats at the end of this answer as to why HTTP GET requests with bodies are, in general, not advised.
If you are using .NET 5+ or .NET Core, the standard HttpClient
can do this out-of-the-box. For example, to send a GET request with a JSON body:
HttpClient client = ...
...
var request = new HttpRequestMessage
{
Method = HttpMethod.Get,
RequestUri = new Uri("some url"),
Content = new StringContent(
"some json",
Encoding.UTF8,
MediaTypeNames.Application.Json), // or "application/json" in older versions
};
var response = await client.SendAsync(request)
.ConfigureAwait(false);
response.EnsureSuccessStatusCode();
var responseBody = await response.Content.ReadAsStringAsync()
.ConfigureAwait(false);
.NET Framework doesn't support this out-of-the-box (you will receive a ProtocolViolationException
if you try the above code). Thankfully Microsoft has provided the System.Net.Http.WinHttpHandler package that does support the functionality - simply install and use it instead of the default HttpClientHandler
when constructing your HttpClient
instances:
var handler = new WinHttpHandler();
var client = new HttpClient(handler);
<rest of code as above>
Reference: https://github.com/dotnet/runtime/issues/25485#issuecomment-467261945
Caveats:
Upvotes: 131
Reputation: 31
I use WebRequest. The value is in variable json.
var request = WebRequest.Create(requestUri);
System.Net.ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12 | SecurityProtocolType.Tls11 | SecurityProtocolType.Tls;
request.ContentType = "application/json";
request.Method = "GET";
request.Headers.Add("Authorization", "Bearer " + Token);
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(JsonConvert.SerializeObject(Entity));
}
var response = request.GetResponse();
var responseStream = response.GetResponseStream();
if (responseStream != null)
{
var myStreamReader = new StreamReader(responseStream, Encoding.Default);
var resultEntity= myStreamReader.ReadToEnd();
myStreamReader.ReadToEnd());
}
responseStream.Close();
response.Close();
Upvotes: 3
Reputation: 583
After spending a lot of time I couldn't make neither HttpClient
nor WebRequest
work in my .Net Core project, apparently the server was not getting my data and it returned an error saying some specific data was not available in my request. At last only RestSharp
worked in my case (the variable myData
is a Dictionary<string,string>
instance in the following code):
var client = new RestClient("some url");
var request = new RestRequest(Method.GET);
foreach (var d in myData)
request.AddParameter(d.Key, d.Value);
var result = (await client.ExecuteAsync(request)).Content;
Upvotes: 1
Reputation: 4654
I can't use .NET core and I don't want to install System.Net.Http.WinHttpHandler
, which has a ton of dependencies.
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.
Upvotes: 41
Reputation: 44
similar to above answer but less code
var request = new HttpRequestMessage
{
Method = HttpMethod.Get,
RequestUri = targetUri,
Content = new StringContent(payload.Payload),
};
var response = await client.SendAsync(request).ConfigureAwait(false);
var responseInfo = await response.Content.ReadAsStringAsync();
Upvotes: -3