Making a cURL call in C# - c#

I want to make the following curl call in my C# console application:
curl -d "text=This is a block of text" \
http://api.repustate.com/v2/demokey/score.json
I tried to do like the question posted here, but I cannot fill the properties properly.
I also tried to convert it to a regular HTTP request:
http://api.repustate.com/v2/demokey/score.json?text="This%20is%20a%20block%20of%20text"
Can I convert a cURL call to an HTTP request? If so, how? If not, how can I make the above cURL call from my C# console application properly?

Well, you wouldn't call cURL directly, rather, you'd use one of the following options:
HttpWebRequest/HttpWebResponse
WebClient
HttpClient (available from .NET 4.5 on)
I'd highly recommend using the HttpClient class, as it's engineered to be much better (from a usability standpoint) than the former two.
In your case, you would do this:
using System.Net.Http;
var client = new HttpClient();
// Create the HttpContent for the form to be posted.
var requestContent = new FormUrlEncodedContent(new [] {
new KeyValuePair<string, string>("text", "This is a block of text"),
});
// Get the response.
HttpResponseMessage response = await client.PostAsync(
"http://api.repustate.com/v2/demokey/score.json",
requestContent);
// Get the response content.
HttpContent responseContent = response.Content;
// Get the stream of the content.
using (var reader = new StreamReader(await responseContent.ReadAsStreamAsync()))
{
// Write the output.
Console.WriteLine(await reader.ReadToEndAsync());
}
Also note that the HttpClient class has much better support for handling different response types, and better support for asynchronous operations (and the cancellation of them) over the previously mentioned options.

Or in restSharp:
var client = new RestClient("https://example.com/?urlparam=true");
var request = new RestRequest(Method.POST);
request.AddHeader("content-type", "application/x-www-form-urlencoded");
request.AddHeader("cache-control", "no-cache");
request.AddHeader("header1", "headerval");
request.AddParameter("application/x-www-form-urlencoded", "bodykey=bodyval", ParameterType.RequestBody);
IRestResponse response = client.Execute(request);

Below is a working example code.
Please note you need to add a reference to Newtonsoft.Json.Linq
string url = "https://yourAPIurl";
WebRequest myReq = WebRequest.Create(url);
string credentials = "xxxxxxxxxxxxxxxxxxxxxxxx:yyyyyyyyyyyyyyyyyyyyyyyyyyyyyy";
CredentialCache mycache = new CredentialCache();
myReq.Headers["Authorization"] = "Basic " + Convert.ToBase64String(Encoding.ASCII.GetBytes(credentials));
WebResponse wr = myReq.GetResponse();
Stream receiveStream = wr.GetResponseStream();
StreamReader reader = new StreamReader(receiveStream, Encoding.UTF8);
string content = reader.ReadToEnd();
Console.WriteLine(content);
var json = "[" + content + "]"; // change this to array
var objects = JArray.Parse(json); // parse as array
foreach (JObject o in objects.Children<JObject>())
{
foreach (JProperty p in o.Properties())
{
string name = p.Name;
string value = p.Value.ToString();
Console.Write(name + ": " + value);
}
}
Console.ReadLine();
Reference: TheDeveloperBlog.com

