Mister Ben
Mister Ben

Reputation: 33

How do I Get the Children of a DevOps Work Item?

I'm trying to piece together a C# console app that accesses the work items in TFS/DevOps via it's API and compares the original estimate field parent work item with that of all its children and then spits out the name and ID of any work items that do not add up.

So far, I have been able to get back a list of all my work items with the original estimates included, but I still need to get the children of each work item so that I can loop through them and compare the summation of their original estimates with that of their parent. Given how little I know about C# and queries I am pretty stuck right now.

Since linked items are not reportable fields, I have to use $expand to execute a query to get the info I need (at least that's what the doc linked below says). This is where I am stuck. Any tips?

https://learn.microsoft.com/en-us/azure/devops/report/extend-analytics/work-item-links?view=azure-devops

Here is what I have so far.

using System;
using System.Collections.Generic;
using System.Linq;

using Microsoft.TeamFoundation.WorkItemTracking.WebApi;
using Microsoft.TeamFoundation.WorkItemTracking.WebApi.Models;
using Microsoft.VisualStudio.Services.Common;

namespace QueryWorkitems0619
{
    class Program
    {
        static void Main(string[] args)
        {
            string orgName = "{Organization's name}";
            string PAT = "{Personal Access Token}";

            Uri uri = new Uri($"https://dev.azure.com/{orgName}");
            string project = "Wingnit_2";
            VssBasicCredential credentials = new VssBasicCredential("", PAT);
            //create a wiql object and build our query
            Wiql wiql = new Wiql()
            {
                Query = "Select * " +
                "From WorkItems " +
                "Where [System.TeamProject] = '" + project + "' " +
                "And [System.State] <> 'Closed' " +
                "And [System.RelatedLinkCount] > '0'" +
                "Order By [State] Asc, [Changed Date] Desc"
            };
            //create instance of work item tracking http client
            using (WorkItemTrackingHttpClient workItemTrackingHttpClient = new WorkItemTrackingHttpClient(uri, credentials))
            {
                //execute the query to get the list of work items in the results
                WorkItemQueryResult workItemQueryResult = workItemTrackingHttpClient.QueryByWiqlAsync(wiql).Result;
                //some error handling
                if (workItemQueryResult.WorkItems.Count() != 0)
                {
                    //need to get the list of our work item ids and put them into an array
                    List<int> list = new List<int>();
                   
                    foreach (var item in workItemQueryResult.WorkItems)
                    {
                        list.Add(item.Id);
                    }
                    int[] arr = list.ToArray();
                    //build a list of the fields we want to see
                    string[] fields = new string[5];
                    fields[0] = "System.Id";
                    fields[1] = "System.Title";
                    fields[2] = "System.RelatedLinkCount";
                    fields[3] = "System.Description";
                    fields[4] = "Microsoft.VSTS.Scheduling.OriginalEstimate";
                    //get work items for the ids found in query
                    var workItems = workItemTrackingHttpClient.GetWorkItemsAsync(arr, fields, workItemQueryResult.AsOf).Result;
                    //loop though work items and write to console
                    foreach (var workItem in workItems)
                    {
                        foreach (var field in workItem.Fields)
                        {
                            Console.WriteLine("- {0}: {1}", field.Key, field.Value);
                        }
                    }

                    Console.ReadLine();
                }
            }
        }
    }
}

Upvotes: 3

Views: 6081

Answers (1)

Shayki Abramczyk
Shayki Abramczyk

Reputation: 41775

You are in the right direction, you need to add the expand when you execute the GetWorkItemsAsync method:

var workItems = workItemTrackingHttpClient.GetWorkItemsAsync(arr, expand: WorkItemExpand.Relations workItemQueryResult.AsOf).Result;

Note: you can't use fields with expand together, so you need to remove it (you will get all the fields).

Loop the results, inside the work item result you will see Relations, check inside the Relations if the Rel is System.LinkTypes.Hierarchy-Forward, if yes - it's a child:

enter image description here

Now, you have the child id inside the Url, extract it and make an API to get his details.

Upvotes: 1

Related Questions