Translate a piece of PHP cURL code to C# - c#

I'm trying to translate this piece of code written to fetch data from basis's website (the activity tracker). The task I want to achieve here is to fetch the access_token returned in the Http response header. There is no problem with the original PHP code, however, there are a few cUrl options I don't know how to map to C#'s WebClient implementation. These options include CURLOPT_RETURNTRANSFER, CURLOPT_FOLLOWLOCATION and CURLOPT_COOKIESESSION.
The detail problem is listed below, here is the piece of PhP code:
$login_data = array(
'username' => $this->username,
'password' => $this->password,
);
// Initialize the cURL resource and make login request
$ch = curl_init();
curl_setopt_array($ch, array(
CURLOPT_URL => 'https://app.mybasis.com/login',
CURLOPT_RETURNTRANSFER => false, //default: true
CURLOPT_POST => true,
CURLOPT_POSTFIELDS => $login_data,
CURLOPT_FOLLOWLOCATION => true, // defulat: true
CURLOPT_HEADER => 1,
CURLOPT_COOKIESESSION => true,
CURLOPT_COOKIEJAR => $this->cookie_jar
));
Using this code, the result would be: (which contains the access token I need)
HTTP/1.1 100 Continue
HTTP/1.1 302 Found
Date: Sun, 22 Jun 2014 02:03:47 GMT
Content-Type: text/html; charset=UTF-8
Content-Length: 0
Connection: keep-alive
Server: TornadoServer/3.2
Location: https://app.mybasis.com
Cache-Control: max-age=0
Set-Cookie: access_token=f0659120d52f3fde9edfw1d908b81f0f; Domain=. mybasis.com; expires=Sun, 01 Jan 2040 00:00:00 GMT; Path=/
Set-Cookie: scope=login; Domain=.mybasis.com; expires=Sun, 01 Jan 2040 00:00:00 GMT; Path=/
Set-Cookie: refresh_token=982ff518bfe114e2c03f360f0dfbfke1; Domain=. mybasis.com; expires=Sun, 01 Jan 2040 00:00:00 GMT; Path=/
HTTP/1.1 200 OK
Server: nginx/1.4.3
Date: Sun, 22 Jun 2014 02:03:47 GMT
Content-Type: text/html; charset=utf-8
Content-Length: 5619
Last-Modified: Fri, 25 Apr 2014 04:42:49 GMT
Connection: keep-alive
Vary: Accept-Encoding
ETag: "5359e7c9-15f3"
Accept-Ranges: bytes
However, when I use C# WebClient to communicate with basis like below:
var data = new NameValueCollection
{
{ "username", username},
{ "password", password},
};
HttpWebResponse response = client.UploadValues("https://app.mybasis.com/login", "POST", data);
foreach (string name in client.ResponseHeaders.Keys)
{
Console.WriteLine(name+"="+client.ResponseHeaders[name]);
}
I could only get this:
Connection=keep-alive
Vary=Accept-Encoding
Accept-Ranges=bytes
Content-Length=5619
Content-Type=text/html; charset=utf-8
Date=Sun, 22 Jun 2014 02:17:44 GMT
ETag="53f3e7c9-99f3"
Last-Modified=Fri, 25 Apr 2014 04:42:49 GMT
Server=nginx/1.4.3
as response.
Does anyone know why I cannot get the first two Http responses but the third one only?

In order to get the functionality out of C# you are looking for you need to use the Http web Request API within the .NET framework. It should provide the capability you are looking for.

I did the same thing but used the 4.5 HttpClient
CookieContainer cookies = new CookieContainer();
HttpClientHandler handler = new HttpClientHandler();
handler.CookieContainer = cookies;
HttpClient client = new HttpClient(handler);
// Create the HttpContent for the form to be posted.
var requestContent = new FormUrlEncodedContent(new[] {
new KeyValuePair<string, string>("username", "***"),
new KeyValuePair<string, string>("password", "***"),
});
// Get the response.
HttpResponseMessage response = await client.PostAsync(
"https://app.mybasis.com/login",
requestContent);
// Get the response content.
HttpContent responseContent = response.Content;
Uri uri = new Uri("https://app.mybasis.com/login");
IEnumerable<Cookie> responseCookies = cookies.GetCookies(uri).Cast<Cookie>();
foreach (Cookie cookie in responseCookies)
Console.WriteLine(cookie.Name + ": " + cookie.Value);

