如何正确调用 Jira Rest API

How to properly call the Jira Rest API

我一直在尝试设置一个函数来调用带有参数的 Jira Rest API,然后能够在 Jira 中创建问题。为了调用 Rest API,Jira 提供了一个文档,其中描述了如何调用 Rest API here。在网站上,给出了 CURL 和 JSON。这是我尝试在 C#:

中设置的 REST API 请求
curl -D- -u peno.ch:yourpassword -H "Content-Type: application/json" --data @foo.json https://jira-test.ch.*******.net/rest/api/latest/issue/

这是 foo.json 负载:

{
    "fields": {
   "project":
   {
      "key": "FOO"
   },
   "summary": "Test the REST API",
   "issuetype": {
      "name": "Task"
   }
  }
 }

我尝试实现 HttpWebRequest 来调用 Rest API,我也尝试过 WebClient。 None 他们成功了。我有点理解 API 但我认为我的参数不正确,我认为我在那里做错了。同样在 Google 上,我没有找到任何解决方案。

我在执行以下函数时收到来自 Jira 的内部错误。 (没有关于错误的具体信息)

public static void CreateJiraRequest(JiraApiObject jiraApiObject)
{
    string url = "https://jira-test.ch.*******.net/rest/api/latest/issue/";
    string user = "peno.ch";
    string password = "****";

    var client = new WebClient();        
    string data = JsonConvert.SerializeObject(jiraApiObject);
    client.Credentials = new System.Net.NetworkCredential(user, password);
    client.UploadStringTaskAsync(url, data);
}

这是我的 JiraApiObject,它完全转换为上面显示的 Json 负载。

public class JiraApiObject
{
    public class Project
    {
        public string key { get; set; }
    }

    public class Issuetype
    {
        public string name { get; set; }
    }

    public class Fields
    {
        public Project project { get; set; }
        public Issuetype issuetype { get; set; }
        public string summary { get; set; }
    }

    public class RootObject
    {
        public Fields fields { get; set; }
    }
}

当我在控制台上执行 CURL 命令时,一切正常我只是不知道如何构建 WebClientHttpWebRequest.

我发现很多 Jira 用户都面临这个问题,我在互联网上找不到一个好的解决方案。我希望通过提出这个问题找到解决方案并帮助其他有同样问题的人。

一般来说,最好的做法是(很多时候是必要的)当您进行 REST API 调用时,您明确指定内容类型、HTTP 方法等。此外,我更喜欢使用 HttpWebRequest 对象来进行 REST API 调用。这是重构的代码:

public static void CreateJiraRequest(Chat jiraApiObject)
{
    string url = "https://jira-test.ch.*******.net/rest/api/latest/issue/";
    string user = "peno.ch";
    string password = "****";

    var request = (HttpWebRequest)WebRequest.Create(url);
    request.Method = "POST";
    request.ContentType = "application/json";
    request.Credentials = new System.Net.NetworkCredential(user, password);

    string data = JsonConvert.SerializeObject(jiraApiObject);

    using (var webStream = request.GetRequestStream())
    using (var requestWriter = new StreamWriter(webStream, System.Text.Encoding.ASCII))
    {
        requestWriter.Write(data);
    }

    try
    {
        var webResponse = request.GetResponse();
        using (var responseReader = new StreamReader(webResponse.GetResponseStream()))
        {
            string response = responseReader.ReadToEnd();
            // Do what you need to do with the response here.
        }
    }
    catch (Exception ex)
    {
        // Handle your exception here
        throw ex;
    }
}

此外,请确保序列化 JiraApiObject 后的 JSON 结构与相关 API 所需的 JSON 结构相匹配。为方便起见,您可能需要考虑在 类 和属性上使用 JsonObjectJsonProperty 属性,以便按照您的方式命名它们API 期望。

