Posting tasks to asana through API stopped working - c#

I wrote a program to post tasks to asana through the API and it has been working fine up until this morning, can anyone help me figure out why that is?
this is an example of the JSON string I am sending:
{"workspace":09876543321111,"data": {"assignee":null,"name":"Sample Name","notes":"Sample Noted","due_on":"2015-01-27","projects":"12434567889099","completed":false}}
and I am getting a 400 error: bad request.
this is my code:
string ID = "09876543321111"; //workspace ID
string url = #"https://app.asana.com/api/1.0/workspaces/" + ID + #"/tasks";
Data dat = new Data();
string ProjName = "Test Project";
dat.projects = "1234567890234";
dat.assignee = null;
dat.name = "Sample Name";
dat.notes = "Sample Notes";
dat.due_on = val.requiredBy.Value.ToString("u").Substring(0, 10);
dat.completed = false;
//if task doesnt exist, make one
if (!Tasks.CheckExist(project, dat.projects, dat.name, apiKey, log))
{
string json = JsonConvert.SerializeObject(dat);
string data = "{\"workspace\":" + ID + ",\"data\": " + json + "}";
log.WriteLine(data);
Functions.Post(data, url, apiKey, log);
}
Post function:
//post tasks to asana
public static void Post(string data, string url, string apiKey, StreamWriter log)
{
byte[] bytes = Encoding.UTF8.GetBytes(data);
var req = (HttpWebRequest)WebRequest.Create(url);
req.Method = WebRequestMethods.Http.Post;
req.ContentLength = bytes.Length;
req.ContentType = "application/json";
var authInfo = apiKey + ":";
var encodedAuthInfo = Convert.ToBase64String(
Encoding.Default.GetBytes(authInfo));
req.Headers.Add("Authorization: Basic " + encodedAuthInfo);
req.ContentLength = bytes.Length;
Stream reqStream = req.GetRequestStream();
reqStream.Write(bytes, 0, bytes.Length);
reqStream.Close();
try
{
HttpWebResponse response = (HttpWebResponse)req.GetResponse();
string res = new StreamReader(response.GetResponseStream()).ReadToEnd();
}
catch (WebException ex)
{
HttpWebResponse response = ((HttpWebResponse)ex.Response);
string exc = url + " caused a " + (int)response.StatusCode + " error.\n" + response.StatusDescription;
Console.WriteLine(exc);
log.WriteLine(exc);
}
}
EDIT
for anyone who cares I solved the problem by changing string data to:
string data = "{\"data\": " + json + "}";

We recently made a change to return a 400 error if there were unexpected parameters passed at the top level, as (nearly) all API routes only use the parameters passed in under the "data" attribute. In this case (as you correctly determined) the "workspace" attribute at the top level was incorrect - previously we just ignored it, but in an effort to make the API less "surprising" we wanted to be explicit and strict about parameters that could be ignored, as otherwise it could be misleading.

Related

JSON Post Request In C#

