tfsazure-devopsobject-modelazure-devops-rest-api

How can i get all work items across all Team Services accounts?


I'm using the .NET libraries for accessing Visual Studio Team Services and i'm trying to work around a glaring design flaw on Microsoft's part. Apparently you can't have more than one collection per server/account, so i have to use several accounts, which in this example i'll refer to as collections, since Microsoft has even made clear they map to the same thing.

What i'm actually trying to achieve is to have a list with all my work items from all the collections i'm a member of. I have a QueryWorkItems() method that uses GetAllCollections() to get all my collections. That method has been tested and it works, it does return the two accounts i have. The top level method that triggers the whole thing is AssignedWorkItems(). My code is as follows:

        public static List<TfsTeamProjectCollection> GetAllCollections()
        {
            // Get collections/accounts associated with user
            string request = "https://app.vssps.visualstudio.com/_apis/Accounts?memberId=" + versionControl.AuthorizedIdentity.TeamFoundationId + "&api-version=3.2-preview";
            string content = MakeRequestToAPI(request).Result;
            dynamic results = JsonConvert.DeserializeObject<dynamic>(content);
            List<TfsTeamProjectCollection> collections = new List<TfsTeamProjectCollection>();
            // Iterate through all collections
            Parallel.ForEach((IEnumerable<dynamic>)results.value, collection =>
           {
               TfsTeamProjectCollection col = TfsTeamProjectCollectionFactory.GetTeamProjectCollection(new Uri((string)collection.accountUri));
               collections.Add(col);
           });
            return collections;
        }


        public static List<WorkItem> QueryWorkItems(string query)
        {
            List<WorkItem> workItems = new List<WorkItem>();
            List<TfsTeamProjectCollection> collections = GetAllCollections();
            //Parallel.ForEach(collections, collection =>
            foreach(var collection in collections)
            {
                WorkItemCollection items = collection.GetService<WorkItemStore>().Query(query);
                // Add each work item to the overall list
                Parallel.For(0, items.Count, i =>
                {
                    Console.WriteLine(items[i].Title);
                    lock (workItems)
                    {
                        workItems.Add(items[i]);
                    }
                });
            }

            return workItems;
        }

        public static List<WorkItem> AssignedWorkItems()
        {
            Init(); //initializes variables like projectName, workItemStore and VersionControlServer(versionControl)
            string myItems = "select * from issue where [System.AssignedTo]=@me";
            return QueryWorkItems(myItems);
        }

When i call the AssignedWorkItems method i get a login prompt, even though i have a default connection already setup:enter image description here

After i input my credentials though, in this line:

WorkItemCollection items = collection.GetService().Query(query);

i get the following error:

An unhandled exception of type 'Microsoft.TeamFoundation.TeamFoundationServiceUnavailableException' occurred in Microsoft.TeamFoundation.Client.dll

Additional information: TF31002: Unable to connect to this Team Foundation Server: https://xxxxxx.vssps.visualstudio.com/.

Team Foundation Server Url: https://xxxxxx.vssps.visualstudio.com/

Possible reasons for failure include:

  • The name, port number, or protocol for the Team Foundation Server is incorrect.

  • The Team Foundation Server is offline.

  • The password has expired or is incorrect.

Funny thing is everytime i run this the URL mentioned in the error switches back and forth between the two collections i have. Any idea as to why this is happening?


Solution

  • I can test the method QueryWorkItems successfully.

    Based on the error message you got, it seems the VSTS URL stored in collections as the format https://account.vssps.visualstudio.com instead of https://account.visualstudio.com. So please confirm the URLs stored in collections for the method GetAllCollections are correct.

    I used this GetAllCollections method to verify QueryWorkItems:

    public static List<TfsTeamProjectCollection> GetAllCollections()
    {
    
        List<TfsTeamProjectCollection> collections = new List<TfsTeamProjectCollection>();
    
        NetworkCredential cred1 = new NetworkCredential("username for Alternate authentication", "password for Alternate authentication");
        TfsTeamProjectCollection tpc1 = new TfsTeamProjectCollection(new Uri("https://account1.visualstudio.com"), cred1);
    
        collections.Add(tpc1);
    
        NetworkCredential cred2 = new NetworkCredential("username for Alternate authentication", "password for Alternate authentication");
        TfsTeamProjectCollection tpc2 = new TfsTeamProjectCollection(new Uri("https://account2.visualstudio.com"), cred2);
    
        collections.Add(tpc2);
        return collections;
    }