JIRA: Basic C#/JIRA connection using REST

As I’m working a lot through JIRA I thought I’d try to communicate with it using C# and the REST api it’s exposing. This was not completely simple and it’s obvious they prefer people using java. There is a library available if you are a java user which simplifies a lot but there is none for C#. I will probably write more than a few articles about the subject as I’ve just installed JIRA on my computer.

The first thing you need to know about communicating with the REST api is that the full api documentation is found here. This will be your bestest friend ever when developing against it.
The second thing you need to know is that they used to have a SOAP api but since 4.something that’s deprecated in favor of the new REST api.

A standard JIRA REST call looks like this:
http://host:port/context/rest/api-name/api-version/resource-name

If you want to try it out you can use an open project on atlassian:
https://jira.atlassian.com/rest/api/latest/issue/JRA-9

The response is given in JSON format which is short and nice and easy to parse using the JSON.NET library. In this first article however we’ll just ensure that we can connect to JIRA and get some data in return.
When we use the open atlassian project in the link above we view the issue as an anonymous user. That takes us only so far so one of the most important parts of the connection is to send the proper credentials. We’ll create a console project which asks the user for a username and password which it uses to fetch all projects available to that user. That’s enough to get one started:

public enum JiraResource
{
    project
}
 
public class JiraManager
{
    private const string m_BaseUrl = "http://localhost.:8080/rest/api/latest/";
    private string m_Username;
    private string m_Password;
 
    public JiraManager(string username, string password)
    {
        m_Username = username;
        m_Password = password;
    }
 
    public void RunQuery(
        JiraResource resource, 
        string argument = null, 
        string data = null,
        string method = "GET")
    {
        string url = string.Format("{0}{1}/", m_BaseUrl, resource.ToString());
 
        if (argument != null)
        {
            url = string.Format("{0}{1}/", url, argument);
        }
 
        HttpWebRequest request = WebRequest.Create(url) as HttpWebRequest;
        request.ContentType = "application/json";
        request.Method = method;
 
        if (data != null)
        {
            using (StreamWriter writer = new StreamWriter(request.GetRequestStream()))
            {
                writer.Write(data);
            }
        }
 
        string base64Credentials = GetEncodedCredentials();
        request.Headers.Add("Authorization", "Basic " + base64Credentials);
 
        HttpWebResponse response = request.GetResponse() as HttpWebResponse;
 
        string result = string.Empty;
        using (StreamReader reader = new StreamReader(response.GetResponseStream()))
        {
            result = reader.ReadToEnd();
        }
 
        Console.WriteLine(result);
    }
 
    private string GetEncodedCredentials()
    {
        string mergedCredentials = string.Format("{0}:{1}", m_Username, m_Password);
        byte[] byteCredentials = UTF8Encoding.UTF8.GetBytes(mergedCredentials);
        return Convert.ToBase64String(byteCredentials);
    }
}

And then we use it in our programs.cs file:

class Program
{
    static void Main(string[] args)
    {
        Console.WriteLine("Hello and welcome to a Jira Example application!");
 
        Console.Write("Username: ");
        string username = Console.ReadLine();
 
        Console.Write("Password: ");
        string password = Console.ReadLine();
 
        JiraManager manager = new JiraManager(username, password);
        manager.RunQuery(JiraResource.project);
 
        Console.Read();
    }
}

The code could do with some refactoring but this is just a simple example. This, if run, should generate something like this (if you log in correctly and have some projects):

A finished connection to Jira

A finished connection to Jira with all Projects for ‘testuser’ showing.

Things to notice in the code:

  • The Authorization header that we use to send our credentials look like this: “Authorization” : “Basic [BASE64 ENCODED CREDENTIALS]“
  • Content-type must be application/json as we send and receive data using the json format
  • The RunQuery method is more generic than required but I’m going to re-use it in future articles. It allows for you to attach data and extra parameters which is sometimes needed
  • The URL goes to localhost. (notice the dot ‘.’ after localhost). This is to make the transaction visible in Fiddler when I monitor the communication

