Why does cURL work, but my HttpWebRequest does not? - c#

I'm trying to take the below curl statement and reperform it in a c# method. The following curl statement works fine (I masked the credentials and IP address) so I'm sure the destination server is willing to play ball:
curl -D- -u user:password -X POST --data #data.txt -H "Content-Type: application/json" http://0.0.0.0:8080/rest/api/2/issue/
where the data.txt looks like this:
{
"fields": {
"project":{"id": "10000"},
"summary": "No REST for the Wicked.",
"description": "Creating of an issue using ids for projects and issue types using the REST API",
"issuetype": {"id": "10002"},
"customfield_10115" : "3212.12",
"customfield_10116" : "Client Name",
"customfield_10117" : "Engagement Name",
"customfield_10118" : "TEst",
"customfield_10121" : "2019-11-30",
"customfield_10120" : "Daily"
}
}
However, when I try and re-perform the above in C#, it's giving me the dreaded I'm-Not-Telling-You-Why-This-Doesn't-Work message: "The remote server returned an error: (500) Internal Server Error."
Here's my C# Code.
Console.WriteLine("Start");
var httpWebRequest = (HttpWebRequest)WebRequest.Create("http://0.0.0.0:8080/rest/api/2/issue/");
httpWebRequest.ContentType = "application/json";
httpWebRequest.Method = "POST";
httpWebRequest.Headers.Add("Authorization", "Basic user:password");
using (var streamWriter = new StreamWriter(httpWebRequest.GetRequestStream()))
{
string json = "{\"fields\": {\"project\":{ \"id\": \"10000\"},\"summary\": \"No REST for the Wicked.\",\"description\": \"description text\",\"issuetype\": { \"id\": \"10002\"},\"customfield_10115\" : \"3212.12\",\"customfield_10116\" : \"Client Name\",\"customfield_10117\" : \"Engagement Name\",\"customfield_10118\" : \"Payroll\",\"customfield_10121\" : \"2019-11-30\",\"customfield_10120\" : \"Daily\"}}";
streamWriter.Write(json);
}
var httpResponse = (HttpWebResponse)httpWebRequest.GetResponse();
using (var streamReader = new StreamReader(httpResponse.GetResponseStream()))
{
var result = streamReader.ReadToEnd();
}
Any ideas?

Kudos to fenixil who spotted my issue:
Just needed to Base64 the username/password pair. Works like a champ now!

Related

Jira API POST returning (405) Method Not Allowed

