locked
How to remove a single TAG from a Work Item via API RRS feed

  • Question

  • I'm having trouble identifying the method to delete a single, specific TAG from a work item via Rest API.  I've been able to remove ALL tags with the following JSON, unaware of how to do so for a specific tag.  This is a problem when trying to remove only TAG1 when at work item has TAG1, TAG2, TAG3.   Nothing is apparent in the API documentation.

    $json=@"[{"op":"remove","path":"/fields/System.Tags"}]"@

    I'm using the following to make the call to update the work items in a loop, 1 work item at a time.

    $contentTypeJsonPatch="application/json-patch+json"

    $headers=@{Authorization=("Basic {0}"-f$basicAuth)}

    Invoke-RestMethod-Uri"https://$BaseURL/_apis/wit/workitems/$WIID`?api-version=1.0"-MethodPatch-Body$JSON-ContentType$ContentTypeJsonPatch-Headers$Headers

    I attempted to submit the following JSON modified from the ADD Tag code example from the API documentation

    $json=@"

      { "op": "test", "path": "/rev", "value": 6 },

      { "op": "remove", "path": "/fields/System.Tags", "value": "BlockingQA" }

    ]

    "@

    and it returned this error:

    Invoke-RestMethod : {"$id":"1","innerException":null,"message":"Remove requires Value to be null.","typeName":"Microsoft.VisualStudio.Services.Common.VssPropertyValidationException,

    Microsoft.VisualStudio.Services.Common, Version=14.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a","typeKey":"VssPropertyValidationException","errorCode":0,"eventId":3000}

    At line:102 char:21

    +     $RequestResponse = Invoke-RestMethod -Uri "https://$BaseURL/_apis/wit/workitems ...

    +    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

        + CategoryInfo          : InvalidOperation: (System.Net.HttpWebRequest:HttpWebRequest) [Invoke-RestMethod], WebException

        + FullyQualifiedErrorId : WebCmdletWebResponseException,Microsoft.PowerShell.Commands.InvokeRestMethodCommand


    • Edited by Axlmiller Wednesday, April 12, 2017 4:17 AM add'l info
    Tuesday, April 11, 2017 11:25 PM

Answers

  • The approach that you take is the right one. We don't have APIs to add or remove a single tag from a work item.

    Please remember to mark the replies as answers if they help.

    • Marked as answer by Axlmiller Wednesday, April 12, 2017 2:32 PM
    Wednesday, April 12, 2017 2:28 PM

All replies

  • I ended up with this horrific way of doing it, get all work items that have the tag (that I care about) and then one-by-one, loop each work item, get the current tags, replace the one I want removed with a blank string... making sure to account for the tag being the first, last or in the middle of the tags and then updating the work item tags with the updated list of tags.   I hope there is a more direct method out there?

    $WISelectQuery=@{query ="Select [System.Id] From WorkItems Where ([System.WorkItemType] = 'Product Backlog Item' OR [System.WorkItemType] = 'Bug') AND [State] = 'Committed' AND [$TeamKanbanBoardID.Column] = 'QA' AND [$TeamKanbanBoardID.Column.Done] = False AND [System.Tags] Contains 'BlockingQA'"}

       

    $json=ConvertTo-Json($WISelectQuery)

       

    $wiqlResults=Invoke-RestMethod-MethodPost-Headers$Headers-Uri"https://$TeamURL/_apis/wit/wiql?api-version=1.0&expand=relations"-Body$JSON-ContentType$ContentTypeJsonPost-ErrorAction$ErrorActionPreference

       

    $workItems=$wiqlResults.workItems |selectURL


       

    foreach($workItemin$workItems) {

       

           

    $workItemUrl=$workItem.url

           

    $iWorkItem=Invoke-RestMethod-MethodGet-Headers$Headers-Uri"$workItemUrl`?api-version=1.0&expand=relations&fields=id,system.tags"


           

    $updatedTags=$iWorkItem.fields.'System.Tags'.Replace("; BlockingQA","").Replace("BlockingQA; ","").Replace("BlockingQA","")



    $json

    =@"

    [

        {"op":"add","path":"/fields/System.Tags","value":"

    $updatedTags"}

    ]

    "@


           

    $iWorkItemID=$iWorkItem.id.ToString()

           

    $RequestResponse=Invoke-RestMethod-Uri"https://$BaseURL/_apis/wit/workitems/$iWorkItemID`?api-version=1.0"-MethodPatch-Body$json-ContentType$ContentTypeJsonPatch-Headers$Headers-ErrorAction$ErrorActionPreference


        }

    Wednesday, April 12, 2017 5:35 AM
  • The approach that you take is the right one. We don't have APIs to add or remove a single tag from a work item.

    Please remember to mark the replies as answers if they help.

    • Marked as answer by Axlmiller Wednesday, April 12, 2017 2:32 PM
    Wednesday, April 12, 2017 2:28 PM
  • It turns out that you can use Microsoft.TeamFoundation.WorkItemTracking.Client.

    Just pull an existing WorkItem, remove the tag or tags from workItem.Tags collection, and then use workItem.Save();

    This is essentially what I have (I hacked it down for clarity just now, so hopefully it compiles):

        public static void RemoveTag(WorkItem workItem, string tagToRemove)
        {
          string[] tagsArray = workItem.Tags.Split(';', StringSplitOptions.RemoveEmptyEntries);

          workItem.Tags = FormatTagsString(tagsArray.Where(t => t != tagToRemove));

          workItem.Save();
        }

        private static string FormatTagsString(IEnumerable<string> tags)
        {
          return string.Join("; ", tags);
        }

    Friday, June 2, 2017 10:04 PM