22 August 2013 HowTo, TFS, WorkItems Robert Muehsig

Nachdem wir schon Build-Informationen und Changesets über die API geholt haben kommen wir nun zu den WorkItems – wobei hiermit alles gemeint ist, was der TFS zu bieten hat: User Stories, Issues etc.

Benötigte Assemblies

Es gibt wieder eine Reihe von Assemblies die man aus dem Installationsverzeichnis (C:\Program Files (x86)\Microsoft Visual Studio 11.0\Common7\IDE\ReferenceAssemblies\v2.0 – für VS 2012) kopieren muss. Eine Besonderheit gibt es noch: Scheinbar ist eine Assembly im GAC höher als in dem Ordner, daher muss man diese Assembly direkt aus dem GAC kopieren, ansonsten kommt es zu einer Exception.

- Microsoft.TeamFoundation.Client.dll
- Microsoft.TeamFoundation.Common.dll
- Microsoft.TeamFoundation.WorkItemTracking.Client.DataStoreLoader.dll
- Microsoft.TeamFoundation.WorkItemTracking.Client.dll
- Microsoft.TeamFoundation.WorkItemTracking.Common.dll
- Microsoft.TeamFoundation.WorkItemTracking.Proxy.dll (diese ist die GAC dll!)

Zusätzlich muss noch “Microsoft.WITDataStore.dll” mit ausgeliefert werden – dies ist allerdings keine .NET Assembly.

Den Fehler habe ich in einem ReadMe im GitHub Projekt näher erklärt – evtl. ist die mit einem späteren Update ohnehin nicht mehr relevant.

Ohne jetzt in diesem Fall genau nachgeschaut zu haben: Im Falle von einer IIS WebApp müsste vermutlich “Enable 32bit Applications” auf true stehen – wie bei den anderen Samples.

Gleich zum Code…

Ziel der Übung soll es sein die WorkItems anzuzeigen, welche sich in den letzten 48 Stunden geändert haben. Für diese WorkItems möchten wir zusätzlich noch die einzelnen Revisions anschauen – also was hat sich genau geändert.

…etwas Konfiguration….

Das Vorgehen hier ist ähnlich wie bei den anderen Beispielen, allerdings nutzt mein Beispiel einen Query der vorher definiert sein muss. Man kann über die API auch direkt einen Query absetzen – dies muss aber in der Work Item Query Language verfasst sein.

Da mir dies zu “kompliziert” war, habe ich den Query über die Webapp erstellt:

image

Code:

Die API ist etwas komplexer, da man erst in den “Query-Folder” wechseln muss (jedenfalls habe ich nichts anderes gefunden – ausser über eine GUID zu gehen, die nirgends angezeigt wird). Mein Query hier liegt und “My Queries” und heisst “New Query 1” im TFS Projekt “Grocerylist”. Man muss den @Project Platzhalter im Code mit dem richtigen Projektnamen ersetzen – mit @Today hat er keine Probleme.

            TfsTeamProjectCollection tfs = new TfsTeamProjectCollection(new Uri("https://code-inside.visualstudio.com/DefaultCollection"));


            // http://stackoverflow.com/questions/10748412/retrieving-work-items-and-their-linked-work-items-in-a-single-query-using-the-tf/10757338#10757338
            var workItemStore = tfs.GetService<WorkItemStore>();

            var project = workItemStore.Projects["Grocerylist"];
            QueryHierarchy queryHierarchy = project.QueryHierarchy;
            var queryFolder = queryHierarchy as QueryFolder;
            QueryItem queryItem = queryFolder["My Queries"];
            queryFolder = queryItem as QueryFolder;

            if (queryFolder != null)
            {
                Dictionary<string, string> variables = new Dictionary<string, string>();
                variables.Add("project", "Grocerylist");

                var myQuery = queryFolder["New Query 1"] as QueryDefinition;
                if (myQuery != null)
                {
                    var wiCollection = workItemStore.Query(myQuery.QueryText, variables);
                    foreach (WorkItem workItem in wiCollection)
                    {
                        Console.WriteLine("WorkItem -----------------------------");
                        Console.WriteLine(workItem.Title);

                        foreach (Revision rev in workItem.Revisions)
                        {
                            Console.WriteLine("  - Revition: " + rev.Index);

                            foreach (Field f in rev.Fields)
                            {
                                if (!Object.Equals(f.Value, f.OriginalValue))
                                {
                                    Console.WriteLine("  - Changes: {0}: {1} -> {2}", f.Name, f.OriginalValue, f.Value);
                                }
                            }
                            Console.WriteLine("  ------------------");

                        }

                    }
                }
            }

Ergebnis:

Der Query lieft mir ein WorkItem zurück und ich iteriere noch über alle Revisions dieses Items. Hier könnte man noch filtern, da ja nicht alle Revisions in den letzten 48 Stunden gemacht wurden, aber das sind Details ;)

Man kann auch recht einfach ausgeben lassen, welche Felder sich geändert haben. Im Grunde merkt man hier recht schnell, warum auch Visual Studio zum Teil in der WorkItem History so viele Einträge drin hat – es wird recht schnell unübersichtlich.

image

Fazit:

Ein klein wenig mehr Arbeit, aber auch dies ging relativ problemlos. Zumindest die Daten lesen ist recht einfach gemacht.

Das Sample ist wie immer in unserem Sample-Repo auf GitHub.


Written by Robert Muehsig

Software Developer - from Dresden, Germany, now living & working in Switzerland. Microsoft MVP & Web Geek.
Other Projects: KnowYourStack.com | ExpensiveMeeting | EinKofferVollerReisen.de

If you like the content and want to support me you could buy me a beer or a coffee via Litecoin or Bitcoin - thanks for reading!