JIRA web request causes issues - c#

I am trying to to extract data from Jira via JIRA REST API from a c# application. to do so I execute this method :
public string RunQuery(JiraRessource resource, string project_id, int startAt, int maxResults, string method = "GET")
{
string url = string.Format(m_BaseUrl);
if (project_id != null)
{
string jql = "search?jql=project=" + project_id;
url = string.Format("{0}{1}", url, jql);
}
string jqr = "&startAt=" + startAt + "&maxResults=" + maxResults;
url = string.Format("{0}{1}", url, jqr);
HttpWebRequest request = WebRequest.Create(url) as HttpWebRequest;
request.ContentType = "application/json";
request.Method = method;
string base64Credentials = GetEncodedCredentials();
request.Headers.Add("Authorization", "Basic " + base64Credentials);
string result = string.Empty;
using (WebResponse response = request.GetResponse())
{
using (StreamReader reader = new StreamReader(response.GetResponseStream()))
{
result = reader.ReadToEnd();
return result;
}
}
}
I execute this method in a loop in order to be able to get all issues after I read that the REST API only gives 50 issues each time. I get errors such as "connection timed out" or "unable to read data from the transport connection". I searched online and all i found is that the connection to the server is lost but I do not know how to solve this.
If anyone knows anything about the reason why I'm getting this error or how to solve it, I will be very thankful.

