What is the best way to create post request like this one in .net ?
I try to use HttpClient and MultipartFormDataContent classes but so far I can only be able to upload image. How can i add additional parameter like api key?
POST /services/upload/ HTTP/1.1
Content-Type: multipart/form-data; boundary=---------------------------7d44e178b0434
Host: api.flickr.com
Content-Length: 35261
-----------------------------7d44e178b0434
Content-Disposition: form-data; name="api_key"
3632623532453245
-----------------------------7d44e178b0434
Content-Disposition: form-data; name="auth_token"
436436545
-----------------------------7d44e178b0434
Content-Disposition: form-data; name="api_sig"
43732850932746573245
-----------------------------7d44e178b0434
Content-Disposition: form-data; name="photo"; filename="C:\test.jpg"
Content-Type: image/jpeg
{RAW JFIF DATA}
-----------------------------7d44e178b0434--
Something along the lines of.. in C# + .NET 4.0
Uri uri = new Uri("api.flickr.com");
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(uri);
request.Method = "POST";
//goes into the body. not header
NameValueCollection queryString = HttpUtility.ParseQueryString(string.Empty);
queryString["api_key"] = "7d44e178b0434";
...
object returnValue = null;
try
{
using (var writer = new StreamWriter(request.GetRequestStream()))
{
writer.WriteLine(queryString);
}
returnValue = request.GetResponse();
}
catch (Exception ex)
{
..
}
And if you wanted to add something to the header -
request.Headers.Add("HeaderKEY", somevalue);
Related
I'm trying to receive data from compressor, but it's answer is always empty. Here is my code:
WebClient client = new WebClient();
client.Headers[HttpRequestHeader.ContentType]= "application/x-www-form-urlencoded";
string question = "online_pressure";
string URL = "http://10.0.163.51/getVar.cgi";
string answer = client.UploadString(URL, "POST", question);
Console.WriteLine(answer);
When I use this code for another compressor, which different only 2 strings, it works great and I can see answer in console:
string question = "QUESTION=300201";
string URL = "http://10.0.163.50/cgi-bin/mkv.cgi";
Code in VBS works great for both compressors. I can see answer in MsgBox from first and second compressors:
Dim objHTTP
strToSend = "online_pressure"
Set objHTTP = CreateObject("Microsoft.XMLHTTP")
Call objHTTP.Open("POST", "http://10.0.163.51/getVar.cgi", false)
objHTTP.setRequestHeader "Content-Type", "application/x-www-form-urlencoded"
objHTTP.Send strToSend
MsgBox(objHTTP.ResponseText)
HttpRequest code works just for second compressor too:
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(URL);
request.Method = "POST";
request.ContentType = "application/x-www-form-urlencoded";
request.ContentLength = data.Length;
StreamWriter requestWriter = new StreamWriter(request.GetRequestStream(), System.Text.Encoding.ASCII);
requestWriter.Write(data);
requestWriter.Close();
try
{
// get the response
WebResponse webResponse = request.GetResponse();
Stream webStream = webResponse.GetResponseStream();
StreamReader responseReader = new StreamReader(webStream);
string response = responseReader.ReadToEnd();
responseReader.Close();
Console.WriteLine(response);
}
catch (WebException we)
{
string webExceptionMessage = we.Message;
}
What I can try else to get data from first compressor in C#?
I compared the three requests in Fiddler 4 and realized that the only difference (apart from some other headers which won't affect behavior) between vbs script and both WebClient
and HttpWebRequest is that, managed API's send the Expect: 100-continue header and vbs script does not.
This can be the issue if the software running on the compressor device does not support this.
Please try the following, which tells the HttpWebRequest to not send this header:
For the HttpWebRequest, you can simply prevent sending this by:
request.ServicePoint.Expect100Continue = false;
Note: For the WebClient, the assignment requires accessing to the HttpWebRequest object used internally, but this has "protected" access modifier and can be worked around.
Before setting this value:
POST http://oguzozgul.com.tr/getVar.cgi HTTP/1.1
Content-Type: application/x-www-form-urlencoded
Host: oguzozgul.com.tr
Content-Length: 15
Expect: 100-continue
Connection: Keep-Alive
online_pressure
After setting this value:
POST http://oguzozgul.com.tr/getVar.cgi HTTP/1.1
Content-Type: application/x-www-form-urlencoded
Host: oguzozgul.com.tr
Content-Length: 15
Connection: Keep-Alive
online_pressure
I also want to put the vb script request here so you can see other differences as well. The Accept-Encoding and some other headers are also not sent by default:
POST http://oguzozgul.com.tr/getVar.cgi HTTP/1.1
Accept: */*
Content-Type: application/x-www-form-urlencoded
Accept-Language: tr,en-US;q=0.8,en-GB;q=0.7,en;q=0.5,zh-Hans-CN;q=0.3,zh-Hans;q=0.2
UA-CPU: AMD64
Accept-Encoding: gzip, deflate
User-Agent: Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 6.3; Win64; x64; Trident/7.0; .NET4.0E; .NET4.0C; Tablet PC 2.0; .NET CLR 3.5.30729; .NET CLR 2.0.50727; .NET CLR 3.0.30729; wbx 1.0.0; Zoom 3.6.0; wbxapp 1.0.0)
Host: oguzozgul.com.tr
Content-Length: 15
Connection: Keep-Alive
Pragma: no-cache
online_pressure
WebClient and HttpWebRequest still do not works with this comressor. I tried to add any headers, but no result.
I tried PowerShell and it returns empty response too:
Invoke-WebRequest -Uri http://10.0.163.51/getVar.cgi -Method POST -Body "package_discharge_pressure" -ContentType "application/x-www-form-urlencoded"
Curl not working too, it hangs without errors
curl -i -X POST -H "Content-Type:application/x-www-form-urlencoded" -d "sump_pressure" http://10.0.163.51/getVar.cgi
Javascript and VBS works good. And today I found c# code wich works too
WinHttpRequest req = new WinHttpRequest();
try {
req.Open("POST", "http://10.0.163.51/getVar.cgi", true);
req.SetRequestHeader("Content-Type", "application/x-www-form-urlencoded");
req.Send("sump_pressure");
req.WaitForResponse();
}
catch(Exception ex) {
Console.WriteLine("Error : " + ex.Message.Trim());
}
Console.WriteLine(req.ResponseText);
In visual studio need to make reference to WinHttp
I'm working with an external api and want to upload file using multipart/form-data. The working solution in curl is: curl --form file=#./fileName.mp4 "http://page.com"
According to https://curl.olsh.me/. The code I'm looking for is:
using (var httpClient = new HttpClient())
{
using (var request = new HttpRequestMessage(new HttpMethod("POST"), "http://page.com/"))
{
var multipartContent = new MultipartFormDataContent();
multipartContent.Add(new ByteArrayContent(File.ReadAllBytes("./fileName.mp4")), "file", Path.GetFileName("./fileName.mp4"));
request.Content = multipartContent;
var response = await httpClient.SendAsync(request);
}
}
However it doesn't work. The headers and the file is different so I'm getting an error.
The code I've written and 'works', but the attachment is not valid, because encoding bytes to string is incorrect.
var webClient = new HttpClient();
webClient.DefaultRequestHeaders.ExpectContinue = true;
string boundary = "------------------------" + DateTime.Now.Ticks.ToString("x");
var fileData = Encoding.ASCII.GetString(System.IO.File.ReadAllBytes(pathToFile));
var package = string.Format("--{0}\r\nContent-Disposition: form-data; name=\"file\"; filename=\"{1}\"\r\nContent-Type: {2}\r\n\r\n{3}\r\n--{0}--\r\n", boundary, "fileName", "application/octet-stream", fileData);
var content = new StringContent(package);
content.Headers.Remove("Content-Type");
content.Headers.Add("Content-Type", "multipart/form-data; boundary=" + boundary);
content.Headers.Remove("Content-Length");
content.Headers.Add("Content-Length", package.Length.ToString());
await webClient.PostAsync(address, content);
Edit:
The headers from curl request:
POST http://page.com/ HTTP/1.1
Host: page.com
User-Agent: curl/7.55.1
Accept: */*
Connection: Keep-Alive
Content-Length: 1703578
Expect: 100-continue
Content-Type: multipart/form-data; boundary=------------------------1a538744c5619c1e
--------------------------1a538744c5619c1e
Content-Disposition: form-data; name="file"; filename="cst.mp4"
Content-Type: application/octet-stream
The headers from the 1st example code:
POST http://page.com/ HTTP/1.1
Content-Type: multipart/form-data; boundary="735b20d4-4de4-46fb-8293-2c2e996ce180"
Content-Length: 1703552
Host: page.com
--735b20d4-4de4-46fb-8293-2c2e996ce180
Content-Disposition: form-data; name=file; filename=cst.mp4; filename*=utf-8''cst.mp4
I think the file size difference is a red herring here.
A common practice for web servers is to deny requests that don't specify a user agent. Try adding a user agent (or even spoofing the curl agent) as below:
webClient.DefaultRequestHeaders.Add("User-Agent", "curl/7.55.1");
The problem with the first code is that the boundary, file headers and output headers differs. I had to add two Content-Type headers - one to my file and one to the output. I was unable to add the correct headers and remove the wrong one, beacuse I tried to add headers to multipart instead of multipart content.
If you want to add headers to your multipart content you need to do it on HttpContent.
The working solution is:
string boundary = "------------------------" + DateTime.Now.Ticks.ToString("x");
using (var httpClient = new HttpClient())
{
using (var request = new HttpRequestMessage(new HttpMethod("POST"), address))
{
httpClient.DefaultRequestHeaders.Add("User-Agent", userAgentName);
httpClient.DefaultRequestHeaders.Add("Connection", "Keep-Alive");
httpClient.DefaultRequestHeaders.ExpectContinue = true;
var multipartContent = new MultipartFormDataContent(boundary);
multipartContent.Headers.Remove("Content-Type");
multipartContent.Headers.Add("Content-Type", "multipart/form-data; boundary="+boundary);
var bcd = new ByteArrayContent(System.IO.File.ReadAllBytes(path));
bcd.Headers.Clear();
bcd.Headers.Add("Content-Disposition", "form-data; name=\"file\"; filename=\""+fileName+"\"");
bcd.Headers.Add("Content-Type", "application/octet-stream");
multipartContent.Add(bcd, "file", fileName);
request.Content = multipartContent;
var response = await httpClient.SendAsync(request);
}
}
Now the headers from curl and the HttpClient are almost the same(Accept header is missing, but I don't need it).
I'm trying to repead browser Post-request using C# but till now my C# code does not give expected result.
What the correct code should be?
Some info from Firebug about request.
Headers:
Host:"test-url:8080"
User-Agent:"Mozilla/5.0 (Windows NT 6.1; WOW64; rv:51.0) Gecko/20100101 Firefox/51.0"
Accept:"text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8"
Accept-Language:"ru-RU,ru;q=0.8,en-US;q=0.5,en;q=0.3"
Accept-Encoding:"gzip, deflate"
Referer:"http://test-url:8080/Emul/report.jsp?type=1"
Cookie:"JSESSIONID=31DF4BFA5ECA4014EE091774D0719AC0"
Connection:"keep-alive"
Upgrade-Insecure-Requests:"1"
Params:
Content-Type: multipart/form-data; boundary=---------------------------1987383936223
Content-Length: 5641
-----------------------------1987383936223
Content-Disposition: form-data; name="type"
1
-----------------------------1987383936223
Content-Disposition: form-data; name="file"; filename="409474.xml"
Content-Type: text/xml
<?xml version="1.0" encoding="utf-8"?>
<prequest>
...
</prequest>
-----------------------------1987383936223
Content-Disposition: form-data; name="upload"
Upload
-----------------------------1987383936223--
My C#-code
HttpWebRequest request = (HttpWebRequest)WebRequest.Create("http:/test-url:8080/Emul/report.jsp");
// here prequest-xml is contained
var bytes = File.ReadAllBytes(#"C:\NBCH\1.xml");
request.ContentLength = bytes.Length;
request.KeepAlive = true;
request.Method = "POST";
request.ContentType = "text/xml; encoding='utf-8'";
Stream requestStream = request.GetRequestStream();
requestStream.Write(bytes, 0, bytes.Length);
requestStream.Close();
HttpWebResponse response;
response = (HttpWebResponse)request.GetResponse();
Use fiddler to check the difference between browser and c# request.
I am trying to upload a file via a POST to a REST API in a c# winform.
If I run the following command with curl the file is uploaded successfully:
curl.exe -H "Content-type: application/octet-stream" -X POST http://myapiurl --data-binary #C:\test.docx
I have tried using WebClient in my WinForm:
using (var client = new WebClient())
{
client.Headers.Add("Content-Type", "application/octet-stream");
byte[] result = client.UploadFile(url, file);
string responseAsString = Encoding.Default.GetString(result);
tb_result.Text += responseAsString;
}
But I just get a (500) Internal Server.
Checking this with fiddler the following headers are added with CURL:
POST http://myapiurl HTTP/1.1
User-Agent: curl/7.33.0
Host: 10.52.130.121:90
Accept: */*
Connection: Keep-Alive
Content-type: application/octet-stream
Content-Length: 13343
Expect: 100-continue
But checking my WebClient method shows the following:
POST http://myapiurl HTTP/1.1
Accept: */*
Content-Type: multipart/form-data; boundary=---------------------8d220bbd95f8b18
Host: 10.52.130.121:90
Content-Length: 13536
Expect: 100-continue
Connection: Keep-Alive
How can I simulate the CURL command above from my app?
How can I simulate the CURL command above from my app?
Use HttpWebRequest. It offers you more flexibility. As follows:
HttpWebRequest request = (HttpWebRequest)WebRequest.Create("http://myapiurl");
request.Method = "POST";
request.UserAgent = "curl/7.33.0";
request.Host = "10.52.130.121:90";
request.Accept = "Accept=*/*";
request.Connection = "Keep-Alive";
request.ContentType = "application/octet-stream";
request.ContentLength = 13343;
request.Expect = "100-continue";
I am trying to send Facebook graph link to the AppEngine server. I receive "Malformed string exception". Here is my method sending json to server:
public async Task<string> SendJSONData(string urlToCall, string JSONData)
{
// server to POST to
string url = urlToCall;
// HTTP web request
var httpWebRequest = (HttpWebRequest)WebRequest.Create(url);
httpWebRequest.ContentType = "application/x-www-form-urlencoded";
httpWebRequest.Method = "POST";
// Write the request Asynchronously
using (var stream = await Task.Factory.FromAsync<Stream>(httpWebRequest.BeginGetRequestStream,
httpWebRequest.EndGetRequestStream, null))
{
//create some json string
string json = "action=" + JSONData;
// convert json to byte array
byte[] jsonAsBytes = Encoding.UTF8.GetBytes(json);
// Write the bytes to the stream
await stream.WriteAsync(jsonAsBytes, 0, jsonAsBytes.Length);
}
WebResponse response = await httpWebRequest.GetResponseAsync();
StreamReader requestReader = new StreamReader(response.GetResponseStream());
String webResponse = requestReader.ReadToEnd();
return webResponse; }
Here is what I sniff using Fiddler:
POST http://x.appspot.com/register HTTP/1.1
Accept: */*
Content-Length: 376
Accept-Encoding: identity
Content-Type: application/x-www-form-urlencoded
User-Agent: NativeHost
Host: x.appspot.com
Connection: Keep-Alive
Pragma: no-cache
action={
"mailFb": "mail#gmail.com",
"userName": "Michael",
"userSurname": "w00t",
"nickname": "Michael w00t",
"userSex": "male",
"userAvatar": "https://graph.facebook.com/myperfectid/picture?type=large&access_token=BlahblahblahblahToken"
}
So everything looks fine, but the problem is that i receive the following error in AppEngine log:
2013-03-02 17:52:10.431 /register 500 56ms 0kb NativeHost
W 2013-03-02 17:52:10.427 /register com.google.gson.JsonSyntaxException: com.google.gson.stream.MalformedJsonException: Unterminated string at line 7 column 79 at com.google.g
C 2013-03-02 17:52:10.429 Uncaught exception from servlet com.google.gson.JsonSyntaxException: com.google.gson.stream.MalformedJsonException: Unterminated string at line 7 colu
I managed to narrow the problem to its source, which is "&" character. So my question is, how to fix the code, so that it works with AppEngine.
Oh, here is how i read the received data on the server:
gson.fromJson(reader, User.class);
The problem is highlighted by the fact you're claiming you are sending "Content-Type: application/x-www-form-urlencoded"
But it isn't. Hence the error.
The correct encoding for & is &.