Strange issue with multiple calls to the same REST WebClient in PowerShell

Hit a strange problem today trying to do a simple Work Item update via the Azure DevOps REST API.

To do a WI update you need to call the REST API

  • Using the verb PATCH
  • With the Header “Content-Type” set to “application/json-patch+json”
  • Include in the Body the current WI update revision (to make sure you are updating the current version)

So the first step is to get the current WI values to find the current revision.

So my update logic was along the lines of

  1. Create new WebClient with the Header “Content-Type” set to “application/json-patch+json”
  2. Do a Get call to API to get the current work item
  3. Build the update payload with my updated fields and the current revision.
  4. Do a PATCH call to API using the client created in step 1 to update the current work item

Problem was at Step 4 I got a 400 error. A general error, not too helpful

After much debugging I spotted the issue was that after Step 2. my WebClient’s Headers had changed, I had lost the content type – no idea why.

It all started to work if I recreated my WebClient after Step 2, so something like (in PowrShell)

 1Function Get-WebClient
 2
 3{
 4
 5param  
 6(
 7
 8> \[string\]$pat,  
 9> \[string\]$ContentType = "application/json"
10
11)
12
13> $wc = New-Object System.Net.WebClient  
14> $pair = ":${password}"  
15> $bytes = \[System.Text.Encoding\]::ASCII.GetBytes($pair)  
16> $base64 = \[System.Convert\]::ToBase64String($bytes)  
17> $wc.Headers.Add(“Authorization”,"Basic $base64")  
18> $wc.Headers\["Content-Type"\] = $ContentType  
19> $wc
20
21}
22
23  

function Update-WorkItemTitle {

param

(

$baseUri ,
$teamproject,
$workItemID,
$pat,
$title

)

$wc = Get-WebClient -pat $pat -ContentType "application/json-patch+json"
$uri = "$($baseUri)/$teamproject/_apis/wit/workitems/$($workItemID)?api-version=5.1"

# you can only update a work item if you also pass in the rev, this makes sure you are updating lastest version
$jsondata = $wc.DownloadString($uri) | ConvertFrom-Json

$wc = Get-WebClient -pat $pat -ContentType "application/json-patch+json"

$data = @(
@{
            op    = "test";
            path  = "/rev";
            value = $jsondata.Rev
},
@{
            op    = "add";
            path  = "/fields/System.Title";
            value = $title
}
) | ConvertTo-Json

$jsondata = $wc.UploadString($uri, "PATCH", $data) | ConvertFrom-Json
$jsondata

}