convert curl command into c# code using httpclient - c#

Command I need to convert :
curl.exe --digest -u login:pw -s -F "cert=#.\cert.pem" http://127.0.0.1/upload.htm
C# code I'm trying :
HttpClientHandler handler = new HttpClientHandler();
handler.Credentials = new NetworkCredential("login", "pw");
HttpClient client = new HttpClient(handler);
client.BaseAddress = new Uri("http://127.0.0.1");
...
var content = new StringContent(fileContents);
content.Headers.ContentDisposition = new ContentDispositionHeaderValue("form-data")
{
Name = "cert",
FileName = "cert.pem"
};
await client.PostAsync("/upload.htm", content);
Result :
<body><h1>HTTP/1.0 415 Unsupported Media Type</h1></body>
aldo tested the following c# code :
string executableLocation = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
String path = Path.Combine(executableLocation, "cert.pem");
var fs = File.Open(path, FileMode.Open);
var multiPartContent = new MultipartFormDataContent();
var fc = new StreamContent(fs);
fc.Headers.ContentType = new MediaTypeHeaderValue("application/octet-stream");
multiPartContent.Add(fc, "certUsageUnspecified", "cert.pem");
var uploadCertificate = await client.PostAsync("/upload.htm", multiPartContent);
logger.Info(await uploadCertificate.Content.ReadAsStringAsync());
logger.Info("=== end upload certificate ===");
and result is the following :
<body><h1>HTTP/1.0 400 Bad Request</h1></body>
I don't know what I'm doing wrong there but I can't find the solution. It's working fine with the curl command.

curl -Fis for multipart -F, --form <name=content> Specify HTTP multipart POST data
Try the following:
var content = new MultipartFormDataContent();
var fs = File.Open(".\cert.pem", FileMode.Open);
var fc = new StreamContent(fs);
fc.Headers.ContentType = new MediaTypeHeaderValue("application/octet-stream");
content.Add(fc, "cert", "cert.pem");
For information only
curl headers received with a file cert.pem whose content is "cert".
POST
Partial body: --------------------------87b709a918c0166a
Content-Disposition: form-data; name="cert"; filename="cert.pem"
Content-Type: application/octet-stream
"cert"
--------------------------87b709a918c0166a--
Body: --------------------------87b709a918c0166a
Content-Disposition: form-data; name="cert"; filename="cert.pem"
Content-Type: application/octet-stream
"cert"
--------------------------87b709a918c0166a--
The equivalent received with proposed .NET code:
POST
Partial body: --7ee9988d-bfd9-46d6-b0c9-74af30d7a6a2
Content-Disposition: form-data; name=cert; filename=cert.pem; filename*=utf-8''cert.pem
Content-Type: application/octet-stream
"cert"
--7ee9988d-bfd9-46d6-b0c9-74af30d7a6a2--
Body: --7ee9988d-bfd9-46d6-b0c9-74af30d7a6a2
Content-Disposition: form-data; name=cert; filename=cert.pem; filename*=utf-8''cert.pem
Content-Type: application/octet-stream
"cert"
--7ee9988d-bfd9-46d6-b0c9-74af30d7a6a2--
This is not strictly the same for Content-Disposition: header value but its very close.

Related

MultipartFormDataContent not adding Content-Type in HttpRequestBody

