Soham Dasgupta
Soham Dasgupta

Reputation: 5199

C# VSTS WorkItem related count fields show zero even though I see related links from VSTS web app

I'm trying to pull some information from our VSTS hosted evironment that I need to present as report. What I observed that the API library is reporting there are no related items associated with that WorkItem even though I see related links from the VSTS web app.

Here is my code -

void Main()
{
    string url = "https://[redacted].visualstudio.com";
    string token = "[redacted]";
    string project = "[redacted]";
    string version = "[redacted]";

    VssConnection conn = GetConnection(url, token);
    WorkItemTrackingHttpClient witClient = conn.GetClient<WorkItemTrackingHttpClient>();

    Wiql q = new Wiql();
    q.Query = $"SELECT * FROM WorkItems WHERE [System.TeamProject] = '{project}' AND [System.Tags] CONTAINS '{version}' AND [System.WorkItemType] IN ('Product Backlog Item', 'Defect') ORDER BY [System.CreatedDate] desc";

    var qi = witClient.QueryByWiqlAsync(q).Result;
    var ids = qi.WorkItems.Select(x => x.Id);
    var workitems = witClient.GetWorkItemsAsync(ids).Result.Select(r =>
    {
        return new
        {
            ItemId = r.Id,
            ItemAssignedTo = r.Fields["System.AssignedTo"],
            ItemCreatedBy = r.Fields["System.CreatedBy"],
            ItemTitle = r.Fields["System.Title"],
            ItemType = r.Fields["System.WorkItemType"],
            State = r.Fields["System.State"],
            ItemHasDescription = r.Fields.ContainsKey("System.Description") ? "Yes" : "No",
            ItemHasAcceptanceCriteria = r.Fields.ContainsKey("Microsoft.VSTS.Common.AcceptanceCriteria") ? "Yes" : "No",
            RelatedItems = r.Fields.ContainsKey("System.RelatedLinkCount") ? r.Fields["System.RelatedLinkCount"] : null //This line reports no related links,
            Links = r.Links != null ? r.Links.Links : null //So does this line report null
        };
    });
    workitems.Dump();
    conn.Disconnect();
}

private static VssConnection GetConnection(string accountUri, string personalAccessToken)
{
    var cred = new VssBasicCredential(string.Empty, personalAccessToken);
    VssHttpMessageHandler vssHandler = new VssHttpMessageHandler(cred, VssClientHttpRequestSettings.Default.Clone());
    return new VssConnection(
                        new Uri(accountUri),
                        vssHandler,
                        new DelegatingHandler[] { new SuppressHandler() });
}

public class SuppressHandler : DelegatingHandler
{

}

Also I'm getting these console logging which I'd like to avoid.

Web method running: [https://[redacted].visualstudio.com/_apis/wit/wiql] (POST)wiql[wit]

Is there a way I can remove these console logging?

Upvotes: 1

Views: 1176

Answers (2)

adam.k
adam.k

Reputation: 404

I just had a similar problem, what you have to do is use the WorkItemExpand parameter of GetWorkItemAsync method like below:

var item = client.GetWorkItemAsync(c_projectName, id, null, null, WorkItemExpand.Relations).Result;

If not used the Relations property is null, which is quite misleading. If used it stores the proper information about related work.

Upvotes: 0

Andy Li-MSFT
Andy Li-MSFT

Reputation: 30372

Cannot figure out the problem based on your code.

However you can use below code sample to retrieve the work item information from VSTS, it works on my side:

To avoid getting these console logging, you can disable the Program output :

Right-click in the Output Window --> deselect the option Program output, then try it again.

using Microsoft.TeamFoundation.WorkItemTracking.WebApi;
using Microsoft.TeamFoundation.WorkItemTracking.WebApi.Models;
using Microsoft.VisualStudio.Services.Common;
using System;
using System.Collections.Generic;
using System.Linq;

namespace QueryWorkitems0619
{
    class Program
    {
        static void Main(string[] args)
        {
            Uri uri = new Uri("https://{account}.visualstudio.com");
            string PAT = "TokenHere";
            string project = "ProjectName";

            VssBasicCredential credentials = new VssBasicCredential("", PAT);

            //create a wiql object and build our query
            Wiql wiql = new Wiql()
            {
                Query = "Select * " +
                        "From WorkItems " +
                        "Where [Work Item Type] IN ('Product Backlog Item', 'Task') " +
                        "And [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[3];
                    fields[0] = "System.Id";
                    fields[1] = "System.Title";
                    fields[2] = "System.RelatedLinkCount";

                    //get work items for the ids found in query
                    var workItems = workItemTrackingHttpClient.GetWorkItemsAsync(arr, fields, workItemQueryResult.AsOf).Result;

                    Console.WriteLine("Query Results: {0} items found", workItems.Count);

                    //loop though work items and write to console
                    foreach (var workItem in workItems)
                    {
                        Console.WriteLine("ID:{0} Title:{1}  RelatedLinkCount:{2}", workItem.Id, workItem.Fields["System.Title"], workItem.Fields["System.RelatedLinkCount"]);
                    }

                    Console.ReadLine();
                }
            }
        }
    }
}

enter image description here

Upvotes: 1

Related Questions