Late response but this is what I ended up doing. If you want to run your curl commands very similarly as you run them on linux and you have windows 10 or latter do this:
public static string ExecuteCurl(string curlCommand, int timeoutInSeconds=60)
{
if (string.IsNullOrEmpty(curlCommand))
return "";
curlCommand = curlCommand.Trim();
// remove the curl keworkd
if (curlCommand.StartsWith("curl"))
{
curlCommand = curlCommand.Substring("curl".Length).Trim();
}
// this code only works on windows 10 or higher
{
curlCommand = curlCommand.Replace("--compressed", "");
// windows 10 should contain this file
var fullPath = System.IO.Path.Combine(Environment.SystemDirectory, "curl.exe");
if (System.IO.File.Exists(fullPath) == false)
{
if (Debugger.IsAttached) { Debugger.Break(); }
throw new Exception("Windows 10 or higher is required to run this application");
}
// on windows ' are not supported. For example: curl 'http://ublux.com' does not work and it needs to be replaced to curl "http://ublux.com"
List<string> parameters = new List<string>();
// separate parameters to escape quotes
try
{
Queue<char> q = new Queue<char>();
foreach (var c in curlCommand.ToCharArray())
{
q.Enqueue(c);
}
StringBuilder currentParameter = new StringBuilder();
void insertParameter()
{
var temp = currentParameter.ToString().Trim();
if (string.IsNullOrEmpty(temp) == false)
{
parameters.Add(temp);
}
currentParameter.Clear();
}
while (true)
{
if (q.Count == 0)
{
insertParameter();
break;
}
char x = q.Dequeue();
if (x == '\'')
{
insertParameter();
// add until we find last '
while (true)
{
x = q.Dequeue();
// if next 2 characetrs are \'
if (x == '\\' && q.Count > 0 && q.Peek() == '\'')
{
currentParameter.Append('\'');
q.Dequeue();
continue;
}
if (x == '\'')
{
insertParameter();
break;
}
currentParameter.Append(x);
}
}
else if (x == '"')
{
insertParameter();
// add until we find last "
while (true)
{
x = q.Dequeue();
// if next 2 characetrs are \"
if (x == '\\' && q.Count > 0 && q.Peek() == '"')
{
currentParameter.Append('"');
q.Dequeue();
continue;
}
if (x == '"')
{
insertParameter();
break;
}
currentParameter.Append(x);
}
}
else
{
currentParameter.Append(x);
}
}
}
catch
{
if (Debugger.IsAttached) { Debugger.Break(); }
throw new Exception("Invalid curl command");
}
StringBuilder finalCommand = new StringBuilder();
foreach (var p in parameters)
{
if (p.StartsWith("-"))
{
finalCommand.Append(p);
finalCommand.Append(" ");
continue;
}
var temp = p;
if (temp.Contains("\""))
{
temp = temp.Replace("\"", "\\\"");
}
if (temp.Contains("'"))
{
temp = temp.Replace("'", "\\'");
}
finalCommand.Append($"\"{temp}\"");
finalCommand.Append(" ");
}
using (var proc = new Process
{
StartInfo = new ProcessStartInfo
{
FileName = "curl.exe",
Arguments = finalCommand.ToString(),
UseShellExecute = false,
RedirectStandardOutput = true,
RedirectStandardError = true,
CreateNoWindow = true,
WorkingDirectory = Environment.SystemDirectory
}
})
{
proc.Start();
proc.WaitForExit(timeoutInSeconds*1000);
return proc.StandardOutput.ReadToEnd();
}
}
}
The reason why the code is a little bit long is because windows will give you an error if you execute a single quote. In other words, the command curl 'https://google.com' will work on linux and it will not work on windows. Thanks to that method I created you can use single quotes and run your curl commands exactly as you run them on linux. This code also checks for escaping characters such as \' and \".
For example use this code as
var output = ExecuteCurl(#"curl 'https://google.com' -H 'Accept: application/json, text/javascript, */*; q=0.01'");
If you where to run that same string agains C:\Windows\System32\curl.exe it will not work because for some reason windows does not like single quotes.

I know this is a very old question but I post this solution in case it helps somebody. I recently met this problem and google led me here. The answer here helps me to understand the problem but there are still issues due to my parameter combination. What eventually solves my problem is curl to C# converter. It is a very powerful tool and supports most of the parameters for Curl. The code it generates is almost immediately runnable.

Don't forget to add System.Net.Http, specially if you receive this error:
Severity Code Description Project File Line Suppression State
Error CS0246 The type or namespace name 'HttpClient' could not be
found (are you missing a using directive or an assembly
reference?) 1_default.aspx D:\Projetos\Testes\FacebookAPI\FB-CustomAudience\default.aspx.cs 56 Active
In this case you shoud:
Add System.Net.Http from Nuget: Tools / NuGet Package Manager / Manager NuGet Packages for Solution;
Search for System.Net.Http
Add in the top of your page the follow code:
using System.Net.Http;

Call cURL from your console app is not a good idea.
But you can use TinyRestClient which make easier to build requests :
var client = new TinyRestClient(new HttpClient(),"https://api.repustate.com/");
client.PostRequest("v2/demokey/score.json").
AddQueryParameter("text", "").
ExecuteAsync<MyResponse>();

Well if you are new to C# with cmd-line exp. you can use online sites like "https://curl.olsh.me/" or search curl to C# converter will returns site that could do that for you.
or if you are using postman you can use Generate Code Snippet only problem with Postman code generator is the dependency on RestSharp library.

Related

Need help to find where does API takes data from in ASP.NET MVC

I am a begginer and i work in a MVC project which I cant understand it well yet.
I can't understand where does the API takes data from when I try to connect in Login Screen.
It doesn't use Entity Framework and there isn't a json with the data.
When I enter Id and Pass it calls an API (GetAPIResponse) which somehow finds that is correct.
Need help to understand the code and the logic behind it.
LoginBL class contains:
public bool IsAuthenticated(LoginEntity user)
{
string url = string.Empty;
string callType = string.Empty;
string server = string.Empty;
try
{
// get URL, Call type, Server from config file
url = ConfigurationManager.AppSettings["login_url"].ToString();
callType = ConfigurationManager.AppSettings["calltype"].ToString();
server = ConfigurationManager.AppSettings["server"].ToString();
// Encrypt password
string password = Scrambler.GenerateMD5Hash(user.Password);
// Prepare content for the POST request
string content = #"calltype=" + callType + "&server=" + server + "&user=" + user.UserName + "&pass=" + password + "";
Debug.WriteLine("Callcenter login url: " + content);
HttpResponseMessage json_list = ApiCallBL.GetAPIResponse(url, content);
LoginResponseEntity obj = new LoginResponseEntity();
obj = JsonConvert.DeserializeObject<LoginResponseEntity>(json_list.Content.ReadAsStringAsync().Result);
Debug.WriteLine(callType + " Response: " + json_list.Content.ReadAsStringAsync().Result);
//if API resultCode return 0 then user details and token save in session for further use
if (obj.ResultCode == 0)
{
int restrict = obj.UserInfo.RestrictCallType.HasValue ?
obj.UserInfo.RestrictCallType.Value : 0;
HttpContext.Current.Session["user_id"] = obj.UserInfo.usr_id;
HttpContext.Current.Session["user_name"] = obj.UserInfo.usr_username;
HttpContext.Current.Session["user_group_id"] = obj.UserInfo.UserGroupID;
HttpContext.Current.Session["groupid"] = obj.UserInfo.groupid;
HttpContext.Current.Session["token"] = obj.Token;
HttpContext.Current.Session["web_server_url"] = obj.ServerInfo.web_server_url;
HttpContext.Current.Session["centerX"] = obj.ServerInfo.DefaultGeoX;
HttpContext.Current.Session["centerY"] = obj.ServerInfo.DefaultGeoY;
HttpContext.Current.Session["dateFormat"] = obj.ServerInfo.dateFormat;
HttpContext.Current.Session["currency"] = obj.ServerInfo.currency;
HttpContext.Current.Session["customer_img"] = obj.ServerInfo.customer_img;
HttpContext.Current.Session["groups"] = obj.groups;
HttpContext.Current.Session["restrict_call_type"] = restrict ;
Debug.WriteLine("obj.UserInfo.UserGroupID " + obj.UserInfo.UserGroupID);
Debug.WriteLine("obj.UserInfo.groups " + obj.groups);
//HttpContext.Current.Session["defaultLanguage"] = obj.ServerInfo.defaultLanguage;
HttpCookie cookie = new HttpCookie("Login");
// if remember me checked then user name and password stored in cookie else cookes is expired
if (user.RememberMe)
{
cookie.Values.Add("user_name", obj.UserInfo.usr_username);
cookie.Values.Add("pwd", user.Password);
cookie.Expires = DateTime.Now.AddDays(15);
HttpContext.Current.Response.Cookies.Add(cookie);
}
else
{
cookie.Expires = DateTime.Now.AddDays(-1);
HttpContext.Current.Response.Cookies.Add(cookie);
}
return true;
}
else
{
//ResultCode -5 :Invalid Login ,-1:Database Error ,-2:Server Error ,-3:Invalid Parameter specified ,-4:Invalid Token
return false;
}
}
catch
{
throw;
}
finally
{
url = string.Empty;
callType = string.Empty;
server = string.Empty;
}
}
Okay here after converts pass to MD5 creates a "string content" with the information given.
Then in next line (HttpResponseMessage json_list = ApiCallBL.GetAPIResponse(url, content);) calls the API with the url and content as parameters where it finds if the data exists.
API code:
public static HttpResponseMessage GetAPIResponse(string url, string content)
{
StringBuilder traceLog = null;
HttpContent httpContent = null;
try
{
traceLog = new StringBuilder();
traceLog.AppendLine("Start: BusinessLayer getAPIResponse() Request Data:- " + DateTime.Now + "URL = " + url + "&content = " + httpContent);
using (HttpClient client = new HttpClient())
{
httpContent = new StringContent(content);
httpContent.Headers.ContentType = new MediaTypeHeaderValue("application/x-www-form-urlencoded");
var resp = client.PostAsync(url, httpContent).Result;
Debug.WriteLine("resp: " + resp.Content.ReadAsStringAsync().Result);
traceLog.AppendLine("End: BusinessLayer getAPIResponse() call completed HttpResponseMessage received");
return resp;
}
}
catch
{
throw;
}
finally
{
traceLog = null;
httpContent.Dispose();
url = string.Empty;
content = string.Empty;
}
}
In the following line, console prints the result that I cant understand where it cames from (Debug.WriteLine("resp: " + resp.Content.ReadAsStringAsync().Result);)
Sorry for the confusion , I am in my first job with zero work experience and I am called to learn how this works alone without proper education on ASP.NET from them.
You will not go very far without debbugger. Learn how to debug in Visual Studio (YouTube tutorials might be fastest way). Place debug points along critical points in code (for example moment when client sends and receives response is line var resp = client.PostAsync...) and check variables.
Url for API server is actually defined in the line
url = ConfigurationManager.AppSettings["login_url"].ToString();
ConfigurationManager means Web.config file, check it's appSettings section for login_url entry, there is your url.
Btw, using (HttpClient client = new HttpClient()) is not a good way to use a HttpClient and will lead to port exhaustion. It's ok for small number of requests, but for larger ones you must reuse it, or use HttpClientFactory (for .NET Core).

Using parallelism to speed up the code

I've made a tool that sends HTTP requests (GET) (reads the info of what to send from a .txt), captures the json and parses it + writes it to a .txt. The tool is a console app targetting .NET Framework 4.5.
Could I possibly speed this up with the help of "multi-threading"?
System.IO.StreamReader file =
new System.IO.StreamReader(#"file.txt");
while ((line = file.ReadLine()) != null)
{
using (var client = new HttpClient(new HttpClientHandler { AutomaticDecompression = DecompressionMethods.GZip | DecompressionMethods.Deflate }))
{
client.BaseAddress = new Uri("https://www.website.com/");
HttpResponseMessage response = client.GetAsync("index?userGetLevel=" + line).Result;
response.EnsureSuccessStatusCode();
string result = response.Content.ReadAsStringAsync().Result;
dynamic json = JObject.Parse(result);
string level = json.data.level;
if (level == "null")
{
Console.WriteLine("{0}: User does not exist.", line);
}
else
{
Console.WriteLine("{0}: User level is {1}.", line, level);
using (StreamWriter sw = File.AppendText(levels.txt))
{
sw.WriteLine("{0} : {1}", line, level);
}
}
}
}
file.Close();
Answers to questions:
"Speed up what?": I'd like to speed up the whole process (the amount of requests it sends each time, not how fast it sends them.
"How many requests?": The tool reads a string from a text file and puts that information in to a part of the URL, and then captures the response, then places that in a result.txt. I'd like to increase the speed it does this at/how many it does at a time.
"Can the requests happen concurrently or are dependant on prior request responses?": Yes, and no, they are not dependent.
" Does your web server impose a limit on the number of concurrent requests?": No.
"How long does a typical request take?": The request + the time the response shows up on console per each requests is a little bit more than 1/3 of a second.
There are several ways to asymmetric programming, one of them could be something like this:
var messages = new ConcurrentQueue<string>();
//or
//var lockObj = new object();
public int main()
{
var fileText = File.ReadAllLines(#"file.txt");
var taskList = new List<Task>();
foreach (var line in fileText)
{
taskList.Add(Task.Factory.StartNew(HandlerMethod, line));
//you can control the amount of produced task if you want:
//if(taskList.Count > 20)
//{
// Task.WaitAll(taskList.ToArray());
// taskList.Clear();
//}
}
Task.WaitAll(taskList.ToArray()); //this line may not work as I expected.
//for the first way
var results = new StringBuilder();
foreach (var msg in messages)
{
results.AppendLine("{0} : {1}", line, level);
}
File.WriteAllText("path", results.ToString());
}
For writing the results, either you can use a public concurrent collection or use a lock pattern:
public void HandlerMethod(object obj)
{
var line = (string)obj;
var result = string.Empty;
using (var client = new HttpClient(new HttpClientHandler { AutomaticDecompression = DecompressionMethods.GZip | DecompressionMethods.Deflate }))
{
client.BaseAddress = new Uri("https://www.website.com/");
HttpResponseMessage response = client.GetAsync("index?userGetLevel=" + line).Result;
response.EnsureSuccessStatusCode();
string result = response.Content.ReadAsStringAsync().Result;
dynamic json = JObject.Parse(result);
result = json.data.level;
}
//for the first way
if (string.IsNullOrWhiteSpace(result))
{
messages.Enqueue("{0}: User does not exist.", line);
}
else
{
messages.Enqueue("{0}: User level is {1}.", line, result);
}
//for the second way
//lock(lockObj)
//{
// using (StreamWriter sw = File.AppendText(levels.txt))
// {
// sw.WriteLine("{0} : {1}", line, level);
// }
//}
}

Download File to Byte[] with Selenium C#

I need to download a file to byte[] using Selenium in C#.
The problem is the file is downloaded via a button which does a javascript call:
javascript:__doPostBack('ctl00$MainContent$gvOutputs','Select$0')
If i could get a URL I could just use the C# command:
using (WebClient wc = new WebClient())
{
wc.Headers[HttpRequestHeader.Cookie] = this.GetCookieHeaderString(); //Get Cookie from Selenium window
return wc.DownloadData(sourceURL);
}
Unfortunately this wont work as I dont have the URL.
the __dopostback makes a POST request which looks like this:
__EVENTTARGET=ctl00%24MainContent%24gvOutputs
__EVENTARGUMENT=Select%240
__VIEWSTATE=sEM2tcQczKVsK5kzEN2x19Gxco%....
__VIEWSTATEGENERATOR=B935C9B7
__VIEWSTATEENCRYPTED=
__EVENTVALIDATION=kOyxw5ZKBd1yygTXmUR%....
I suppose if there were a way to get those variables I could create a POST in C#.. However I'm not sure how I can get those variables?
I can click the link in selenium, but that will force a download to the clients computer..
I suppose 1 option would be to monitor the download directory, and read it this way, but im trying to avoid this brute force method.
I was hoping for a better answer. However I ended up making a specific DOWNLOAD path for every Selenium instance, then monitoring that directory and associating the files with the selenium instance.. A little bit hacky but it works.
I am a bit late, but I just found a solution for my case.
You can use this chunk of JS code to do the post request:
var xhr = new XMLHttpRequest();
xhr.open('POST', '<THE-POST-REQUEST-URL>', true);
xhr.responseType = 'arraybuffer';
xhr.onload = function () {
if (this.status === 200) {
var fileArray = this.response;
var filename = '';
var disposition = xhr.getResponseHeader('Content-Disposition');
if (disposition && disposition.indexOf('attachment') !== -1) {
var filenameRegex = /filename[^;=\n]*=((['"]).*?\2|[^;\n]*)/;
var matches = filenameRegex.exec(disposition);
if (matches != null && matches[1]) filename = matches[1].replace(/['"]/g, '');
}
var byteArray = new Uint8Array(fileArray);
var obj = {
'fileName': filename,
'fileData': byteArray
}
callback(obj);
}
else {
callback('server error - file might not be found');
}
};
xhr.setRequestHeader('Content-type', 'application/x-www-form-urlencoded');
xhr.send('<POST-REQUEST-ARGUMENTS>');
and then call it in selenium:
var response = driver.ExecuteAsyncScript(
#$ "var callback = arguments[arguments.length - 1];
// The rest of the code from the last example
"
);
if (response is Dictionary < string, object > fileDict)
{
var fileName = fileDict["fileName"]?.ToString();
var fileData = fileDict["fileData"];
if (fileData is ReadOnlyCollection < object > readonlyCollection)
{
var byteArray = readonlyCollection.Select(i => (byte)(int)(long) i).ToArray();
var tempFile = "PATH/TO/FILE";
File.WriteAllBytes(tempFile, byteArray);
}
else
{
throw new Exception("fileData is not a byte array");
}
}

how to get the response body in code webtest?

I wrote a webtest that calls a web-service.
I want to get the response body and do some validation on it.
public override IEnumerator<WebTestRequest> GetRequestEnumerator()
{
WebTestRequest request2 = new WebTestRequest("webservice");
request2.Headers.Add("Content-Type", "application/json");
request2.Method = "POST";
request2.Encoding = System.Text.Encoding.GetEncoding("utf-8");
StringHttpBody request2Body = new StringHttpBody();
request2Body.ContentType = "application/json";
request2Body.InsertByteOrderMark = false;
request2Body.BodyString = #"{ <body>}";
request2.Body = request2Body;
WebTestResponse res = new WebTestResponse();
console.WriteLine(res.BodyBytes);
yield return request2;
request2 = null;
}
When i ran the above code i didn't get any response on my console.
How can i get the response body using coded webtest?
There are at least three problems with the code in the question
The code in the question does not perform the request before doing the WriteLine. The two statements WebTestResponse res = new WebTestResponse(); and console.WriteLine(res.BodyBytes); just create a new WebTestResponse object (with all default values) and then try to print part of its contents. The request is issued by the code that calls your GetRequestEnumerator method.
The console object is not defined. The normal console has a first letter uppercase, ie Console.
When a web test executes I am not sure where its "console" output will go. The standard output of a web test is not, as far as I know, a well defined thing.
An easy way to get at the response body is to use the PostRequest method of a WebTestRequestPlugin. For a start
public class BodyContentsDemo : WebTestRequestPlugin
{
public override void PostRequest(object sender, PostRequestEventArgs e)
{
byte[] bb = e.Response.BodyBytes;
string ss = e.Response.BodyString;
e.WebTest.AddCommentToResult(
"BodyBytes is " +
bb == null ? " null"
: bb.Length.ToString() + " bytes");
e.WebTest.AddCommentToResult(
"BodyString is " +
ss == null ? "null"
: ss.Length.ToString() + " chars");
// Use bb or ss.
}
}
Note the use of AddCommentToResult to provide logging information to the web test results log.
Finally I am able to find a solution for last couple of days I was struggling to capture the response text from Web Performance test. Hope this helps
public override IEnumerator GetRequestEnumerator()
{
WebTestRequest request2 = new WebTestRequest("webservice");
request2.Headers.Add("Content-Type", "application/json");
request2.Method = "POST";
request2.Encoding = System.Text.Encoding.GetEncoding("utf-8");
StringHttpBody request2Body = new StringHttpBody();
request2Body.ContentType = "application/json";
request2Body.InsertByteOrderMark = false;
request2Body.BodyString = #"{<body>}";
request2.Body = request2Body;
WebTestResponse res = new WebTestResponse();
console.WriteLine(res.BodyBytes);
yield return request2;
/*This will generate a new string which can be part of your filename when you run performance tests*/
String randomNo = DateTime.Now.ToString("MM/dd/yyyy HH:mm:ss").Replace("-", "").Replace(" ", "").Replace(":", "");
/*This will generate a new file each time your WebRequest runs so you know what the server is returning when you perform webtests*/
/*You can use some Json parser if your response is Json and capture and validate the response*/
System.IO.File.WriteAllText(#"C:\Users\XXXX\PerformanceTestRequests\LastResponse" + randomNo+ ".txt", this.LastResponse.BodyString);
request2 = null;
}

Convert curl sample to c#.net [duplicate]

I want to make the following curl call in my C# console application:
curl -d "text=This is a block of text" \
http://api.repustate.com/v2/demokey/score.json
I tried to do like the question posted here, but I cannot fill the properties properly.
I also tried to convert it to a regular HTTP request:
http://api.repustate.com/v2/demokey/score.json?text="This%20is%20a%20block%20of%20text"
Can I convert a cURL call to an HTTP request? If so, how? If not, how can I make the above cURL call from my C# console application properly?
Well, you wouldn't call cURL directly, rather, you'd use one of the following options:
HttpWebRequest/HttpWebResponse
WebClient
HttpClient (available from .NET 4.5 on)
I'd highly recommend using the HttpClient class, as it's engineered to be much better (from a usability standpoint) than the former two.
In your case, you would do this:
using System.Net.Http;
var client = new HttpClient();
// Create the HttpContent for the form to be posted.
var requestContent = new FormUrlEncodedContent(new [] {
new KeyValuePair<string, string>("text", "This is a block of text"),
});
// Get the response.
HttpResponseMessage response = await client.PostAsync(
"http://api.repustate.com/v2/demokey/score.json",
requestContent);
// Get the response content.
HttpContent responseContent = response.Content;
// Get the stream of the content.
using (var reader = new StreamReader(await responseContent.ReadAsStreamAsync()))
{
// Write the output.
Console.WriteLine(await reader.ReadToEndAsync());
}
Also note that the HttpClient class has much better support for handling different response types, and better support for asynchronous operations (and the cancellation of them) over the previously mentioned options.
Or in restSharp:
var client = new RestClient("https://example.com/?urlparam=true");
var request = new RestRequest(Method.POST);
request.AddHeader("content-type", "application/x-www-form-urlencoded");
request.AddHeader("cache-control", "no-cache");
request.AddHeader("header1", "headerval");
request.AddParameter("application/x-www-form-urlencoded", "bodykey=bodyval", ParameterType.RequestBody);
IRestResponse response = client.Execute(request);
Below is a working example code.
Please note you need to add a reference to Newtonsoft.Json.Linq
string url = "https://yourAPIurl";
WebRequest myReq = WebRequest.Create(url);
string credentials = "xxxxxxxxxxxxxxxxxxxxxxxx:yyyyyyyyyyyyyyyyyyyyyyyyyyyyyy";
CredentialCache mycache = new CredentialCache();
myReq.Headers["Authorization"] = "Basic " + Convert.ToBase64String(Encoding.ASCII.GetBytes(credentials));
WebResponse wr = myReq.GetResponse();
Stream receiveStream = wr.GetResponseStream();
StreamReader reader = new StreamReader(receiveStream, Encoding.UTF8);
string content = reader.ReadToEnd();
Console.WriteLine(content);
var json = "[" + content + "]"; // change this to array
var objects = JArray.Parse(json); // parse as array
foreach (JObject o in objects.Children<JObject>())
{
foreach (JProperty p in o.Properties())
{
string name = p.Name;
string value = p.Value.ToString();
Console.Write(name + ": " + value);
}
}
Console.ReadLine();
Reference: TheDeveloperBlog.com
Late response but this is what I ended up doing. If you want to run your curl commands very similarly as you run them on linux and you have windows 10 or latter do this:
public static string ExecuteCurl(string curlCommand, int timeoutInSeconds=60)
{
if (string.IsNullOrEmpty(curlCommand))
return "";
curlCommand = curlCommand.Trim();
// remove the curl keworkd
if (curlCommand.StartsWith("curl"))
{
curlCommand = curlCommand.Substring("curl".Length).Trim();
}
// this code only works on windows 10 or higher
{
curlCommand = curlCommand.Replace("--compressed", "");
// windows 10 should contain this file
var fullPath = System.IO.Path.Combine(Environment.SystemDirectory, "curl.exe");
if (System.IO.File.Exists(fullPath) == false)
{
if (Debugger.IsAttached) { Debugger.Break(); }
throw new Exception("Windows 10 or higher is required to run this application");
}
// on windows ' are not supported. For example: curl 'http://ublux.com' does not work and it needs to be replaced to curl "http://ublux.com"
List<string> parameters = new List<string>();
// separate parameters to escape quotes
try
{
Queue<char> q = new Queue<char>();
foreach (var c in curlCommand.ToCharArray())
{
q.Enqueue(c);
}
StringBuilder currentParameter = new StringBuilder();
void insertParameter()
{
var temp = currentParameter.ToString().Trim();
if (string.IsNullOrEmpty(temp) == false)
{
parameters.Add(temp);
}
currentParameter.Clear();
}
while (true)
{
if (q.Count == 0)
{
insertParameter();
break;
}
char x = q.Dequeue();
if (x == '\'')
{
insertParameter();
// add until we find last '
while (true)
{
x = q.Dequeue();
// if next 2 characetrs are \'
if (x == '\\' && q.Count > 0 && q.Peek() == '\'')
{
currentParameter.Append('\'');
q.Dequeue();
continue;
}
if (x == '\'')
{
insertParameter();
break;
}
currentParameter.Append(x);
}
}
else if (x == '"')
{
insertParameter();
// add until we find last "
while (true)
{
x = q.Dequeue();
// if next 2 characetrs are \"
if (x == '\\' && q.Count > 0 && q.Peek() == '"')
{
currentParameter.Append('"');
q.Dequeue();
continue;
}
if (x == '"')
{
insertParameter();
break;
}
currentParameter.Append(x);
}
}
else
{
currentParameter.Append(x);
}
}
}
catch
{
if (Debugger.IsAttached) { Debugger.Break(); }
throw new Exception("Invalid curl command");
}
StringBuilder finalCommand = new StringBuilder();
foreach (var p in parameters)
{
if (p.StartsWith("-"))
{
finalCommand.Append(p);
finalCommand.Append(" ");
continue;
}
var temp = p;
if (temp.Contains("\""))
{
temp = temp.Replace("\"", "\\\"");
}
if (temp.Contains("'"))
{
temp = temp.Replace("'", "\\'");
}
finalCommand.Append($"\"{temp}\"");
finalCommand.Append(" ");
}
using (var proc = new Process
{
StartInfo = new ProcessStartInfo
{
FileName = "curl.exe",
Arguments = finalCommand.ToString(),
UseShellExecute = false,
RedirectStandardOutput = true,
RedirectStandardError = true,
CreateNoWindow = true,
WorkingDirectory = Environment.SystemDirectory
}
})
{
proc.Start();
proc.WaitForExit(timeoutInSeconds*1000);
return proc.StandardOutput.ReadToEnd();
}
}
}
The reason why the code is a little bit long is because windows will give you an error if you execute a single quote. In other words, the command curl 'https://google.com' will work on linux and it will not work on windows. Thanks to that method I created you can use single quotes and run your curl commands exactly as you run them on linux. This code also checks for escaping characters such as \' and \".
For example use this code as
var output = ExecuteCurl(#"curl 'https://google.com' -H 'Accept: application/json, text/javascript, */*; q=0.01'");
If you where to run that same string agains C:\Windows\System32\curl.exe it will not work because for some reason windows does not like single quotes.
I know this is a very old question but I post this solution in case it helps somebody. I recently met this problem and google led me here. The answer here helps me to understand the problem but there are still issues due to my parameter combination. What eventually solves my problem is curl to C# converter. It is a very powerful tool and supports most of the parameters for Curl. The code it generates is almost immediately runnable.
Don't forget to add System.Net.Http, specially if you receive this error:
Severity Code Description Project File Line Suppression State
Error CS0246 The type or namespace name 'HttpClient' could not be
found (are you missing a using directive or an assembly
reference?) 1_default.aspx D:\Projetos\Testes\FacebookAPI\FB-CustomAudience\default.aspx.cs 56 Active
In this case you shoud:
Add System.Net.Http from Nuget: Tools / NuGet Package Manager / Manager NuGet Packages for Solution;
Search for System.Net.Http
Add in the top of your page the follow code:
using System.Net.Http;
Call cURL from your console app is not a good idea.
But you can use TinyRestClient which make easier to build requests :
var client = new TinyRestClient(new HttpClient(),"https://api.repustate.com/");
client.PostRequest("v2/demokey/score.json").
AddQueryParameter("text", "").
ExecuteAsync<MyResponse>();
Well if you are new to C# with cmd-line exp. you can use online sites like "https://curl.olsh.me/" or search curl to C# converter will returns site that could do that for you.
or if you are using postman you can use Generate Code Snippet only problem with Postman code generator is the dependency on RestSharp library.

Categories