Related

IIS is returning JSON instead of File (in Export to Excel functionality)

I have a web application that's being hosted on IIS 8. It uses VueJS, and ASP.NET Web API. It has the ability to export a grid to Excel, which works in our TEST environment, but doesn't work in our Production environment. In TEST, when the user clicks on the Export to Excel button, it allows the user to download the XLSX document in the web browser. But in Production, it returns JSON.
Here's the code I'm using to stream out the file:
var appRoot = HttpContext.Current.Server.MapPath("~/");
var savePath = string.Format("{0}\\Temporary_Files\\{1}.xlsx", appRoot, Guid.NewGuid());
workbook.SaveAs(savePath);
HttpResponseMessage document = new HttpResponseMessage(HttpStatusCode.OK);
var stream = new FileStream(savePath, FileMode.Open);
document.Content = new StreamContent(stream);
document.Content.Headers.ContentDisposition = new ContentDispositionHeaderValue("attachment");
document.Content.Headers.ContentDisposition.FileName = "Export.xlsx";
document.Content.Headers.ContentType = new MediaTypeHeaderValue("application/octet-stream");
document.Content.Headers.ContentLength = stream.Length;
return document;
Here's the response in TEST:
RESPONSE HEADERS
HTTP/1.1 200 OK
Cache-Control: no-cache
Pragma: no-cache
Content-Length: 7713
Content-Type: application/octet-stream
Expires: -1
Server: Microsoft-IIS/8.5
Content-Disposition: attachment; filename=Export.xlsx
X-AspNet-Version: 4.0.30319
Persistent-Auth: true
X-Powered-By: ASP.NET
Access-Control-Allow-Headers: Origin, X-Requested-With, Content-Type, Accept
Access-Control-Allow-Methods: POST,GET,OPTIONS,PUT,DELETE
Date: Fri, 04 Dec 2020 17:50:54 GMT
Here's the response in Production:
RESPONSE HEADERS
HTTP/1.1 200 OK
Cache-Control: no-cache
Pragma: no-cache
Content-Type: application/json; charset=utf-8
Expires: -1
Server: Microsoft-IIS/8.5
X-AspNet-Version: 4.0.30319
Persistent-Auth: true
X-Powered-By: ASP.NET
Access-Control-Allow-Headers: Origin, X-Requested-With, Content-Type, Accept
Access-Control-Allow-Methods: POST,GET,OPTIONS,PUT,DELETE
Date: Fri, 04 Dec 2020 17:45:02 GMT
Content-Length: 373
RESPONSE BODY
{"Version":{"_Major":1,"_Minor":1,"_Build":-1,"_Revision":-1},"Content":{"Headers":[{"Key":"Content-Disposition","Value":["attachment; filename=Export.xlsx"]},{"Key":"Content-Type","Value":["application/octet-stream"]},{"Key":"Content-Length","Value":["7497"]}]},"StatusCode":200,"ReasonPhrase":"OK","Headers":[],"RequestMessage":null,"IsSuccessStatusCode":true}
You can try my way:
return File(bytes, "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
reportFilename + "." + extension)

How to use the Visual Studio Team Services API