If you need to monitor the communication with Fiddler you have to, as mentioned in the last line above, add a dot after ‘localhost’ in your URL (if you are running on your local computer, otherwise never mind). Open Fiddler2 and monitor the communication and you’ll see something like this:

Communication monitoring in Fiddler

Communication caught in Fiddler, header highlighted in red

Read more in the next article: JIRA: Basic C#/JIRA fetching and displaying projects


28 Responses to JIRA: Basic C#/JIRA connection using REST

  1. Hi Magnus Ferm,

    This is a very nice article.. thanks for it..
    I am very eager to know how to get issues from Jira using the REST API’s.
    Your reply with the code snippet is most awaited.

    Thanks,
    Suhas

  2. Pingback: JIRA: Basic C#/JIRA fetching and displaying projects | Maffelu.net

  3. I’m having trouble using this code to connect to an online Jira domain with authentication.

    I stripped down RunQuery function to a very basic form:

    public void RunSimpleQuery(string method = “GET”)
    {
    string url = m_BaseUrl;

    HttpWebRequest request = WebRequest.Create(url) as HttpWebRequest;
    request.ContentType = “application/json”;
    request.Method = method;

    string base64Credentials = GetEncodedCredentials();
    request.Headers.Add(“Authorization”, “Basic ” + base64Credentials);

    HttpWebResponse response = request.GetResponse() as HttpWebResponse;

    string result = string.Empty;
    using (StreamReader reader = new StreamReader(response.GetResponseStream()))
    {
    result = reader.ReadToEnd();
    }
    Console.WriteLine(result);
    }

    I if comment out the authentication lines and switch the baseURl to: “https://jira.atlassian.com/rest/api/latest/issue/JRA-9″; I can quickly get information, so I know the system works when accessing the web. Using cURL I can access the right domain with my username and password but I can’t get anything to work in C#. My url is:”https://jira.****.com/rest/api/latest/issue/SSI-39″ where **** is the domain I am connecting to. Everytime I try to connect the program waits for about a minute or two and then tells me a WebException was unhandled and that “The operation has timed out”.
    Any thoughts or suggestions?

  4. I set up a trial JIRA server and the code worked. I think I figured out the issue (but not how to fix it yet). The server I am attempting to connect to is https not http so I probably need to configure the connection differently.

  5. Thank you for posting this, was a huge help. I am able to get the JSON return from my JIRA API call writen to the console app, is there an easy way to serialize this to XML and write to a file so it can be ingested by another app that cant read JSON, rather than writing to the console app?

      • Magnus, thank you again, I am a bit lost when it comes to understanding from a structure aspect where within your code would the json.net come into play? at the console.writeline within public void RunQuery(?

  6. Hi Guys,

    I’m new to both C#.NET and JIRA REST. I have been asked to write code for some basic interaction with our JIRA programmatically.
    I tried the code given by Magnus here against our JIRA but am getting the following error:
    The remote server returned an error: (404) Not Found.

    I’m not sure whether RPC is enabled on our server as we don’t have Admin rights. Is there a programmatic way to find whether this is enabled?

    I also tried the stripped-down version from Lnk2128 and was able to run it successfully.

    Can anybody help me with my problem please?

    • Hello JavvyM

      If you are receiving a 404 error then you have entered either the wrong address or you cannot access the JIRA server at the time of testing. You must enable remote API calls, follow this guide to enable it.

      If you have enabled remote API calls and you can reach the JIRA server via the browser from the computer of execution it sounds like you have an error in your address.

      • Hi Magnus,

        Thanks for the reply. Apologies for not responding earlier. Actually, I was asked to work on another module of the product having a higher-priority. Have finished it off and came back to this.

        Saw you reply:
        If you are receiving a 404 error then you have entered either the wrong address or you cannot access the JIRA server at the time of testing. You must enable remote API calls, follow this guide to enable it.
        Unfortunately, the link provided is for Confluence and not JIRA.

        If you have enabled remote API calls and you can reach the JIRA server via the browser from the computer of execution it sounds like you have an error in your address.
        When I give the address like “https:///rest/api/2/issue/” in the browser, the server returns a JSON output. Problem is that when I use the same address in my code, I get a 404 error. Am not sure why this is happens.

        Regards,
        JavvyM

        • Sorry about the link. To enable remote api calls check this guide on how to configure JIRA options: https://confluence.atlassian.com/display/JIRA/Configuring+JIRA+Options. Basically you just change the Accept remote API calls to ON.

          When it comes to your URL problems it is harder for me to help you. If you can reach it and get your expected output in a browser than that is a good step forward. Are you executing your code on the same computer? The URL looks a bit funny and it seems to be executing locally. Are you sure you’re not running your code on another machine? Try using the full address when you make the call.

          • Then I would start by examining whatever exception you are getting when you try to connect. Are there any clues or is it just a generic “cannot connect” error?
            I can’t really help you more than that. If you have connection problems then you need to take a look at how you’ve configured everything etc etc.

            Good luck!

  7. Thanks Magnus. I have been able to figure out the problem. Actually, the issue was with my URL where my code was adding an extra character just before making the web request. And, somehow, I was missing it. Anyway, its working for me now. Thanks a lot. This wouldn’t have been possible without your help.

  8. How can i create our username and password to connection your online URL using this Code. Please reply me as soon as possible. Thanks in Advance!!!

  9. hi I just started with your examples and it works great. do you have any example on how to create a issue by posting JSON to the jira server., Thanks

    • Hello Venki. Unfortunately I don’t have any examples of creating issues with C# but if you get a connection working and you manage to fetch data, which i have written about, I don’t think it should be very hard to figure out how to post data. The documentation is quite good and there are some examples available via google.
      Good luck!

      • Hi magnus, thanks for the reply. I research on some article and tried to post an issue using the below code
        m_BaseUrl = @”http://localhost:8080/rest/api/2/issue”;
        HttpWebRequest request = WebRequest.Create(m_BaseUrl) as HttpWebRequest;
        request.ContentType = “application/json”;
        request.Method = “POST”;

        Dictionary project = new Dictionary();
        project.Add(“key”, “RSAM”);

        Dictionary issuetype = new Dictionary();
        issuetype.Add(“id”, “1″);

        Dictionary key = new Dictionary();
        key.Add(“id”, “10000″);

        Dictionary fields = new Dictionary();
        fields.Add(“project”, key);
        fields.Add(“summary”, “REST EXMAPLE”);
        fields.Add(“description”, “Creating an issue via REST API”);
        fields.Add(“reporter”, “admin”);
        fields.Add(“issuetype”, issuetype);

        Dictionary dict = new Dictionary();
        dict.Add(“fields”, fields);

        JavaScriptSerializer serializer = new JavaScriptSerializer();
        string json = serializer.Serialize((object)dict);

        if (json != null)
        {
        using (StreamWriter writer = new StreamWriter(request.GetRequestStream()))
        {
        writer.Write(json);
        }
        }

        string base64Credentials = GetEncodedCredentials();
        request.Headers.Add(“Authorization”, “Basic ” + base64Credentials);

        HttpWebResponse response = request.GetResponse() as HttpWebResponse;

        string result = string.Empty;
        using (StreamReader reader = new StreamReader(response.GetResponseStream()))
        {
        result = reader.ReadToEnd();
        }

        Console.WriteLine(result);

        it errors out with an exception ” The remote server returned an error: (400) Bad Request.” on the line
        HttpWebResponse response = request.GetResponse() as HttpWebResponse;

        I am not sure on what is going in this.. any idea on this.

        Thanks and regards,
        venki

        • I have solved this.. the issuetype should go as 2 and also the reporter seems to be not supported. I changed the issuetype to 2 and removed the reporter field and it started to work..

Leave a Reply