I have a simple HttpClient that does a multipart/form-data post to an endpoint.
using (var httpClient = new HttpClient())
{
using (var request = new HttpRequestMessage(new HttpMethod("POST"), url))
{
MultipartFormDataContent mfdc = new MultipartFormDataContent();
mfdc.Add(new StreamContent(content: new MemoryStream(Encoding.UTF8.GetBytes("This is from a file"))),
name: "file",
fileName: "File1.txt");
var response = await httpClient.PostAsync(url, mfdc);
}
}
This code produces this request:
Content-Type: multipart/form-data; boundary="0d411b9f-a36b-4326-97b6-85c781d348d2"
Content-Length: 196
Host: somehost.net
--0d411b9f-a36b-4326-97b6-85c781d348d2
Content-Disposition: form-data; name=file; filename=File1.txt; filename*=utf-8''File1.txt
This is from a file
--0d411b9f-a36b-4326-97b6-85c781d348d2--
The problem that I'm running into is that the API I'm calling is requiring the Content-Type in the request body as well.
The correct request should look like this:
Content-Type: multipart/form-data; boundary="0d411b9f-a36b-4326-97b6-85c781d348d2"
Content-Length: 196
Host: somehost.net
--0d411b9f-a36b-4326-97b6-85c781d348d2
Content-Disposition: form-data; name=file; filename=File1.txt; filename*=utf-8''File1.txt
Content-Type: text/plain
This is from a file
--0d411b9f-a36b-4326-97b6-85c781d348d2--
You have not added the content type of the content to be sent. So it will not be included in the request
using (var httpClient = new HttpClient()) {
MultipartFormDataContent form = new MultipartFormDataContent();
var stream = new MemoryStream(Encoding.UTF8.GetBytes("This is from a file"));
var fileContent = new StreamContent(content: stream);
//setting content type
fileContent.Headers.ContentType = new MediaTypeHeaderValue("text/plain");
form.Add(fileContent, name: "file", fileName: "File1.txt");
var response = await httpClient.PostAsync(url, form);
}

Unable to get json data from curl graph api using c#

I'm executing curl graph api using c#.
I took my curl query used this website and convert it into c#.
https://curl.olsh.me/
Api is able to give 200 ok status code and but output is below-
{
"extensions" : {
"requestId" : "123"
},
"data" : null,
"errors" : [ {
"message" : "Unable to process JSON",
"extensions" : {
"errorType" : "developer_error",
"errorClass" : "VALIDATION"
}
} ]
}
result string conv: StatusCode: 200, ReasonPhrase: 'OK', Version: 1.1, Content: System.Net.Http.StreamContent, Headers:
{
Connection: keep-alive
Braintree-Version: 2016-10-07
Strict-Transport-Security: max-age=31536000; includeSubDomains
Vary: Braintree-Version
X-Cache: Miss from cloudfront
X-Amz-Cf-Pop: MIA3-C2
X-Amz-Cf-Id: 111
Date: Tue, 10 Sep 2019 16:13:54 GMT
Via: 1.1 demo.cloudfront.net (CloudFront)
Content-Length: 286
Content-Type: application/json
}
C# code -
HttpClientHandler handler = new HttpClientHandler()
{
UseProxy = false,
};
using (var httpClient = new HttpClient(handler))
{
using (var request = new HttpRequestMessage(new HttpMethod("POST"), "https://demo/graphql"))
{
// Prod token
request.Headers.TryAddWithoutValidation("Authorization", "Basic abc");
request.Headers.TryAddWithoutValidation("Braintree-Version", "2019-01-01");
request.Content = new StringContent("{\"query\": \"{ report { transactionLevelFees(date: \"2019-08-28\"){ url } } }\" }", Encoding.UTF8, "application/json");
request.Content.Headers.ContentType = new MediaTypeHeaderValue("application/json");
var response = await httpClient.SendAsync(request);
// Get the response content.
HttpContent responseContent = response.Content;
response.Content.Headers.ContentType = new MediaTypeHeaderValue("application/json");
// Get the stream of the content.
using (var reader = new StreamReader(await responseContent.ReadAsStreamAsync()))
{
// Write the output.
Console.WriteLine((await reader.ReadToEndAsync()));
}
Console.WriteLine($"result string conv: {response }");
}
}
I expect in output i should get something in data json

Convert CURL to C# using HttpClient