I've cracked how to pull data using the API but now I'm trying to push a new work item to a project and i just can't seem to get it working here's my c# :
try {
using (HttpClient client = new HttpClient()) {
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Basic", Convert.ToBase64String(
ASCIIEncoding.ASCII.GetBytes(
string.Format("{0}:{1}", "", token))));
string Url = $"https://XXX/DefaultCollection/{Job.Project}/_apis/wit/workitems/$Task?api-version=1.0";
var method = new HttpMethod("PATCH");
var request = new HttpRequestMessage(method, Url) {
Content = new StringContent(Job.WorkItem, Encoding.UTF8,
"application/json-patch+json")
};
using (HttpResponseMessage response = client.SendAsync(request).Result) {
response.EnsureSuccessStatusCode();
string responseBody = response.Content.ReadAsStringAsync().Result;
}
}
}
catch (Exception ex) {
MessageBox.Show(ex.ToString());
return null;
}
Here is Job.WorkItem as shown up in the debugger
"[
{
\"op\":\"add\",
\"path\":\"/fields/System.Title\",
\"value\":\"Please add a business area for XXX Systems\\n\"
}
]"
Have I missed something or doing something wrong as it responds with
{StatusCode: 400, ReasonPhrase: 'Bad Request', Version: 1.1, Content: System.Net.Http.StreamContent, Headers:
{
Pragma: no-cache
X-TFS-ProcessId: xxx
Strict-Transport-Security: max-age=31536000; includeSubDomains
Access-Control-Allow-Origin: *
Access-Control-Max-Age: 3600
Access-Control-Allow-Methods: OPTIONS,GET,POST,PATCH,PUT,DELETE
Access-Control-Expose-Headers: ActivityId,X-TFS-Session,X-MS-ContinuationToken
Access-Control-Allow-Headers: authorization
X-FRAME-OPTIONS: SAMEORIGIN
X-VSS-UserData: xxxx
ActivityId: xxxx
X-TFS-Session: xxx
X-Content-Type-Options: nosniff
Cache-Control: no-cache
Date: Wed, 13 Jul 2016 16:48:28 GMT
P3P: CP="CAO DSP COR ADMa DEV CONo TELo CUR PSA PSD TAI IVDo OUR SAMi BUS DEM NAV STA UNI COM INT PHY ONL FIN PUR LOC CNT"
Server: Microsoft-IIS/8.5
X-AspNet-Version: 4.0.30319
X-Powered-By: ASP.NET
Content-Length: 429
Content-Type: application/json; charset=utf-8
Expires: -1
}}
I have omitted some details with xxx just FYI
You should refer to REST Api documentation for specific actions.
Also, as you are calling it from .net maybe client lib for VSO Api is a simpler way to go?
There is redundant double quotation marks in the Job.WorkItem which will cause bad request. The content should be:
[
{
\"op\":\"add\",
\"path\":\"/fields/System.Title\",
\"value\":\"Please add a business area for XXX Systems\\n\"
}
]
Refer to this link for details: Create a work item.

Http Authorization Header