A few things to try below. If any of these work, it will help you get to the source of the problem.
Try with a request for a small amount of data:
string url = "<your base url>/search?jql=startAt=1&maxResults=1&fields=created";
Try that same url in a web browser (log in to Jira first with the same creds you are using in your C# code)
Try with this code before the call:
System.Net.ServicePointManager.ServerCertificateValidationCallback = delegate (Object obj, X509Certificate X509certificate, X509Chain chain, System.Net.Security.SslPolicyErrors errors)
{
return true;
};
Check the permissions in Jira for the user id you are using for the api call.

Related

Trying to do a GET web requisition but ProtocolViolationException was unhandled [duplicate]

I am new to silverlight. I am programming in Visual Studio 2010 for Windows phone.
I try to do HttpWebRequest but debugger says ProtocolViolationException.
This my code
private void log_Click(object sender, RoutedEventArgs e)
{
//auth thi is my url for request
string auth;
string login = Uri.EscapeUriString(this.login.Text);
string password = Uri.EscapeUriString(this.pass.Password);
auth = "https://api.vk.com/oauth/token";
auth += "?grant_type=password" + "&client_id=*****&client_secret=******&username=" + login + "&password=" + password + "&scope=notify,friends,messages";
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(auth);
request.BeginGetRequestStream(RequestCallBack, request);//on this line debager say ProtocolViolationExceptio
}
void RequestCallBack(IAsyncResult result)
{
HttpWebRequest request = result.AsyncState as HttpWebRequest;
Stream stream = request.EndGetRequestStream(result);
request.BeginGetResponse(ResponceCallBack, request);
}
void ResponceCallBack(IAsyncResult result)
{
HttpWebRequest request = result.AsyncState as HttpWebRequest;
HttpWebResponse response = request.EndGetResponse(result) as HttpWebResponse;
using (StreamReader sr = new StreamReader(response.GetResponseStream()))
{
string a =sr.ReadToEnd();
MessageBox.Show(a);
}
}
I think the problem is that you aren't using POST, but GET. Try this:
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(auth);
request.Method = "POST";
request.BeginGetRequestStream(RequestCallBack, request);
You aren't even doing anything with the request stream when you get it.
HttpWebRequest is assuming that the reason you tried to get it, was to write content to it (the only reason for getting it, after all).
Since you aren't allowed to include content in a GET request, it realises that the only thing you can do with that stream, is something that would violate the HTTP protocol. As a tool for using the HTTP protocol, it's its job to stop you making that mistake.
So it throws ProtocolViolationException.
Cut out the bit about the request stream - it's only for POST and PUT. Go straight to GetResponse() or BeginGetResponse() at that point.

Console application, first webrequest doesn't get response, later does, why?

I am developing console application for API integration. This follow fetching token in first request and then getting report in second request after passing token.
string token = GetToken(app_id); // API call, which is working fine and getting token
string reportquerystring = "path?token=" + token;
WebRequest req = WebRequest.Create(#reportquerystring);
req.Method = "GET";
req.Headers["Authorization"] = "Basic " +
Convert.ToBase64String(Encoding.Default.GetBytes("username:password"));
var resp = req.GetResponse() as HttpWebResponse;
using (Stream downloadstream = resp.GetResponseStream())
{
XmlDocument reportxml = new XmlDocument();
string filename = "location\\";
string reportxmlString = (new StreamReader(downloadstream)).ReadToEnd();
reportxml.LoadXml(reportxmlString);
string json = JsonConvert.SerializeXmlNode(reportxml);
System.IO.File.WriteAllText(filename + "data_" + app_id + ".txt", json);
}
Here when I run this code while debugging, on the first call of download report, response xml is empty, when I drag debugger again before call, in the same run, then it gets response properly. But until and unless I figure out the reason why first call to download report API is not working or how I can make it work, I can not proceed.
Any suggestions ?

JSON post from c# fails with 500 error

I have a c# winforms app in which I'm trying to call into a web service for which I control the code (on both ends). I know the web service is fine because I can call it from jquery with no problems and valid json is returned. But when I call it from c#, I get this error: "The remote server returned an error: (500) Internal Server Error." In the debugger I cannot glean any more details than that.
Here is my c# caller code:
private string GetMemberCheckInData() {
string response = string.Empty;
string fullURL = RootServiceURL + "MemberCheckIn";
var httpWebRequest = (HttpWebRequest) WebRequest.Create(fullURL);
httpWebRequest.ContentType = "text/json";
httpWebRequest.Method = "POST";
using(var streamWriter = new StreamWriter(httpWebRequest.GetRequestStream())) {
string json = "{\"scanCode\":\"" + APIKey + "\"," +
"\"siteID\":\"2\"," +
"\"revenueGroupID\":\"0\"," +
"\"employeeID\":\"12345\"}";;
streamWriter.Write(json);
streamWriter.Flush();
streamWriter.Close();
var httpResponse = (HttpWebResponse) httpWebRequest.GetResponse();
using(var streamReader = new StreamReader(httpResponse.GetResponseStream())) {
response = streamReader.ReadToEnd();
}
}
return response;
}
Here is the literal JSON that is being sent:
{"scanCode":"***8G9V3MA39H0N****","siteID":"2","revenueGroupID":"0","employeeID":"12345"}
Here is the c# web service code (works fine when called from jquery):
[WebMethod]
public void MemberCheckIn(string scanCode, int siteID, int revenueGroupID, int employeeID)
{
...code is never reached...
}
The web service function is never actually entered; I confirmed this with the debugger. When I call it from jquery, I can debug right into it. So it seems the request is being rejected by the .net runtime or IIS or something.
Any ideas what I am doing wrong?
Your webmethod is expecting you to pass parameters in to it.
string fullURL = RootServiceUrl + "MemberCheckIn?scanCode=X&siteID=1...etc.

About: get REST - returning a NotFound exception C#

Attempting to retrieve quota information from Google Drive via REST in C#. Here is a code snippet:
public async Task<string> HasQuota(string accessToken) {
var url = string.Concat(new string[] {
" https://www.googleapis.com/drive/v2/about",
"?access_token=" + accessToken,
"&fields=quotaBytesTotal%2CquotaBytesUsed"
});
// Create the request.
var request = WebRequest.Create(url) as HttpWebRequest;
request.Method = "GET";
// Create the response.
var response = await Task<WebResponse>.Factory.FromAsync(
request.BeginGetResponse,
request.EndGetResponse,
request
);
if (((HttpWebResponse)response).StatusDescription == "OK") {
using (Stream stream = response.GetResponseStream()) {
StreamReader reader = new StreamReader(stream, Encoding.UTF8);
return reader.ReadToEnd();
}
}
return null;
}
When I obtained the access_token I scoped the authentication request with https://www.googleapis.com/auth/drive.file and my test user granted permissions. So as far as I aware I have the code requirements to execute this call.
However I get an NotFound exception when I attempt to execute this method. The documentation says I can pass the access_token in the query string or add the Authorization header to the request i.e
request.Headers["Authorization"] = string.Format("Bearer {0}", accessToken);
Any ideas why I might be getting this exception?
Thanks
I hadn't enabled the Drive API option in the console...

Harvest (timecard app) API

Harvest is the time tracking application that I use at my job. While the web UI is quite simple, there are a few custom features I would like to add. I noticed they have an API... So I want to make a custom desktop client in C# for it.
Just looking at the page, its not very informative. The C# sample that you can find (after doing some digging) doesn't help much either. So... How in the world do I use the API with C#?
Link to API page
Any help would be greatly appreciated :)
Harvest is using a REST API, so what is does is you do a get/put/post request to a web address on the server and it will return a result (usually formatted in XML or JSON (appears to be XML in this case)). A quick Google search returned this tutorial on how to use a REST API, hopefully that will be enough for what you need. If not, feel free to ask us about specific problems you are having using REST and C#
Here I will try to add some more comments to their sample:
using System;
using System.Net;
using System.IO;
using System.Text;
using System.Security.Cryptography.X509Certificates;
using System.Net.Security;
class HarvestSample
{
//This is used to validate the certificate the server gives you,
//it allays assumes the cert is valid.
public static bool Validator (object sender, X509Certificate certificate,
X509Chain chain, SslPolicyErrors sslPolicyErrors)
{
return true;
}
static void Main(string[] args)
{
//setting up the initial request.
HttpWebRequest request;
HttpWebResponse response = null;
StreamReader reader;
StringBuilder sbSource;
//1. Set some variables specific to your account.
//This is the URL that you will be doing your REST call against.
//Think of it as a function in normal library.
string uri = "https://yoursubdomain.harvestapp.com/projects";
string username="youremail#somewhere.com";
string password="yourharvestpassword";
string usernamePassword = username + ":" + password;
//This checks the SSL cert that the server will give us,
//the function is above this one.
ServicePointManager.ServerCertificateValidationCallback = Validator;
try
{
//more setup of the connection
request = WebRequest.Create(uri) as HttpWebRequest;
request.MaximumAutomaticRedirections = 1;
request.AllowAutoRedirect = true;
//2. It's important that both the Accept and ContentType headers
//are set in order for this to be interpreted as an API request.
request.Accept = "application/xml";
request.ContentType = "application/xml";
request.UserAgent = "harvest_api_sample.cs";
//3. Add the Basic Authentication header with username/password string.
request.Headers.Add("Authorization", "Basic " + Convert.
ToBase64String(new ASCIIEncoding().GetBytes(usernamePassword)));
//actually perform the GET request
using (response = request.GetResponse() as HttpWebResponse)
{
//Parse out the XML it returned.
if (request.HaveResponse == true && response != null)
{
reader = new StreamReader(response.GetResponseStream(),
Encoding.UTF8);
sbSource = new StringBuilder(reader.ReadToEnd());
//4. Print out the XML of all projects for this account.
Console.WriteLine(sbSource.ToString());
}
}
}
catch (WebException wex)
{
if (wex.Response != null)
{
using (HttpWebResponse errorResponse = (HttpWebResponse)wex.Response)
{
Console.WriteLine(
"The server returned '{0}' with the status code {1} ({2:d}).",
errorResponse.StatusDescription, errorResponse.StatusCode,
errorResponse.StatusCode);
}
}
else
{
Console.WriteLine( wex);
}
}
finally
{
if (response != null) { response.Close(); }
}
}
}
I've also struggled with their API. Scott's answer is very useful.
Anyway there is a very useful and easy library which is called EasyHttp witch you can find in NuGet.
here is the same method as Scott's but much shorter :):
public static string getProjects()
{
string uri = "https://<companyname>.harvestapp.com/projects";
HttpClient http = new HttpClient();
//Http Header
http.Request.Accept = HttpContentTypes.ApplicationJson;
http.Request.ContentType = HttpContentTypes.ApplicationJson;
http.Request.SetBasicAuthentication(username, password);
http.Request.ForceBasicAuth = true;
HttpResponse response = http.Get(uri);
return response.RawText;
}
If you want to learn more about WebApi calls you can use Fidler or a more easier and RestClient which is a Firefox plugin.
With RestClient you can talk to rest servers directly, very helpful if you want to understand RESTful services.

Categories