I just can't seem to figure out why I am getting a 405 "Method Not Allowed" error message..
I would like to create a new issue in my project, the key is "BS". I copied/pasted this directly from Jira documentation and still can't get it to work.
I have tried so many different types of string variances, but this one should work. Is it something else that might be giving me this error?
Here is my code:
string stringData = #"{""fields"": {""project"":{""key"": ""BS""},""summary"": ""REST ye merry gentlemen."",""issuetype"": {""name"": ""Ticket""}}}";
string url = #"http://HOST.atlassian.net/rest/api/2/issue";
var data = Encoding.ASCII.GetBytes(stringData); // or UTF8
WebRequest wrUrl = WebRequest.Create(url);
wrUrl.ContentType = "application/json";
wrUrl.Method = "POST";
wrUrl.Headers["Authorization"] = "Basic " + Convert
.ToBase64String(Encoding.ASCII.GetBytes(Username+":"+Password));
wrUrl.ContentLength = data.Length;
var newStream = wrUrl.GetRequestStream();
newStream.Write(data, 0, data.Length);
newStream.Close();
Console.WriteLine(wrUrl.GetResponse().ToString());
Console.ReadKey();
Just hit this exact error: a status code 405 "Method Not Allowed". It turns out the answer is literally just using HTTPS instead of HTTP. The accepted answer lacks this detail.
https://developer.atlassian.com/cloud/jira/platform/rest/#api-api-2-issue-post
1 - try HTTPS
2 - Do you have WRITE scope?
3 - What content comes back with the response? Could be something
4 - "You must provide a parent field with the ID or key of the parent issue."
So to anyone having a similar problem, I'd like to leave this answer to show how I fixed it.
First off, I scrapped this whole project and used RestSharp to connect instead. I used Postman to test my json until I got it right. Postman has an option to convert your JSON to a C# request, Here is my code:
using System;
using RestSharp;
using RestSharp.Authenticators;
public class Program
{
//This gets meta tags for the SS project and issue type "Ticket"
// https://HOST.atlassian.net/rest/api/2/issue/createmeta?projectKeys=SS&issuetypeNames=Ticket&expand=projects.issuetypes.fields
public static string url = "https://HOST.atlassian.net/rest/api/2/issue";
public static string username = "YOURUSERNAME";
public static string password = "YOURAPIKEY";
//host:port/context/rest/api-name/api-version/resource-name
static void Main(string[] args)
{
var fieldPriority = "Low";
var fieldSubject = "Payment Problem";
var fieldTechResource = "BLAH";
NewJiraIssue(fieldSubject,fieldPriority, fieldTechResource);
}
//*****************************************
// Create a new Jira Issue
//*****************************************
//INPUT: OUT: New Ticket Number
//*****************************************
static void NewJiraIssue(string fieldSubject, string fieldPriority, string fieldTechResource)
{
try
{
var client = new RestClient("https://HOST.atlassian.net/rest/api/latest/issue");
var request = new RestRequest(Method.POST);
request.AddHeader("Postman-Token", "ad6dbffb-89fe-4b21-b59a-0dc60724510f");
request.AddHeader("Cache-Control", "no-cache");
request.AddHeader("Authorization", "Basic
KEY FROM ");
request.AddHeader("Content-Type", "application/json");
//Created Date
//Date CR Is approved internal //Customer Approval
Sent Date //Customer Approval Date:
//Planned UAT Completion Date: //Actual Delivery
Date to UAT:
request.AddParameter("undefined", "{\r\n \"fields\": {\r\n
\"project\":\r\n {\r\n \"key\": \"SS\",\r\n \"id\":
\"10040\"\r\n },\r\n \"summary\": \""+fieldSubject+"\",\r\n \r\n
\"issuetype\": {\r\n \"name\": \"Ticket\"\r\n },\r\n
\"customfield_10042\" : \"2010-03-01T00:00:00.000+0400\",\r\n
\"customfield_10043\" : \"customfield_10043\",\r\n\r\n \"customfield_10067\" :
\"customfield_10067\",\r\n \"customfield_10068\" :
\"customfield_10068\",\r\n\r\n \"customfield_10070\" : \"2001-03-
01T00:00:00.000+0400\",\r\n \"customfield_10071\" : \"2002-03-
01T00:00:00.000+0400\",\r\n \"customfield_10072\" : \"2003-03-
01T00:00:00.000+0400\",\r\n \"customfield_10073\" : \"2004-03-
01T00:00:00.000+0400\",\r\n \"customfield_10074\" : \"2005-03-
01T00:00:00.000+0400\",\r\n \r\n \"priority\": {\"name\": \"" +
fieldPriority + "\"},\r\n \"customfield_10069\": {\"name\" : \"" +
fieldTechResource + "\"}\r\n}\r\n}", ParameterType.RequestBody);
IRestResponse response = client.Execute(request);
Console.WriteLine(response.Content);
Console.ReadKey();
}
catch (Exception ex)
{
Console.WriteLine(ex);
Console.ReadKey();
}
}

Converting CURL request to C# for accessing Snipcart API returns 401 Unauthorized

I am trying to access the Snipcart API (Reference - https://docs.snipcart.com/api-reference/authentication). I have created an API key and followed the steps mentioned in the documentation.
I am trying to Convert a CURL request to C#. I chose to use HttpWebRequest. I get 401 Unauthorized returned from the Server. I am not able to figure out what's wrong with my request.
Actual Curl Request: - curl -H "Accept: application/json"
https://app.snipcart.com/api/orders
-u {API_KEY}:
The following is the code that i tried converting the above curl request to
string baseURL = "https://app.snipcart.com/api/orders";
HttpWebRequest req = (HttpWebRequest)WebRequest.Create(baseURL);
req.AllowAutoRedirect = true;
req.ContentType = "application/json";
req.Accept = "application/json";
req.Method = "GET";
req.Headers.Add("API_Key", "MY_API_KEY_VALUE_COMES_HERE");
string jsonResponse = null;
using (WebResponse resp = req.GetResponse())
{
if (req.HaveResponse && resp != null)
{
using (var reader = new StreamReader(resp.GetResponseStream()))
{
jsonResponse = reader.ReadToEnd();
}
}
}
Console.Write(jsonResponse);
You need to send the header as a basic auth header instead of "API_Key" Try something like this.
HttpWebRequest req = (HttpWebRequest)WebRequest.Create(baseURL);
req.AllowAutoRedirect = true;
req.ContentType = "application/json";
req.Accept = "application/json";
req.Method = "GET";
var basicAuthHeader = Convert.ToBase64String(ASCIIEncoding.ASCII.GetBytes("MY_API_KEY_VALUE_COMES_HERE"));
req.Headers.Add("Authorization", "Basic " + basicAuthHeader);
The API reference from Snipcart says you need Basic HTTP Authentication.
When I have a look at your code, I think you should change this line
req.Headers.Add("API_Key", "MY_API_KEY_VALUE_COMES_HERE");
to
req.Credentials = new NetworkCredential("API_Key", "MY_API_KEY_VALUE_COMES_HERE");
A kind of the same issue is described in this topic, you can take it as reference.
If it's not solving the issue, you could have a closer look at the curl API parameters manual, and then translate it to C# code.
curl -H "Accept: application/json" \
https://app.snipcart.com/api/orders \
-u {API_KEY}:

How to call Google Cloud API using RestSharp and OAuth 2

I'm trying to call the google cloud API. Specifically, the language API from c# using the RestSharp library and OAuth 2. I'm able to successfully connect to the API using the curl call below:
curl -s -k -H "Content-Type: application/json" -H "Authorization: Bearer <access_token>"
https://language.googleapis.com/v1beta1/documents:annotateText
-d #c:\temp\entity_request.json > c:\temp\googleanalysis.json
I've tried several different ways of authenticating, but none of them so far have worked. My latest c# code looks like the following:
var client = new RestClient("https://language.googleapis.com");
client.Authenticator = new RestSharp.Authenticators.HttpBasicAuthenticator("client-app", "<access_token>");
var request = new RestRequest("/v1beta1/documents:analyzeEntities", Method.POST);
request.AddHeader("Content-Type", "application/json");
request.AddFile("filename", #"c:\temp\entity_request.json");
var response = client.Execute(request);
var content = response.Content;
When I run this call from c# I get the following error back:
{
"error": {
"code": 403,
"message": "The request cannot be identified with a client project. Please pass a valid API key with the request.",
"status": "PERMISSION_DENIED"
}
}
My question is how do I properly call the google cloud API in RestSharp the way I am successfully with curl?
This works for me:
//obtenemos el token para las peticiones
string access_token = GetAccessToken(jsonFolder, new string[] { "https://www.googleapis.com/auth/cloud-platform" });
//peticiones hacia el rest de automl
var client = new RestClient("https://language.googleapis.com");
var request = new RestRequest("v1/documents:analyzeEntities", Method.POST);
request.AddHeader("Authorization", string.Format("Bearer {0}", access_token));
request.AddHeader("Content-Type", "aplication/json");
//seteamos el objeto
var aml = new AutoMLload_entities();
aml.document.content = text;
request.AddJsonBody(aml);
IRestResponse response = client.Execute(request);
if (response.StatusCode == System.Net.HttpStatusCode.OK)
{

Connecting to Urban Airship REST API with c#

I am getting a 400 bad request error when trying to connect to the Urban Airship Rest API. Below is the curl command I am trying to replicate in .NET. The .NET code is at the end. Please help.
curl -v -X POST
-u "username:passowrd"
-H "Content-type: application/json"
-H "Accept: application/vnd.urbanairship+json; version=3;"
--data '{"audience" : {"tag":"1_13_98"},
"device_types" : "all",
"notification" : {"alert": "Tag push alert"}
}'
https://go.urbanairship.com/api/push
The c# code I am trying to use is:
var json = gcm.ToJsonString();
Console.WriteLine("JSON GCM Message: " + json);
var uri = new Uri("https://go.urbanairship.com/api/push/?");
var encoding = new UTF8Encoding();
var request = (HttpWebRequest)WebRequest.Create(uri);
request.Method = "POST";
request.Credentials = new NetworkCredential(username, master);
request.ContentType = "application/json";
WebHeaderCollection myWebHeaderCollection = request.Headers;
myWebHeaderCollection.Add(HttpRequestHeader.Accept, "application/vnd.urbanairship+json; version=3;");
request.ContentLength = encoding.GetByteCount(json);
using (var stream = request.GetRequestStream())
{
stream.Write(encoding.GetBytes(json), 0, encoding.GetByteCount(json));
stream.Close();
var response = request.GetResponse();
response.Close();
}
return true;
The API for urbanAirship can be found here:
http://docs.urbanairship.com/reference/api/v3/push.html
And here is an example request..
POST /api/push HTTP/1.1
Authorization: Basic <master authorization string>
Content-Type: application/json
Accept: application/vnd.urbanairship+json; version=3;
{
"audience" : {
"device_token" : "998BAD77A8347EFE7920F5367A4811C4385D526AE42C598A629A73B94EEDBAC8"
},
"notification" : {
"alert" : "Hello!"
},
"device_types" : "all"
}
I've created a c# .Net library for talking to Urban Airship API V3
You can find it here:
https://github.com/JeffGos/urbanairsharp
Hope it helps
Instead of using the header collection (which is throwing an exception) try setting the Accept property on the Request object, e.g. request.Accept = "application/vnd.urbanairship+json; version=3;"
If you still get a 400, try looking in the response body for more details.

What is the C# equivalent of this cURL PUT Request?

I'm trying to do the equivalent of the following in C# ...
curl --request PUT \
--user-agent "Your Client Name/1.0" \
--header "Authorization: Basic YWRtaW46WW91ckFQSUtleUhlcmU=" \
--header "Content-Type: application/xml" \
--data-binary '<order><status_id>10</status_id></order>' \
https://www.example.com/api/v2/orders/101
My effort is giving my a 404 - Bad Request response. I've never looked at curl before.
Anyone out there have any ideas?
var url = String.Format("https://www.website.com/api/v2/orders/{0}", 1647);
var credentials = Convert.ToBase64String(
Encoding.ASCII.GetBytes(String.Format("{0}:{1}", "admin", "mypassword")));
var request = (HttpWebRequest)WebRequest.Create(url);
request.Method = "PUT";
request.Headers.Add(String.Format("Authorization: Basic {0}", credentials));
var status = "<?xml version='\"1.0'\" encoding='\"UTF-8'\"?><order><status_id>2<order><status_Id>";
using (var stream = request.GetRequestStream())
{
using (var writer = new BinaryWriter(stream))
{
writer.Write(status);
}
}
var response = request.GetResponse();
Usually 'Bad request' is because the header is malformed:
look at
<?xml version='\"1.0'\" encoding='\"UTF-8'\"?>
it should be written as follow
<?xml version=\"1.0\" encoding=\"UTF-8\"?>
with no ' or if you want to avoid escapes you could write
<?xml version='1.0' encoding='UTF-8'?>

Categories