how to get the response body in code webtest? - c#

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;
}

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).

Web Api Post method is receiving NULL parameter always

I am trying to pass List as a parameter to web Api , Using below code;
Client Side
public async Task<ActionResult>BatchUpdatePartial(MVCxGridViewBatchUpdateValues<NewWorkItem, int> batchValues)
{
var updatedItems = new List<NewWorkItem>();
string url = "http://localhost:9198/api/values";
foreach (var item in batchValues.Update)
{
if (batchValues.IsValid((item)))
{
var updatedVals = new NewWorkItem();
updatedVals.CPK_ID = item.CPK_ID;
updatedVals.BYR_ID = item.BYR_ID;
updatedVals.P_ID = item.P_ID;
updatedVals.CPK_PRI_FLG = item.CPK_PRI_FLG;
updatedItems.Add(updatedVals);
}
else
batchValues.SetErrorText(item, "Correct Vallidation Errors");
}
using (var client = new WebClient())
{
client.Headers[HttpRequestHeader.ContentType] = "application/json";
client.Encoding = System.Text.Encoding.UTF8;
string serialisedData = JsonConvert.SerializeObject(updatedItems);
string response = client.UploadString(url, serialisedData);
Object result = JsonConvert.DeserializeObject(response);
}
return PartialView("_GridViewPartial", NewWorkItem.GridData);
}
Server Side
public string Post([FromBody]string[] values)
{
string seperator = ",";
string data = string.Join(seperator, values.ToList<string>());
string result = string.Format("Succesfully uploaded: {0}", data);
return result;
}
But I am always getting NULL inside the values at server side ?
Can you please suggest me solution ?
Thanks
Unfortunately, you are not actually sending a string[] the way your POST method expects. You are sending serializedData, which is, by your own definition, a serialization of updatedItems. updatedItems is a list of a reference type - you do not provide the definition of it here, but I guarantee you it is not going to serialize the same way a string does.
You will need to change updatedItems to be List<string> or something similar.

Error reusing some async json method on windows phone

EDIT 1: I added below the code who calls and uses the second method, and the error and data I recive
First of all sorry if my English isn't good enough, and sorry if there is another thread with the solution. I haven't found it.
Ok, I'm making a windows phone 8 app that uses a lot of info from a web service. The app makes different Json Post and uses the info. I maked a method for Posting that WORKS:
public static async void checkdeviceid()
{
//Where we are posting to:
Uri theUri = new Uri("urlofexample");
//Create an Http client
HttpClient aClient = new HttpClient();
//Class that will be serialized into Json
objetoslistas.checkdeviceidinput paquete = new objetoslistas.checkdeviceidinput();
//Set some values
paquete.Text = "deviceID";
paquete.Text2 = App.device_id;
//serialize data
var serializado = JsonConvert.SerializeObject(paquete);
//Post the data
HttpResponseMessage aResponse = await aClient.PostAsync(theUri, new StringContent(JsonConvert.SerializeObject(paquete), Encoding.UTF8, "application/json"));
if (aResponse.IsSuccessStatusCode)
{
string res = await aResponse.Content.ReadAsStringAsync();
var respuestaperfil = JsonConvert.DeserializeObject<objetoslistas.checkdeviceidoutput>(res.ToString());
//Do something with the data
}
else
{
// show the response status code
String failureMsg = "HTTP Status: " + aResponse.StatusCode.ToString() + " - Reason: " + aResponse.ReasonPhrase;
}
}
This code its actually working, but the fact it's that my app will have maybe 30 or 40 diferent POST, so I tried to make a reusable method like this:
public static async Task<string> jsonPOST(Uri theUri, object paquete)
{
//Create an Http client and set the headers we want
HttpClient aClient = new HttpClient();
//serialize data
var serializado = JsonConvert.SerializeObject(paquete);
//Post the data
HttpResponseMessage aResponse = await aClient.PostAsync(theUri, new StringContent(JsonConvert.SerializeObject(paquete), Encoding.UTF8, "application/json"));
if (aResponse.IsSuccessStatusCode)
{
string res = await aResponse.Content.ReadAsStringAsync();
return res;
}
else
{
// show the response status code
String failureMsg = "HTTP Status: " + aResponse.StatusCode.ToString() + " - Reason: " + aResponse.ReasonPhrase;
return failureMsg;
}
}
This code gives me problems in the main, were it's called. As I can understand, the problem is that, as the method calls some await process, the rest of the code continues with the execution without expect for the await result...
The code in Main is:
objetoslistas.checkdeviceidinput paquete = new objetoslistas.checkdeviceidinput();
paquete.Text = "deviceID";
paquete.Text2 = App.device_id;
Uri url = new Uri("urlofhteservice");
Task<string> recibo = metodosJson.jsonPOST(url, paquete);
var respuestaperfil = JsonConvert.DeserializeObject<objetoslistas.checkdeviceidoutput>(recibo.ToString);
if (respuestaperfil.Text2 == null)
{
IsolatedStorageSettings.ApplicationSettings["DeviceRegistered"] = true;
}
else
{
IsolatedStorageSettings.ApplicationSettings["DeviceRegistered"] = false;
}
And I recive this error (translated from google translator, sorry)
There was an exception of type 'Newtonsoft.Json.JsonReaderException' in Newtonsoft.Json.DLL but not controlled in the user code
The data I have in "recibo" is
recibo Id = 1, Status = WaitingForActivation, Method = "{null}", Result = "{Not yet computed}" System.Threading.Tasks.Task<string>
So as I understand the await method is still waiting.
Was I clear?
Thanks

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.

Making a cURL call in 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.

Categories