Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

TFS get items with relation and children

I need some help with Microsoft TFS. (Or VSTS, correct me if I'm, wrong)

I want to get, for a given item, all it's relations and children. I'm able to get the relations, but as I understand not the children (for example all the tasks under a given backlog, and all related tasks/bugs etc). Eventually I would like to present a tree (or a graphQL style display with all the relations).

Here is part of my class:

using Microsoft.TeamFoundation.WorkItemTracking.WebApi.Models;
using Microsoft.TeamFoundation.Client;

using Microsoft.VisualStudio.Services.Client;
using Microsoft.VisualStudio.Services.Common;
using Microsoft.VisualStudio.Services.WebApi;

public TfsDataProvider(string tfsInstanceUrl, string tfsCollection)
    {
        TfsInstanceUrl = tfsInstanceUrl.TrimEnd('/');
        TfsCollection = tfsCollection;

        TfsUrlPlusCollection = string.Format("{0}/{1}", tfsInstanceUrl, tfsCollection);

        //tfs nuget packages for API version 3.2:
        creds = new VssCredentials();
        creds.Storage = new VssClientCredentialStorage();

        Uri url = new Uri(TfsUrlPlusCollection); //"http://tfs:8080/tfs/aeronautics-100"

        connection = new VssConnection(url, creds);
        wiClient = connection.GetClient<WorkItemTrackingHttpClient>();

        //tracker = new HashSet<int>();
    }



public List<WorkItem> GetWorkItemsByIds(IEnumerable<int> ids)
{
  var wis = wiClient.GetWorkItemsAsync(ids, null, null, WorkItemExpand.Relations).Result;
  return wis;
}

the code above works and I receive all the items and their relations, then I can get the relations by id and build sort of a tree to display. My problem is that I don't understand how can I get all the children as well.

Currently I want to send this function an array of ids (or 1 id at this time) and recursively get all it's children and relations. It seems that I get only the relations.

I'm using TFS version 2017, and the API version is 3.2.

like image 776
Dima Shivrin Avatar asked Oct 19 '25 17:10

Dima Shivrin


2 Answers

All the linked work items are included in relations, so your code have already get the child work items. The next step is checking the relation type to determine which is related work item and which is child work item.

    foreach (WorkItem wi in wis)
    {
        if (wi.Relations != null)
        {
            foreach (WorkItemRelation wir in wi.Relations)
            {
                Console.WriteLine(wir.Rel);
                Console.WriteLine(wir.Url);
            }
        }
    }

Link Types:

Child:   System.LinkTypes.Hierarchy-Forward
Parent:  System.LinkTypes.Hierarchy-Reverse
Related: System.LinkTypes.Related
like image 68
Eddie Chen - MSFT Avatar answered Oct 22 '25 05:10

Eddie Chen - MSFT


Just get all children work items recursively.

For example:

 private static void GetWorkItemsTest()
        {
           //var creds = new VssCredentials();
           // creds.Storage = new VssClientCredentialStorage();
            VssCredentials c = new VssCredentials(new Microsoft.VisualStudio.Services.Common.VssBasicCredential(string.Empty, "{PAT}"));
            Uri url = new Uri("https://starain.visualstudio.com"); 

           var connection = new VssConnection(url, c);
           var wiClient = connection.GetClient<WorkItemTrackingHttpClient>();
            IEnumerable<int> ids = new List<int> { 851, 180 };
            var wis = wiClient.GetWorkItemsAsync(ids, null, null, WorkItemExpand.Relations).Result;
            foreach (WorkItem wi in wis)
            {
                Console.WriteLine(wi.Id);
                GetChildrenWIT(wiClient, wi, 1,new List<int> { wi.Id.Value});
            }
        }
        private static void GetChildrenWIT(WorkItemTrackingHttpClient witClient, WorkItem child, int width,List<int> existingWit)
        { 
            if (child.Relations != null)
            {
                foreach (WorkItemRelation wir in child.Relations)
                {
                    var indent = new string('-', width);
                    int id = int.Parse(wir.Url.Split('/').Last());
                    if(!existingWit.Contains(id))
                    {
                        Console.WriteLine(string.Format("{0}{1}", indent, wir.Rel));
                        var childwit = witClient.GetWorkItemAsync(id, null, null, WorkItemExpand.Relations).Result;
                        existingWit.Add(childwit.Id.Value);
                        Console.WriteLine(string.Format("{0}-{1}", indent, childwit.Id));
                        GetChildrenWIT(witClient, childwit, width+1, existingWit);
                    }         
                }
            }
        }

The result will be like this:

enter image description here

like image 39
starian chen-MSFT Avatar answered Oct 22 '25 05:10

starian chen-MSFT