I am banging my head against a wall trying to convert a working curl command to a c# WebRequest.
I have read through quite a few postings and I was pretty sure I had the code right but it still will not work.
Can anyone see what I am doing wrong please?
Here is the working curl command:
curl -k -u x:reallylongstring -H "Content-Type: application/json" https://api.somewhere.com/desk/external_api/v1/customers.json
And this is the code I have written in c#:
WebRequest wrGETURL;
wrGETURL = WebRequest.Create("https://api.somewhere.com/desk/external_api/v1/customers.json");
wrGETURL.Method = "GET";
wrGETURL.ContentType = "application/json";
wrGETURL.Credentials = new NetworkCredential("x", "reallylongstring");
Stream objStream = wrGETURL.GetResponse().GetResponseStream();
StreamReader objReader = new StreamReader(objStream);
string responseFromServer = objReader.ReadToEnd();
But the api responds:
The remote server returned an error: (406) Not Acceptable.
Any help would be much appreciated!
Thanks
Based on Nikolaos's pointers I appear to have fixed this with the following code:
public static gta_allCustomersResponse gta_AllCustomers()
{
var httpWebRequest = (HttpWebRequest)WebRequest.Create("https://api.somewhere.com/desk/external_api/v1/customers.json");
httpWebRequest.ContentType = "application/json";
httpWebRequest.Accept = "*/*";
httpWebRequest.Method = "GET";
httpWebRequest.Headers.Add("Authorization", "Basic reallylongstring");
var httpResponse = (HttpWebResponse)httpWebRequest.GetResponse();
using (var streamReader = new StreamReader(httpResponse.GetResponseStream()))
{
gta_allCustomersResponse answer = JsonConvert.DeserializeObject<gta_allCustomersResponse>(streamReader.ReadToEnd());
return answer;
}
}
Here is my solution to post json data to using an API call or webservice
public static void PostJsonDataToApi(string jsonData)
{
var httpWebRequest = (HttpWebRequest)WebRequest.Create("https://api.somewhere.com/v2/cases");
httpWebRequest.ReadWriteTimeout = 100000; //this can cause issues which is why we are manually setting this
httpWebRequest.ContentType = "application/json";
httpWebRequest.Accept = "*/*";
httpWebRequest.Method = "POST";
httpWebRequest.Headers.Add("Authorization", "Basic ThisShouldbeBase64String"); // "Basic 4dfsdfsfs4sf5ssfsdfs=="
using (var streamWriter = new StreamWriter(httpWebRequest.GetRequestStream()))
{
// we want to remove new line characters otherwise it will return an error
jsonData= thePostBody.Replace("\n", "");
jsonData= thePostBody.Replace("\r", "");
streamWriter.Write(jsonData);
streamWriter.Flush();
streamWriter.Close();
}
try
{
HttpWebResponse resp = (HttpWebResponse)httpWebRequest.GetResponse();
string respStr = new StreamReader(resp.GetResponseStream()).ReadToEnd();
Console.WriteLine("Response : " + respStr); // if you want see the output
}
catch(Exception ex)
{
//process exception here
}
}
This is the curl command I use to post json data:
curl http://IP:PORT/my/path/to/endpoint -H 'Content-type:application/json' -d '[{...json data...}]'
This is equivalent to the above curl command with C#:
var url = "http://IP:PORT/my/path/to/endpoint";
var jsonData = "[{...json data...}]";
using (var client = new WebClient())
{
client.Headers.Add("content-type", "application/json");
var response = client.UploadString(url, jsonData);
}
According to this question regarding 406: What is "406-Not Acceptable Response" in HTTP? perhaps you could try adding an Accept header to your request? Maybe curl adds that automatically.
Also there's a -k in your curl request telling it to ignore SSL validation, which I'm not sure if it affects the .NET code. In other words, does curl still work without the '-k'? Then, no worries. Otherwise, perhaps you need to tell .NET to also ignore SSL validation.
Related
I am attempting to make a POST request to a server. The following works when I CURL using git Bash:
curl -X POST -H "Content-Type: application/octet-stream" -H "User-Agent: MyUserAgent" --data-binary #MyDocument.xlsx http://myUrl.com
I know I can make POST requests using json as follows (in C#):
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(myUrl);
request.Method = "POST";
request.ContentType = "application/json";
request.Accept = "application/json";
request.UserAgent = myUserAgent;
using (var stream = await request.GetRequestStreamAsync())
{
using (StreamWriter streamWriter = new StreamWriter(stream))
{
streamWriter.Write(myJsonData);
}
}
using (HttpWebResponse webResponse = (HttpWebResponse) await request.GetResponseAsync())
{
using (StreamReader reader = new StreamReader(webResponse.GetResponseStream()))
{
string response = reader.ReadToEnd();
//do stuff with response
}
}
My difficulty is basically combining the two. I know I need to change the request.ContentType to "application/octet-stream", but that is not enough. How do I incorporate the "--data-binary #MyDocument.xlsx" in the HttpWebRequest?
Anyone have any ideas? Thanks!
I suggest you look into WebClient since it's easier to implement:
WebClient client = new WebClient();
byte[] response = client.UploadFile(myUrl,fileName);
I'm trying to use .net to put datapoints in OpenTSDB, using the HTTP /api/put API.
I've tried with httpclient, webRequest and HttpWebRequest. The outcome is always 400 - bad request: chunked request not supported.
I've tried my payload with an api tester (DHC) and works well.
I've tried to send a very small payload (even plain wrong, like "x") but the reply is always the same.
Here's one of my code instances:
public async static Task PutAsync(DataPoint dataPoint)
{
try
{
HttpWebRequest http = (HttpWebRequest)WebRequest.Create("http://127.0.0.1:4242/api/put");
http.SendChunked = false;
http.Method = "POST";
http.ContentType = "application/json";
Encoding encoder = Encoding.UTF8;
byte[] data = encoder.GetBytes( dataPoint.ToJson() + Environment.NewLine);
http.Method = "POST";
http.ContentType = "application/json; charset=utf-8";
http.ContentLength = data.Length;
using (Stream stream = http.GetRequestStream())
{
stream.Write(data, 0, data.Length);
stream.Close();
}
WebResponse response = http.GetResponse();
var streamOutput = response.GetResponseStream();
StreamReader sr = new StreamReader(streamOutput);
string content = sr.ReadToEnd();
Console.WriteLine(content);
}
catch (WebException exc)
{
StreamReader reader = new StreamReader(exc.Response.GetResponseStream());
var content = reader.ReadToEnd();
}
return ;
}
where I explicitly set to false the SendChunked property.
note that other requests, like:
public static async Task<bool> Connect(Uri uri)
{
HttpWebRequest http = (HttpWebRequest)WebRequest.Create("http://127.0.0.1:4242/api/version");
http.SendChunked = false;
http.Method = "GET";
// http.Headers.Clear();
//http.Headers.Add("Content-Type", "application/json");
http.ContentType = "application/json";
WebResponse response = http.GetResponse();
var stream = response.GetResponseStream();
StreamReader sr = new StreamReader(stream);
string content = sr.ReadToEnd();
Console.WriteLine(content);
return true;
}
work flawlessly.
I am sure I am doing something really wrong.
I'd like to to reimplement HTTP in Sockets from scratch.
I've found a solution I'd like to share here.
I've used wireshark to sniff my packets, and I've found that this header is added:
Expect: 100-continue\r\n
(see 8.2.3 of https://www.w3.org/Protocols/rfc2616/rfc2616-sec8.html)
This is the culprit. I've read the post http://haacked.com/archive/2004/05/15/http-web-request-expect-100-continue.aspx/ by Phil Haack, and found that HttpWebRequest puts that header by default, unless you tell it to stop. In this article I've found that using ServicePointManager I can do just this.
Putting the following code on top of my method, when declaring the http object, makes it work very well, and solves my issue:
var uri = new Uri("http://127.0.0.1:4242/api/put");
var spm = ServicePointManager.FindServicePoint(uri);
spm.Expect100Continue = false;
HttpWebRequest http = (HttpWebRequest)WebRequest.Create(uri);
http.SendChunked = false;
I'm trying to do a HTTP GET request for a json file from an api in a C# application. I'm having trouble getting the authorization, request headers and the webresponse (.GetResponse not working).
The example on the api's site is in curl.
curl -H "Authorization: Bearer ACCESS_TOKEN" https://erikberg.com/nba/boxscore/20120621-oklahoma-city-thunder-at-miami-heat.json
Here is my request method, which will also include JSON deseralization
public static string HttpGet(string URI)
{
HttpWebRequest req = (HttpWebRequest)WebRequest.Create(URI);
// Not sure if the credentials input is the correct
string cred = $"{"Bearer"} {"ACCESS_TOKEN_IS_A_GUID"}";
req.Headers[HttpRequestHeader.Authorization] = cred;
req.Method = "GET";
// GetResponse() is "red", won't work.
WebResponse response = req.GetResponse();
using (Stream responseStream = response.GetResponseStream())
{
StreamReader reader = new StreamReader(responseStream, Encoding.UTF8);
return reader.ReadToEnd().Trim();
}
}
EDIT It was resolved. The problem was that the request was for a GZIP file and that had to be decompressed
var request = (HttpWebRequest)WebRequest.Create(requestUri);
request.UserAgent = userAgent;
request.ContentType = "application/json";
request.Method = WebRequestMethods.Http.Get;
request.Headers[HttpRequestHeader.Authorization] = bearer;
request.Headers[HttpRequestHeader.AcceptEncoding] = "gzip";
var response = (HttpWebResponse) request.GetResponse();
string jsonString;
using (var decompress = new GZipStream(response.GetResponseStream(), CompressionMode.Decompress))
{
using (var sr = new StreamReader(decompress))
jsonString = sr.ReadToEnd().Trim();
}
_Game = JsonConvert.DeserializeObject<Game>(jsonString);
You are not getting it because you don't have access.
The cURL command from API's site(that you mentioned in your question) gives the following JSON
{
"error" : {
"code" : "401",
"description" : "Invalid access token: ACCESS_TOKEN"
}
}
And so does the following code:
HttpWebRequest req = (HttpWebRequest)WebRequest.Create("URL");
req.UserAgent = "Bearer";
WebResponse response = req.GetResponse();
So what you need is a valid username/password or userAgent. You might want to contact the site for that.
I'm working on Salesforce and wanting to get cases fields in it. found the command
curl https://yoursite.desk.com/api/v2/cases \
-u email:password \
-H 'Accept: application/json'
And I tried it in command prompt as
curl https://xxx.desk.com/api/v2/cases \-u abc#gmail.com:xxxxxxxxx \ -H 'Accept: application/json'
I have tried the below code in C#
HttpWebRequest httpWebRequest = (HttpWebRequest)WebRequest.Create("https://xxxx.desk.com/api/v2/cases");
httpWebRequest.ContentType = "application/json";
httpWebRequest.Accept = "text/xml";
httpWebRequest.Method = "GET";
httpWebRequest.Credentials = new NetworkCredential("username", "password");
var response = httpWebRequest.GetResponse();
But it is returning an error
The remote server returned an error: (401) Unauthorized.
CURL is just a client for WebRequests
the default C# option is
WebRequest Class
you can also use Restsharp
var httpWebRequest = (HttpWebRequest)WebRequest.Create("https://xxxx.desk.com/api/v2/cases");
httpWebRequest.ContentType = "application/json";
httpWebRequest.Accept = "text/xml";
httpWebRequest.Method = "GET";
httpWebRequest.Credentials = new NetworkCredential("username", "password");
httpWebRequest.Headers.Add("Authorization", "Basic reallylongstring");
var httpResponse = (HttpWebResponse)httpWebRequest.GetResponse();
string text;
using (var streamReader = new StreamReader(httpResponse.GetResponseStream()))
{
string fddf = streamReader.ReadToEnd();
}
I'm working with Spreedly, and I'm running into what I would assume is a minor problem.
For the life of me I don't understand why my code isn't sending my context correctly...
This is my code (credentials have been changed) that returns the error (422) Unprocessable Entity, which I can only assume means something is wrong with the XML that is being sent, but it appears to be correct when I set a break point.
string url = "https://core.spreedly.com/v1/gateways.xml";
WebRequest request = WebRequest.Create(url);
request.ContentType = "Content-type: application/xml";
request.Method = "POST";
request.Credentials = new NetworkCredential("Ll6fAtoVSTyVMlJEmtpoJV8Shw5", "RKOCG5D8D3fZxDSg504D0IxU2XD4Io5VXmyzdCtTivHFTTSylzM2ZzTWFwVH4ucG");
XElement xelement = new XElement("gateway", new XElement("gateway_type", "test"));
byte[] buffer = Encoding.UTF8.GetBytes(xelement.ToString());
request.ContentLength = buffer.Length;
Stream reqstr = request.GetRequestStream();
reqstr.Write(buffer, 0, buffer.Length);
reqstr.Close();
WebResponse response = request.GetResponse();
I don't use WebRequest often, so it's more than plausible that I'm missing something simple.
Spreedly keeps their documentation here.
The examples are in curl and say I should be sending the following:
$ curl https://core.spreedly.com/v1/gateways.xml \
-u 'Ll6fAtoVSTyVMlJEmtpoJV8Shw5:RKOCG5D8D3fZxDSg504D0IxU2XD4Io5VXmyzdCtTivHFTTSylzM2ZzTWFwVH4ucG' \
-H 'Content-Type: application/xml' \
-d '<gateway>
<gateway_type>test</gateway_type>
</gateway>'
Any help would be greatly appreciated.
Thank you.
Try changing the following line:
request.ContentType = "application/xml";
Spreedly return 422 in case of failure in the transaction.
Try use HttpClient instead WebRequest.
var client = new HttpClient();
client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Basic",
"ENVIRONMENT_KEY:ACCESS_SECRET");
var content = new StringContent(data, Encoding.UTF8, "application/json");
var response = client.PostAsync(url, content).Result;
string responseJson;
using (HttpContent resp = response.Content)
{
responseJson = resp.ReadAsStringAsync().Result;
}
return responseJson;