I am trying to convert the following CURL command:
curl --request POST --url http://localhost:8042/tools/find --data "{\"Level\":\"Study\",\"Query\":{\"Modality\":\"MR\",\"StudyInstanceUID\":\"*\"}}"
to a C# rest client method, using HttpClient without success.
One approach i have been trying is the following:
using (var client = new HttpClient())
{
client.BaseAddress = new Uri("http://localhost:8042");
string test = "{\"Level\":\"Study\",\"Query\":{\"Modality\":\"MR\",\"StudyInstanceUID\":\"*\"}}";
var requestContent = new StringContent(test, Encoding.UTF8, "application/x-www-form-urlencoded");
var response = await client.PostAsync("tools/find", requestContent);
HttpContent responseContent = response.Content;
using (var reader = new StreamReader(await responseContent.ReadAsStreamAsync()))
{
// Write the output.
Console.WriteLine(await reader.ReadToEndAsync());
return await reader.ReadToEndAsync();
}
}
But either i am getting some timeout exceptions or the returned result in NULL.
This is what i am getting when i run the CURL command:
Note: Unnecessary use of -X or --request, POST is already inferred.
* Trying ::1...
* TCP_NODELAY set
* Trying 127.0.0.1...
* TCP_NODELAY set
* Connected to localhost (127.0.0.1) port 8042 (#0)
> POST /tools/find HTTP/1.1
> Host: localhost:8042
> User-Agent: curl/7.55.1
> Accept: */*
> Content-Length: 66
> Content-Type: application/x-www-form-urlencoded
>
* upload completely sent off: 66 out of 66 bytes
< HTTP/1.1 200 OK
< Connection: keep-alive
< Content-Type: application/json; charset=utf-8
< Content-Length: 1023
<
[
"06a5bb05-acf327ff-1b1f7432-543a3572-d0778630",
"0d2858ee-9bb9557f-6779c861-4e55604a-bbd9d561",
"241d9063-668f6d5a-84d5e791-aae25988-cbe330e4",
"2a47771d-a7fed498-2ea74733-6ba5b408-0af517d0",
"2c22461c-2529103d-1c3bbf0e-5c1011b7-ef4c4702",
"2e89270f-77b2368b-ec8f7a47-48922528-6d82a563",
"46151c0f-a92e4ffe-b3964a0b-0a217ff0-e138a9b0",
"4ac07d24-df6720d8-410ded38-80c42f81-029b826d",
"6ae5803f-564d02d6-ce2d03c9-87029ebb-c5f5b783",
"6c4dd689-5dc50cc7-7c0b07e1-231c8f06-10a50343",
"79a0e646-d244dced-2a2ac6d0-e61e6029-38b1e61e",
"7beb9698-c3e13f1a-5449e8c0-06f61be7-0285b222",
"8c35bbfa-1f00d0bb-50fdddea-c8b8f085-20ef243a",
"9a318c16-75a5cae8-3f42dd60-2ab5d0c0-664e78d1",
"a7b43909-4ecfe2fe-12f414ad-dc1d013e-0665e60b",
"b85380e8-e66db7da-d575e3d3-80bce548-71d5c251",
"d07b73c3-77cad4ff-1bf045d9-d8677f33-cd4c79f5",
"ec81b8b0-c6f95b97-2a2299ca-fa4d3f68-d79f0079",
"ec9c971a-e66c350c-f808f182-7716b99c-4c8f6f86",
"efe910b9-3bb0e298-c9ec181b-3985c6be-a6b74a89"
]
* Connection #0 to host localhost left intact
Any ideas about how can i convert this command to working c# code?
don't repeat the full URL in PostAsync if you are setting BaseAddress
using (var client = new HttpClient()){
client.BaseAddress = new Uri("http://localhost:8042");
...
var response = await client.PostAsync("tools/find", requestContent);
...
}
After some research and testing here is the code to make a corresponding to curl:
curl --request POST --url http://localhost:8042/tools/find --data "{\"Level\":\"Study\",\"Query\":{\"Modality\":\"MR\",\"StudyInstanceUID\":\"*\"}}"
post request in C#:
public async System.Threading.Tasks.Task<string> MyMethod(string studyInstanceUID)
{
using (var client = new HttpClient())
{
string data = "{\"Level\":\"Study\",\"Query\":{\"Modality\":\"MR\",\"StudyInstanceUID\":\"" + studyInstanceUID + "\"}}";
var requestContent = new StringContent(data, Encoding.UTF8, "application/x-www-form-urlencoded");
client.DefaultRequestHeaders.Add("User-Agent", "Anything");
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
if (reqAuth)
{
var byteArray = Encoding.ASCII.GetBytes(authString);
client.DefaultRequestHeaders.Authorization = new System.Net.Http.Headers.AuthenticationHeaderValue("Basic", Convert.ToBase64String(byteArray));
}
HttpResponseMessage response = await client.PostAsync(baseUrl + "tools/find", requestContent);
var responseContent = response.Content;
return responseContent.ReadAsStringAsync().Result;
}
}
If you don't mind using a small wrapper library, Flurl (disclaimer: I'm the author), which wraps HttpClient and Json.NET, makes this about as simple as using cURL.
using Flurl.Http;
var results = await "http://localhost:8042/tools/find"
.PostJsonAsync(new { Level = "Study", Query = new { Modality = "MR", StudyInstanceUID = "*" }})
.ReceiveJson<string[]>();
Note that JSON serializaiton is handled implicitly, so you're only ever dealing with strongly typed C# objects, rather than stringifying/parsing the JSON that goes in and comes out.

Equivalent of "curl -F" parameter for System.Net.Http.MultipartFormDataContent?

I am trying to use the sonicAPI file/upload API in C#.
My attempt to translate the curl example to C# with HttpClient and MultipartFormDataContent returns the error 400 / Bad Request.
Content of the response :
<?xml version="1.0" encoding="UTF-8"?>
<response>
<status code="400" />
<errors>
<error message="File upload failed: file is missing." parameter="file" error_code="10" />
</errors>
</response>
Example of the curl command-line shown in the documentation :
curl https://api.sonicapi.com/file/upload?access_id=$ACCESS_ID -Ffile=#Vocals.mp3
Code I've crafted so far :
public async Task<HttpResponseMessage> Post(string id, string fileName)
{
string url = string.Format("http://api.sonicapi.com/file/upload?access_id={0}", id);
var stream = new FileStream(fileName, FileMode.Open);
var client = new HttpClient { Timeout = TimeSpan.FromMinutes(10) };
var content = new MultipartFormDataContent();
content.Add(new StreamContent(stream), "file");
HttpResponseMessage message = await client.PostAsync(url, content);
string s = await message.Content.ReadAsStringAsync();
return message;
}
I've tried to remove "file" from content.Add(new StreamContent(stream), "file"); but it didn't help.
Note : the upload happens (i.e. it does not return immediately)
Do you know what is the equivalent of the curl -F parameter when using .NET web classes ?
EDIT :
Output of curl -v
* Hostname was NOT found in DNS cache
* Trying 87.106.252.119...
* Connected to api.sonicapi.com (87.106.252.119) port 80 (#0)
> POST /file/upload?access_id=xxxxxxxxxxxx HTTP/1.1
> User-Agent: curl/7.35.0
> Host: api.sonicapi.com
> Accept: */*
> Content-Length: 882266
> Expect: 100-continue
> Content-Type: multipart/form-data; boundary=------------------------b3c6dc0fc9
34fc71
>
< HTTP/1.1 100 Continue
< HTTP/1.1 201 Created
* Server nginx/0.7.67 is not blacklisted
< Server: nginx/0.7.67
< Date: Tue, 18 Feb 2014 21:14:09 GMT
< Content-Type: application/xml
< Connection: keep-alive
< X-Powered-By: Express
< X-Sonicapi-Request-Id: 6422cd9a-6069-4c2f-a3c5-0865c8ada6d5
< Access-Control-Allow-Origin: *
< location: /file/download?file_id=dae4e051-fe11-4058-a009-855dbb74de50
< X-Sonicapi-File-Id: dae4e051-fe11-4058-a009-855dbb74de50
< Content-Length: 249
<
<?xml version="1.0" encoding="utf-8"?><response><status code="201"/><file file_i
d="dae4e051-fe11-4058-a009-855dbb74de50" status="ready" href="/file/download?fil
e_id=dae4e051-fe11-4058-a009-855dbb74de50" remaining_lifetime_seconds="3599"/></
response>* Connection #0 to host api.sonicapi.com left intact
Output of the request using Fiddly :
POST http://api.sonicapi.com/file/upload?access_id=xxxxxxxx
HTTP/1.1
Content-Type: multipart/form-data; boundary="bd6fba7f-c173-4470-9c44-c9cc91f618a9"
Host: api.sonicapi.com
Content-Length: 882175
Expect: 100-continue
Connection: Keep-Alive
--bd6fba7f-c173-4470-9c44-c9cc91f618a9
Content-Disposition: form-data; name=file
RIFFvu
�WAVEfmt
(truncated)
Thanks to #bzlm, using Fiddler I managed to track what was missing :
Content disposition
Content type
And these needed to be set on streamContent rather than content.
public async Task<HttpResponseMessage> Post(string id, string fileName)
{
string url = string.Format("http://api.sonicapi.com/file/upload?access_id={0}", id);
var stream = new FileStream(fileName, FileMode.Open);
string name = Path.GetFileName(fileName);
var client = new HttpClient { Timeout = TimeSpan.FromMinutes(10) };
var streamContent = new StreamContent(stream);
streamContent.Headers.ContentDisposition = new ContentDispositionHeaderValue("form-data");
streamContent.Headers.ContentDisposition.Name = "\"file\"";
streamContent.Headers.ContentDisposition.FileName = "\"" + name + "\"";
streamContent.Headers.ContentType = new MediaTypeHeaderValue("application/octet-stream");
var content = new MultipartFormDataContent { streamContent };
HttpResponseMessage message = await client.PostAsync(url, content);
string s = await message.Content.ReadAsStringAsync();
return message;
}

PHP can't get raw data sent as multipart/form-data

This is client code (C#) :
string boundary = "--ABC";
try
{
WebRequest request = WebRequest.Create(url);
request.Method = "POST";
request.ContentType = "multipart/form-data;boundary="+boundary;
using (var requestStream = request.GetRequestStream())
using (var writer = new StreamWriter(requestStream))
{
writer.WriteLine(boundary);
writer.WriteLine("Content-Disposition: form-data; name=\"data\"");
writer.WriteLine();
writer.WriteLine("abcdefg");
writer.WriteLine(boundary + "--");
writer.Flush();
}
string responseData = string.Empty;
using (var response = request.GetResponse())
using (var responseStream = response.GetResponseStream())
using (var reader = new StreamReader(responseStream))
{
responseData=reader.ReadToEnd();
}
and this is the server code (php):
print file_get_contents("php://input");
or:
print $_POST["data"];
or:
print $http_raw_post_data;
or:
$fp=fopen("php://output","rb");
$contents=fread($fp,5);
fclose($fp);
print $contents;
Non of these code working, all print empty.
Could any one help please?
The following example illustrates "multipart/form-data" encoding. Suppose we have the following form:
<FORM action="http://server.com/cgi/handle"
enctype="multipart/form-data"
method="post">
<P>
What is your name? <INPUT type="text" name="submit-name"><BR>
What files are you sending? <INPUT type="file" name="files"><BR>
<INPUT type="submit" value="Send"> <INPUT type="reset">
</FORM>
If the user enters "Larry" in the text input, and selects the text file "file1.txt", the user agent might send back the following data:
Content-Type: multipart/form-data; boundary=AaB03x
--AaB03x
Content-Disposition: form-data; name="submit-name"
Larry
--AaB03x
Content-Disposition: form-data; name="files"; filename="file1.txt"
Content-Type: text/plain
... contents of file1.txt ...
--AaB03x--
If the user selected a second (image) file "file2.gif", the user agent might construct the parts as follows:
Content-Type: multipart/form-data; boundary=AaB03x
--AaB03x
Content-Disposition: form-data; name="submit-name"
Larry
--AaB03x
Content-Disposition: form-data; name="files"
Content-Type: multipart/mixed; boundary=BbC04y
--BbC04y
Content-Disposition: file; filename="file1.txt"
Content-Type: text/plain
... contents of file1.txt ...
--BbC04y
Content-Disposition: file; filename="file2.gif"
Content-Type: image/gif
Content-Transfer-Encoding: binary
...contents of file2.gif...
--BbC04y--
--AaB03x--
Multipart Form Post in C# Example
TRY THIS:
string boundary = "AaB03x";
try
{
WebRequest request = WebRequest.Create(url);
request.Method = "POST";
request.ContentType = "multipart/form-data;boundary="+boundary;
using (var requestStream = request.GetRequestStream())
using (var writer = new StreamWriter(requestStream))
{
writer.WriteLine("--"+boundary);
writer.WriteLine( "Content-Disposition: form-data; name=\"files\"; filename=\"file1.txt\"");
writer.WriteLine("Content-Type: text/plain
");
writer.WriteLine("example");
writer.WriteLine("--"boundary + "--");
writer.Flush();
}
string responseData = string.Empty;
using (var response = request.GetResponse())
using (var responseStream = response.GetResponseStream())
using (var reader = new StreamReader(responseStream))
{
responseData=reader.ReadToEnd();
}

Categories

Resources