I am a SQL Developer, JSON and C# are completely new to me. I am trying to get the JSON data from Rest API from elastic DB using POST method. I think my code is incorrect since I am getting all the response from the API even though I am passing string json variable in my c# code.
public static string COSMOS(string getAPiurl, string ApiUserId, string ApiPassword)
{
string url = getAPiurl;
HttpWebRequest webrequest = (HttpWebRequest)WebRequest.Create(url);
webrequest.Method = "POST";
webrequest.ContentType = "application/JSON";
webrequest.Accept = "application/JSON";
String username = ApiUserId;
String password = ApiPassword;
String encoded = System.Convert.ToBase64String(System.Text.Encoding.GetEncoding("ISO-8859-1").GetBytes(username + ":" + password));
webrequest.Headers.Add("Authorization", "Basic " + encoded);
using (var streamWriter = new StreamWriter(webrequest.GetRequestStream()))
{
string json = "{\"query\":{\"bool\":{\"should\":[{\"match\":{\"platform\":{\"query\":\"COSMOS\"}}}],\"filter\":" +
"[{\"range\":{\"cu_ticketLastUpdated_date\":{\"gte\":\"2022-05-01 00:00:00\",\"lt\":" +
"\"2022-05-31 23:59:59\"}}}]}}}";
streamWriter.Write(json);
}
var httpResponse = (HttpWebResponse)webrequest.GetResponse();
using (var streamReader = new StreamReader(httpResponse.GetResponseStream()))
{
var rl = streamReader.ReadToEnd();
httpResponse.Close();
}
I am using the above code in my SSIS script component. When I am trying to debug the above code in the var rl I am getting all the response even though I am passing the filters like "filter":[{"range":{"cu_ticketLastUpdated_date":{"gte":"2022-05-01 00:00:00","lt":"2022-05-31 23:59:59"}}
Please help me with an solution.

Can't create workitem via webrequest in RTC

I'm trying to create a .NET web application integration with RTC, where I would insert new workitems using RTC change management services, as defined in this article (specifically in "Create a Change Request"). I was able to get the URL-to-be-used inside services.xml file (/oslc/contexts/_0_iN4G09EeGGMqpyZT5XdQ/workitems/) and my goal is to insert data using JSON.
My code is basically the following:
CookieContainer cookies = new CookieContainer();
HttpWebRequest documentPost = (HttpWebRequest)WebRequest.Create(rtcServerUrl + "/oslc/contexts/_0_iN4G09EeGGMqpyZT5XdQ/workitems/order");//"Order" is the workitem name
documentPost.Method = "POST";
documentPost.CookieContainer = cookies;
documentPost.Accept = "application/json";
documentPost.ContentType = "application/x-oslc-cm-change-request+json";
documentPost.Timeout = TIMEOUT_SERVICO;
string json = "{ \"dc:title\":\"" + title + "\", \"rtc_cm:filedAgainst\": [ { \"rdf:resource\" : \"" + rtcServerUrl + "/resource/itemOid/com.ibm.team.workitem.Category/" + idCategory + "\"} ] }"; //dc:title and rtc_cm:filedAgainst are the only two mandatory data from the workitem I'm trying to create
using (var writer = new StreamWriter(documentPost.GetRequestStream()))
{
writer.Write(json);
writer.Flush();
writer.Close();
}
Encoding encode = System.Text.Encoding.UTF8;
string retorno = null;
//Login
HttpWebRequest formPost = (HttpWebRequest)WebRequest.Create(rtcServerUrl + "/j_security_check");
formPost.Method = "POST";
formPost.Timeout = TIMEOUT_REQUEST;
formPost.CookieContainer = request.CookieContainer;
formPost.Accept = "text/xml";
formPost.ContentType = "application/x-www-form-urlencoded";
String authString = "j_username=" + userName + "&j_password=" + password; //create authentication string
Byte[] outBuffer = System.Text.Encoding.UTF8.GetBytes(authString); //store in byte buffer
formPost.ContentLength = outBuffer.Length;
System.IO.Stream str = formPost.GetRequestStream();
str.Write(outBuffer, 0, outBuffer.Length); //update form
str.Close();
//FormBasedAuth Step2:submit the login form and get the response from the server
HttpWebResponse formResponse = (HttpWebResponse)formPost.GetResponse();
var rtcAuthHeader = formResponse.Headers["X-com-ibm-team-repository-web- auth-msg"];
//check if authentication has failed
if ((rtcAuthHeader != null) && rtcAuthHeader.Equals("authfailed"))
{
//authentication failed. You can write code to handle the authentication failure.
//if (DEBUG) Console.WriteLine("Authentication Failure");
}
else
{
//login successful
HttpWebResponse responseRetorno = (HttpWebResponse)request.GetResponse();
if (responseRetorno.StatusCode != HttpStatusCode.OK)
retorno = responseRetorno.StatusDescription;
else
{
StreamReader reader = new StreamReader(responseRetorno.GetResponseStream());
retorno = "[Response] " + reader.ReadToEnd();
}
responseRetorno.Close();
formResponse.GetResponseStream().Flush();
formResponse.Close();
}
As I was managed to search for in other forums, this should be enough in order to create the workitem (I have a very similar code working to update workitems using "" URL and PUT method). However, instead of create the workitem in RTC and give me some response with item's identifier, the request's response returns a huge JSON file that ends with "oslc_cm:next":"https:///oslc/contexts/_0_iN4G09EeGGMqpyZT5XdQ/workitems/%7B0%7D?oslc_cm.pageSize=50&_resultToken=_AAY50FEkEee1V4u7RUQSjA&_startIndex=50. It's a JSON representation of the XML I receive when I access /oslc/contexts/_0_iN4G09EeGGMqpyZT5XdQ/workitems/ directly from browser, like I was trying to do a simple query inside the workitem's collection (even though I'm using POST, not GET).
I also tried to use PUT method, but then I receive a 405 status code.
Does anyone have an idea of what am I missing here? My approach is wrong, even though with the same approach I'm able to update existing workitem data in RTC?
Thanks in advance.

Problems with PayPal API Http call

I've integrated an option for users to pay via PayPal their online shopping on the web shop that I'm creating. The problem came up suddenly when I started to get this error:
You must write ContentLength bytes to the request stream before calling [Begin]GetResponse.
And the code for the Http call is as following:
public string HttpCall(string NvpRequest)
{
string url = pEndPointURL;
string strPost = NvpRequest + "&" + buildCredentialsNVPString();
strPost = strPost + "&BUTTONSOURCE=" + HttpUtility.UrlEncode(BNCode);
HttpWebRequest objRequest = (HttpWebRequest)WebRequest.Create(url);
objRequest.Timeout = Timeout;
objRequest.Method = "POST";
objRequest.ContentLength = strPost.Length;
try
{
using (StreamWriter myWriter = new StreamWriter(objRequest.GetRequestStream()))
{
myWriter.Write(strPost.ToString());
}
}
catch (Exception e)
{
}
//Retrieve the Response returned from the NVP API call to PayPal.
HttpWebResponse objResponse = (HttpWebResponse)objRequest.GetResponse(); // this is the line where the exception occurs...
string result;
using (StreamReader sr = new StreamReader(objResponse.GetResponseStream()))
{
result = sr.ReadToEnd();
}
return result;
}
Can someone help me out with this? It worked fine a day ago, now its giving me this error?
Okay so if anyone is interested, I was able to fix the error by adding the following line before creating the web request (I was able to fix it by going down to Tls12 like this):
`ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12`;
Cheers :-)
Edit try this:
public string HttpCall(string NvpRequest)
{
string url = pEndPointURL;
string strPost = NvpRequest + "&" + buildCredentialsNVPString();
strPost = strPost + "&BUTTONSOURCE=" + HttpUtility.UrlEncode(BNCode);
ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls;
// Try using Tls11 if it doesnt works for you with Tls
HttpWebRequest objRequest = (HttpWebRequest)WebRequest.Create(url);
objRequest.Timeout = Timeout;
objRequest.Method = WebRequestMethods.Http.Post;
objRequest.ContentLength = strPost.Length;
try
{
using (StreamWriter myWriter = new StreamWriter(objRequest.GetRequestStream()))
{
myWriter.Write(strPost.ToString());
}
}
catch (Exception e)
{
}
//Retrieve the Response returned from the NVP API call to PayPal.
HttpWebResponse objResponse = (HttpWebResponse)objRequest.GetResponse();
string result;
using (StreamReader sr = new StreamReader(objResponse.GetResponseStream()))
{
result = sr.ReadToEnd();
}
return result;
}
public string HttpCall(string NvpRequest) //CallNvpServer
{
string url = pendpointurl;
//To Add the credentials from the profile
string strPost = NvpRequest + "&" + buildCredentialsNVPString();
strPost = strPost + "&BUTTONSOURCE=" + HttpUtility.UrlEncode( BNCode );
HttpWebRequest objRequest = (HttpWebRequest)WebRequest.Create(url);
objRequest.Timeout = Timeout;
objRequest.Method = "POST";
objRequest.ContentLength = strPost.Length;
try
{
using (StreamWriter myWriter = new StreamWriter(objRequest.GetRequestStream()))
{
myWriter.Write(strPost);
}
}
catch (Exception e)
{
/*
if (log.IsFatalEnabled)
{
log.Fatal(e.Message, this);
}*/
}
//Retrieve the Response returned from the NVP API call to PayPal
HttpWebResponse objResponse = (HttpWebResponse)objRequest.GetResponse();
string result;
using (StreamReader sr = new StreamReader(objResponse.GetResponseStream()))
{
result = sr.ReadToEnd();
}
//Logging the response of the transaction
/* if (log.IsInfoEnabled)
{
log.Info("Result :" +
" Elapsed Time : " + (DateTime.Now - startDate).Milliseconds + " ms" +
result);
}
*/
return result;
}
After a number of hours wasted, it turned out to be the Tls protocol version.
ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12;

Post string and bytearray to server

I have done POSTING and GETing from server using string post data, but now i have the next WebService:
submitFeedback(String token, String subject, String body, byte[] photo, byte[] video);
private void PostFeedbackData()
{
if (GS.online != true)
{
MessageBox.Show(GS.translations["ErrorMsg0"]);
}
else
{
HttpWebRequest request = HttpWebRequest.CreateHttp("https://****/feedback");
request.Method = "POST";
request.BeginGetRequestStream(new AsyncCallback(GetRequestStreamCallback), request);
}
}
void GetRequestStreamCallback(IAsyncResult callbackResult)
{
HttpWebRequest myRequest = (HttpWebRequest)callbackResult.AsyncState;
// End the stream request operation
Stream postStream = myRequest.EndGetRequestStream(callbackResult);
// Create the post data
string postData = "";
Deployment.Current.Dispatcher.BeginInvoke(() =>
{
postData = "{\"jsonrpc\": \"2.0\", \"method\": \"getUserSchedule\", \"params\":[" + "\"" + (App.Current as App).UserToken + "\",\"" + FeedbackTitle.Text + "\",\"" + FeedbackContent.Text + "\",\"" + imageBytes + "\"], \"id\": 1}";
byte[] byteArray = Encoding.UTF8.GetBytes(postData);
// Add the post data to the web request
postStream.Write(byteArray, 0, byteArray.Length);
postStream.Close();
// Start the web request
myRequest.BeginGetResponse(new AsyncCallback(GetResponsetStreamCallback), myRequest);
});
}
Look at post data - it is a string, i can't place there imageBytes array. How to do it?
Is there any reason for using HttpWebRequest ?
I am asking that because i think that the correct way of sending files to a service is by multipartform data. With HttpWebRequest you have to manually implement that.
Here is an example that is using Microsoft's HttpClient that might work for you:
public async Task<string> submitFeedback(String token, String subject, String body, byte[] photo, byte[] video) {
var client = new HttpClient();
var content = new MultipartFormDataContent();
// Some APIs do not support quotes in boundary field
foreach (var param in content.Headers.ContentType.Parameters.Where(param => param.Name.Equals("boundary")))
param.Value = param.Value.Replace("\"", String.Empty);
var tok = new StringContent(token);
content.Add(tok, "\"token\"");
var sub = new StringContent(subject);
content.Add(tok, "\"subject\"");
// Add the Photo
var photoContent = new StreamContent(new MemoryStream(photo));
photoContent.Headers.ContentDisposition = new ContentDispositionHeaderValue("form-data")
{
Name = "\"photo\"",
FileName = "\"photoname.jpg\""
};
photoContent.Headers.ContentType = MediaTypeHeaderValue.Parse("image/jpeg");
content.Add(photoContent);
// Add the video
var videoContent = new StreamContent(new MemoryStream(video));
videoContent.Headers.ContentDisposition = new ContentDispositionHeaderValue("form-data")
{
Name = "\"video\"",
FileName = "\"videoname.jpg\""
};
videoContent.Headers.ContentType = MediaTypeHeaderValue.Parse("video/mp4");
content.Add(videoContent);
HttpResponseMessage resp;
try {
resp = await client.PostAsync("SERVER_URL_GOES_HERE", content);
}
catch (Exception e)
{
return "EXCEPTION ERROR";
}
if (resp.StatusCode != HttpStatusCode.OK)
{
return resp.StatusCode.ToString();
}
var reponse = await resp.Content.ReadAsStringAsync();
return reponse;
}
Change accordingly.
Note: HttpClient is also using HttpWebRequest under the hood.
Also I don't think its a good idea to have the UI thread making the request. That makes no sense since you are blocking the interface and making the async theory useless.

$_POST global empty when uploading a file using HttpWebRequest in C#

I have a c# function that is used to upload a file to a PHP web service. The PHP web service is expecting the following
A POST parameter called UploadFileRequestDto containing some XML data
The File stream
For some odd reason the $_POST parameter contains the UploadFileRequestDto only some of the time. If I look at the contents of
file_get_contents("php://input"))
I can see that the request is comming through as expected with the UploadFileRequestDto included.
Doing a
print_r($_REQUEST)
is returning an empty array.
Can anyone help me with a solution to this problem, my C# function is stipulated below
public string UploadFile(UploadFileRequestDto uploadFileRequestDto,string fileToUpload, string fileUploadEndpoint)
{
try
{
var request = (HttpWebRequest)WebRequest.Create(fileUploadEndpoint);
request.ReadWriteTimeout = 1000 * 60 * 10;
request.Timeout = 1000 * 60 * 10;
request.KeepAlive = false;
var boundary = "B0unD-Ary";
request.ContentType = "multipart/form-data; boundary=" + boundary;
request.Method = "POST";
var postData = "--" + boundary + "\r\nContent-Disposition: form-data;";
postData += "name=\"UploadFileRequestDto\"\r\n\r\n";
postData += string.Format("{0}\r\n", SerializeUploadfileRequestDto(uploadFileRequestDto));
postData += "--" + boundary + "\r\n";
postData += "--" + boundary + "\r\nContent-Disposition: form-data;name=\"file\";filename=\"" + Path.GetFileName(fileToUpload) + "\"\r\n";
postData += "Content-Type: multipart/form-data\r\n\r\n";
var byteArray = Encoding.UTF8.GetBytes(postData);
byte[] boundaryBytes = Encoding.ASCII.GetBytes("\r\n--" + boundary + "\r\n");
byte[] filedata = null;
using (var reader = new BinaryReader(File.OpenRead(fileToUpload)))
{
filedata = reader.ReadBytes((int)reader.BaseStream.Length);
}
request.ContentLength = byteArray.Length + filedata.Length + boundaryBytes.Length;
request.GetRequestStream().Write(byteArray, 0, byteArray.Length);
request.GetRequestStream().Write(filedata, 0, filedata.Length);
request.GetRequestStream().Write(boundaryBytes, 0, boundaryBytes.Length);
var response = request.GetResponse();
var data = response.GetResponseStream();
var sReader = new StreamReader(data);
var sResponse = sReader.ReadToEnd();
response.Close();
return sResponse.TrimStart(new char[] { '\r', '\n' });
}
catch (Exception ex)
{
LogProvider.Error(string.Format("OzLib.Infrastructure : WebHelper : public string UploadFile(UploadFileRequestDto uploadFileRequestDto, string fileUploadEndpoint) : Exception = {0}", ex.ToString()));
}
Ok I found the problem, the
post_max_size
setting in the php.ini was set to 8M and some of the files I was trying to upload exeeded 8M. Changed this setting to 16M and restarted the PHP service.
When the file size exeeds the limit that was set the $_POST global is empty.

Categories

Resources