I would like to get the response of a json api provided by some website this is their cURL Request
curl --include --header "X-Access-Token: XXXXX" "http://api.travelpayouts.com/v2/prices/latest?"
trying to get the content using
using (var client = new HttpClient())
{
client.DefaultRequestHeaders.Add("X-Access-Token", "XXXXX");
HttpResponseMessage response = await client.GetAsync(url);
var contents = await response.Content.ReadAsStringAsync();
MessageBox.Show(contents);
}
but still getting
{"success":false,"data":null,"message":"Unauthorized"}
Are you sure that you are using token? in your code it looks like a marker.
Here is my output:
#e:~$ curl --include --header "X-Access-Token: d273e9325fXXXXXXXXXXXXX" "http://api.travelpayouts.com/v2/prices/latest?currency=rub&period_type=year&page=1&limit=30&show_to_affiliates=true&sorting=price&trip_class=0"
HTTP/1.1 200 OK
Server: nginx/1.2.4
Date: Wed, 25 Nov 2015 13:53:52 GMT
Content-Type: application/json;charset=utf-8
Content-Length: 7083
Connection: keep-alive
Vary: Accept-Encoding
Status: 200 OK
X-Content-Type-Options: nosniff
{"success": true, "data":

HttpClient.SendAsync: 500 - Internal Server Error in Windows Service Application

I am seeing the following message in attempting to post a json string to a web API (this is what is written to file in the line containing System.IO.File.WriteAllText):
Response: StatusCode: 500, ReasonPhrase: 'Internal Server Error', Version: 1.1, Content: System.Net.Http.StreamContent, Headers:
{
Pragma: no-cache
Cache-Control: no-cache
Date: Thu, 13 Aug 2015 21:26:12 GMT
Server: Microsoft-IIS/8.5
X-AspNet-Version: 4.0.30319
X-Powered-By: ASP.NET
Content-Length: 36
Content-Type: application/json; charset=utf-8
Expires: -1
}
The code within my async posting method is as follows:
Uri theUri = new Uri("http://www.website.com/WebsiteAPI/PostDetails");
HttpClient aClient = new HttpClient();
aClient.BaseAddress = theUri;
aClient.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
aClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Basic",
Convert.ToBase64String(
System.Text.ASCIIEncoding.ASCII.GetBytes(
string.Format("{0}:{1}", "USERNAME", "PASSWORD"))));
aClient.DefaultRequestHeaders.Host = theUri.Host;
HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Post, theUri);
request.Content = new StringContent(resource, Encoding.UTF8, "application/json");
// Post the data
aClient.SendAsync(request).ContinueWith(responseTask =>
{
System.IO.File.WriteAllText(PROFILE_JSON_PATH, "Response: " + responseTask.Result);
});
I've tried many different solutions online but nothing seems to work. Any idea why this may not be working?
The short answer is that there is something with your Web API that is erroring. You may or may not have something wrong with your client code--but you'll have to go to the Web API for information that could explain what the problem is.

Reading HTTP file attachment as string

I am using a WebRequest to make a GET and the response includes an attachment.
The attachment is a html file that I want to strip the content out between the tags. I have managed to get the call working with the following code:
string URI = "http://www.sample.com/ReportServer/Pages/ReportViewer.aspx?%2fReports&rs:Command=Render&rs:Format=MHTML&OrganisationID=" + organisationID;
CredentialCache cc = new CredentialCache();
cc.Add(new Uri(URI), "NTLM", new NetworkCredential(userName, userPassword, userDomain));
WebRequest req = WebRequest.Create(URI);
req.Credentials = cc;
WebResponse resp = req.GetResponse();
StreamReader reader = new StreamReader(resp.GetResponseStream());
string response = reader.ReadToEnd().Trim();
The response, when i look in Fiddler is :
HTTP/1.1 200 OK
Cache-Control: private
Content-Type: multipart/related
Expires: Wed, 02 Apr 2014 14:35:15 GMT
Set-Cookie: RSExecutionSession%3a%2fPuborts%2fSecreal%2fClub+Meip+Ret=0yu4f1455xnmznu55; path=/
Server: Microsoft-HTTPAPI/2.0
X-AspNet-Version: 2.0.50727
FileExtension: mhtml
Content-Disposition: attachment; filename="Blah Report.mhtml"
Date: Wed, 02 Apr 2014 14:36:15 GMT
Content-Length: 84215
MIME-Version: 1.0
Content-Type: multipart/related;
boundary="----=_NextPart_01C35DB7.4B204430"
X-MSSQLRS-ProducerVersion: V10.50.4000.0
This is a multi-part message in MIME format.
------=_NextPart_01C35DB7.4B204430
Content-Disposition: inline; filename="Blah Membership Report"
Content-Type: text/html;
name="Club Membership Report";
charset="utf-8"
Content-Transfer-Encoding: base64
PCFET0NUWVBFIEhUTUwgUFVCTElDICItLy9XM0MvL0RURCBIVE1MIDQuMDEgVHJhbnNpdGlvbmFs
------=_NextPart_01C35DB7.4B204430--
How can I get hold of just the attachment and read the contents into a string please?
The "attachment" part is just to enforce a save as screen in the browser.
You can use a normal WebClient
var client = new WebClient();
using (client)
{
client.Credentials = blablabla
var result = client.DownloadString("http://blablabla.com");
}

Categories