以下是您使用 C# 编写的后端 RESTapi 代码

    public class JiraController : ApiController
    {
        public IJiraInterface repository = new JiraRepository();

        [Route("api/Jira/getTickets")]
        [HttpGet]
        [EnableCors(origins: "http://localhost:8080", headers: "*", methods: "*")]
        public Object getTickets(string startAt,string maxResults)
        {
            return repository.getTickets(startAt,maxResults);
        }

        [Route("api/Jira/createTicket")]
        [HttpPost]
        [EnableCors(origins: "http://localhost:8080", headers: "*", methods: "*")]
        public Object createTicket(IssueModel issueModelObject)
        {
            return repository.createTicket(issueModelObject);
        }
    }

这就是您的界面 class 的外观

public interface IJiraInterface
{
    Object getTickets(string startAt,string maxResults);
    Object createTicket(IssueModel issueObj);
}

这是实体的样子

    public class IssueModel
    {
      #region Properties
      public string RequesterType { get; set; }
      public string Summary { get; set; }
      public string Description { get; set; }
      public string Email { get; set; }
      #endregion
    }

这是您的存储库class

public class JiraRepository : IJiraInterface
{
      public JiraRepository()
      {
      }
      public Object getTickets(string startAt, string maxResults)
      {
        string URL = "https://YOUR_SUB_DOMAIN.atlassian.net/rest/api/3/search?jql=project=PROJECT_NAME"+ 
            "&startAt="+ startAt + 
            "&maxResults=" + maxResults;
        
        HttpWebRequest httpWReq = (HttpWebRequest)WebRequest.Create(URL);
        httpWReq.PreAuthenticate = true;
        httpWReq.Headers.Add("Authorization", "Basic " + getAuthorization());
        httpWReq.Headers.Add("Access-Control-Allow-Origin", "*");
        

        HttpWebResponse response = (HttpWebResponse)httpWReq.GetResponse();
        StreamReader reader = new StreamReader(response.GetResponseStream());
        string responseString = reader.ReadToEnd();
        return JObject.Parse(responseString);
      }
      public Object createTicket(IssueModel issueObj)
      {
        string URL = "https://YOUR_SUB_DOMAIN.atlassian.net/rest/api/3/issue";

        HttpWebRequest httpWReq = (HttpWebRequest)WebRequest.Create(URL);
        httpWReq.ContentType = "application/json";
        httpWReq.PreAuthenticate = true;
        httpWReq.Method = "POST";
        using (var streamWriter = new StreamWriter(httpWReq.GetRequestStream()))
        {
            string json =
            "{\n  \"update\": {},\n  \"properties\" : [\n      {\n          \"key\":\"requestType\",\n          \"value\":\""+ issueObj.RequesterType + "\"\n      }\n  ],\n\n  \"fields\": {\n    \"summary\": \"" + issueObj.Summary + "\",\n    \"issuetype\": {\n      \"id\": \"10203\"\n    },\n    \"project\": {\n      \"id\": \"10512\"\n    },\n  \"description\": {\n      \"type\": \"doc\",\n      \"version\": 1,\n      \"content\": [\n        {\n          \"type\": \"paragraph\",\n          \"content\": [\n            {\n              \"text\": \"" + issueObj.Description + "\",\n              \"type\": \"text\"\n            }\n          ]\n        }\n      ]\n    },\n    \"priority\": {\n      \"id\": \"10000\"\n    }\n  }\n}";
            streamWriter.Write(json);
        }
        httpWReq.Headers.Add("Authorization", "Basic " + getAuthorization());
        httpWReq.Headers.Add("Access-Control-Allow-Origin", "*");

        try
        {
            HttpWebResponse response = (HttpWebResponse)httpWReq.GetResponse();
            StreamReader reader = new StreamReader(response.GetResponseStream());
            string responseString = reader.ReadToEnd();
            return JObject.Parse(responseString);
        }
        catch(Exception e)
        {
            return JObject.Parse(e.Message);
        }

      }
    
      public string getAuthorization()
      {
        var username = "YOUR_JIRA_USERNAME_KEY";
        var password = "YOUR_JIRA_PASSWORD_KEY";
        return Convert.ToBase64String(Encoding.GetEncoding("ISO-8859-1").GetBytes(username + ":" + password));

      } 
}

对于前端通过以下link