{"id":40791,"date":"2022-05-30T00:17:02","date_gmt":"2022-05-30T07:17:02","guid":{"rendered":"https:\/\/devblogs.microsoft.com\/premier-developer\/?p=40791"},"modified":"2022-05-24T08:37:12","modified_gmt":"2022-05-24T15:37:12","slug":"how-to-batch-importing-azure-devops-work-items-using-azure-devops-apis-and-c","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/premier-developer\/how-to-batch-importing-azure-devops-work-items-using-azure-devops-apis-and-c\/","title":{"rendered":"How To Batch Importing Azure DevOps Work Items Using Azure DevOps APIs and C#"},"content":{"rendered":"<p><a href=\"https:\/\/www.linkedin.com\/in\/kyleljohnson\/\">Kyle Johnson<\/a> and <a href=\"https:\/\/www.linkedin.com\/in\/sash-kavalaparambil-b497539\/\">Sash Kavalaparambil<\/a> explore batch import for Azure DevOps work items using REST APIs.<\/p>\n<hr \/>\n<p>While you can upload a CSV with work items into Azure DevOps, there is so much flexibility you get when you import work items using the <a href=\"https:\/\/docs.microsoft.com\/en-us\/rest\/api\/azure\/devops\">Azure DevOps AP<\/a>I.<\/p>\n<h2>What you need<\/h2>\n<p>You can do this by creating an app registration and using MSAL to authenticate but to keep it simple for this blog post, we will create a Personal Access Token (PAT) then use that PAT token in the code.<\/p>\n<p>Steps to create a PAT token &#8211; <a href=\"https:\/\/docs.microsoft.com\/en-us\/azure\/devops\/organizations\/accounts\/use-personal-access-tokens-to-authenticate?view=azure-devops&amp;tabs=Windows\">Use personal access tokens &#8211; Azure DevOps | Microsoft Docs<\/a><\/p>\n<p>Below is a sample CSV file.<\/p>\n<p><img decoding=\"async\" width=\"938\" height=\"112\" class=\"wp-image-40792\" src=\"https:\/\/devblogs.microsoft.com\/premier-developer\/wp-content\/uploads\/sites\/31\/2022\/05\/word-image-4.png\" srcset=\"https:\/\/devblogs.microsoft.com\/premier-developer\/wp-content\/uploads\/sites\/31\/2022\/05\/word-image-4.png 938w, https:\/\/devblogs.microsoft.com\/premier-developer\/wp-content\/uploads\/sites\/31\/2022\/05\/word-image-4-300x36.png 300w, https:\/\/devblogs.microsoft.com\/premier-developer\/wp-content\/uploads\/sites\/31\/2022\/05\/word-image-4-768x92.png 768w\" sizes=\"(max-width: 938px) 100vw, 938px\" \/><\/p>\n<h2>Now let\u2019s write some code.<\/h2>\n<pre class=\"prettyprint\">string azureDevOpsOrganizationUrl = \"https:\/\/dev.azure.com\/{Organization}\/{Project}\/\";\r\n\r\n        private void ImportWorkItems()\r\n        {\r\n            string[] workItems = File.ReadAllLines(\"&lt;Path to CSV file&gt;\");\r\n\r\n            var personalAccessToken = \"&lt;Azure DevOps PAT token&gt;\";\r\n\r\n            string credentials = Convert.ToBase64String(System.Text.ASCIIEncoding.ASCII.GetBytes(string.Format(\"{0}:{1}\", \"\", personalAccessToken)));\r\n           \r\n            \/\/Just skipping the CSV file header\r\n            foreach (var row in workItems.Skip(1))\r\n            {\r\n                var columns = row.Split(',');\r\n\r\n                var type = columns[0];\r\n                var title = columns[1];\r\n                var description = columns[2];\r\n\r\n\r\n\r\n                using (var client = new HttpClient())\r\n                {\r\n                    client.BaseAddress = new Uri(azureDevOpsOrganizationUrl);\r\n                    client.DefaultRequestHeaders.Accept.Clear();\r\n                    client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue(\"application\/json-patch+json\"));\r\n                    client.DefaultRequestHeaders.Add(\"User-Agent\", \"ManagedClientConsoleAppSample\");\r\n                    client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue(\"Basic\", credentials);\r\n\r\n                    \/\/connect to the REST endpoint\r\n                    string uri = String.Format(\"_apis\/wit\/workitems\/${0}?bypassRules=true&amp;api-version=6.0\", type);\r\n\t\t\t\/\/building JSON request body\r\n                    var jsonstr = \"[{\\\"op\\\": \\\"add\\\", \\\"path\\\": \\\"\/fields\/System.Title\\\",\\\"value\\\": \\\"\" + title + \"\\\" }\";\r\n                    jsonstr += \",{\\\"op\\\": \\\"add\\\", \\\"path\\\": \\\"\/fields\/System.Description\\\",\\\"value\\\": \\\"\" + description + \"\\\" }\";\r\n                    jsonstr += \"]\"; \r\n                    HttpContent body = new StringContent(jsonstr, Encoding.UTF8, \"application\/json-patch+json\");\r\n                    HttpResponseMessage response = client.PostAsync(uri, body).Result;                    \r\n                    \/\/ check to see if we have a successful respond\r\n                    if (response.IsSuccessStatusCode)\r\n                    {\r\n                        ...\r\n                    }\r\n                    else\r\n                    {\r\n                        ...\r\n                    }\r\n                }\r\n            }\r\n        }\r\n<\/pre>\n<p>After running the above code, you should see<\/p>\n<p><img decoding=\"async\" width=\"2618\" height=\"652\" class=\"wp-image-40793\" src=\"https:\/\/devblogs.microsoft.com\/premier-developer\/wp-content\/uploads\/sites\/31\/2022\/05\/graphical-user-interface-text-application-email-5.png\" alt=\"Graphical user interface, text, application, email Description automatically generated\" srcset=\"https:\/\/devblogs.microsoft.com\/premier-developer\/wp-content\/uploads\/sites\/31\/2022\/05\/graphical-user-interface-text-application-email-5.png 2618w, https:\/\/devblogs.microsoft.com\/premier-developer\/wp-content\/uploads\/sites\/31\/2022\/05\/graphical-user-interface-text-application-email-5-300x75.png 300w, https:\/\/devblogs.microsoft.com\/premier-developer\/wp-content\/uploads\/sites\/31\/2022\/05\/graphical-user-interface-text-application-email-5-1024x255.png 1024w, https:\/\/devblogs.microsoft.com\/premier-developer\/wp-content\/uploads\/sites\/31\/2022\/05\/graphical-user-interface-text-application-email-5-768x191.png 768w, https:\/\/devblogs.microsoft.com\/premier-developer\/wp-content\/uploads\/sites\/31\/2022\/05\/graphical-user-interface-text-application-email-5-1536x383.png 1536w, https:\/\/devblogs.microsoft.com\/premier-developer\/wp-content\/uploads\/sites\/31\/2022\/05\/graphical-user-interface-text-application-email-5-2048x510.png 2048w\" sizes=\"(max-width: 2618px) 100vw, 2618px\" \/><\/p>\n<p>Additional Learning:<\/p>\n<p><a href=\"https:\/\/docs.microsoft.com\/en-us\/rest\/api\/azure\/devops\/wit\/work-items\/create?view=azure-devops-rest-6.0\">Work Items &#8211; Create &#8211; REST API (Azure DevOps Work Item Tracking) | Microsoft Docs<\/a><\/p>\n<p><a href=\"https:\/\/docs.microsoft.com\/en-us\/azure\/devops\/integrate\/how-to\/call-rest-api?view=azure-devops\">Get started with the REST APIs for Azure DevOps &#8211; Azure DevOps | Microsoft Docs<\/a><\/p>\n","protected":false},"excerpt":{"rendered":"<p>Kyle Johnson and Sash Kavalaparambil explore batch import for Azure DevOps work items using REST APIs. While you can upload a CSV with work items into Azure DevOps, there is so much flexibility you get when you import work items using the Azure DevOps API. What you need You can do this by creating an [&hellip;]<\/p>\n","protected":false},"author":582,"featured_media":40794,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[22],"tags":[2571,324],"class_list":["post-40791","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-devops","tag-azure-devops","tag-rest"],"acf":[],"blog_post_summary":"<p>Kyle Johnson and Sash Kavalaparambil explore batch import for Azure DevOps work items using REST APIs. While you can upload a CSV with work items into Azure DevOps, there is so much flexibility you get when you import work items using the Azure DevOps API. What you need You can do this by creating an [&hellip;]<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/premier-developer\/wp-json\/wp\/v2\/posts\/40791","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/devblogs.microsoft.com\/premier-developer\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/devblogs.microsoft.com\/premier-developer\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/premier-developer\/wp-json\/wp\/v2\/users\/582"}],"replies":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/premier-developer\/wp-json\/wp\/v2\/comments?post=40791"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/premier-developer\/wp-json\/wp\/v2\/posts\/40791\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/premier-developer\/wp-json\/wp\/v2\/media\/40794"}],"wp:attachment":[{"href":"https:\/\/devblogs.microsoft.com\/premier-developer\/wp-json\/wp\/v2\/media?parent=40791"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/premier-developer\/wp-json\/wp\/v2\/categories?post=40791"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/premier-developer\/wp-json\/wp\/v2\/tags?post=40791"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}