Custom Sorting for Work Items in Team Foundation Server 2008

Posted by Bryon on September 23rd, 2009

TFS provides the WIQ Language (Work Item Query) to query work items.  WIQ is very similar to standard SQL — you have a Select statement to pull back columns of data, a Where clause to filter data, and a Sort By clause.  However, WIQ is much more limited than standard SQL. In particular, advanced sorting logic is not supported.  Thus, you may find yourself needing to implement some type of custom solution to sort your work items.  A recent client had a pretty advanced sorting system in place in their old Mercury TestDirector system (they migrated over to TFS and got rid of TestDirector).  You might need custom sorting if, for example, you need special logic to determine the priority of the defects/bugs.  Developers will work on the queue of defects based on the order of the work items.  Here are your options:

  1. Use WIQ.  As stated above, this option is limited to basic sorting.  You can sort by a single field, or multiple fields.  Conditional logic or advanced grouping is not supported.
  2. Develop a web service triggered by the Work Item Changed event.  By adding a field to the work item definition (perhaps an integer field labeled "SortOrder") you can evaluate the work item to determine what sort order it should be assigned.  In our case, we identified 5 sort levels, so the "SortOrder" field was assigned a number between 1 and 5.  Work Item queries were written to sort based on this field first, then by other fields to secondary sort the work items.

    The web service gets run after you save the work item.  The web service event fires, evaluates the work item, assigns a value to the "SortOrder" field, and then saves the work item.

    Sample code (this uses the TFSEvents framework available at Codeplex):

    public void Notify(string eventXml, string tfsIdentityXml)
        {
            WorkItemChangedEvent workItemChangedEvent = this.CreateInstance<WorkItemChangedEvent>(eventXml);
            TFSIdentity tfsIdentity = this.CreateInstance<TFSIdentity>(tfsIdentityXml);

            int WorkItemID = workItemChangedEvent.CoreFields.IntegerFields[0].NewValue;
            Microsoft.TeamFoundation.Client.TeamFoundationServer TFS = new TeamFoundationServer(tfsIdentity.Url);
            TFS.Authenticate();

            WorkItemStore WIS = TFS.GetService(typeof(WorkItemStore)) as WorkItemStore;
            WorkItem updatedWI = WIS.GetWorkItem(WorkItemID);
            string priority = "";
            string environment = "";

            if (updatedWI.Fields.Contains("CustomFields.SortOrder"))
            {
                priority = updatedWI.Fields["CustomFields.Priority"].Value.ToString();
                environment = updatedWI.Fields["CustomFields.FoundInEnvironment"].Value.ToString();

                if (priority == "1-Now")
                {
                    updatedWI.Fields["CustomFields.SortOrder"].Value = 1;

                }
                else if (priority == "2-ASAP")
                {
                    updatedWI.Fields["CustomFields.SortOrder"].Value = 2;
                }
                else if (updatedWI.Fields["CustomFields.CRID"].Value.ToString() != "" ||
                    (updatedWI.Fields["System.IterationID"].Value.ToString() != "154" &&
                    updatedWI.Fields["System.IterationID"].Value.ToString() != "314"))
                {
                    updatedWI.Fields["CustomFields.SortOrder"].Value = 3;
                }
                else if (environment == "2-PRE-PROD" || environment == "3-Test" || environment == "4-DEVL")
                {
                    updatedWI.Fields["CustomFields.SortOrder"].Value = 4;
                }
                else if (environment == "1-PROD")
                {
                    updatedWI.Fields["CustomFields.SortOrder"].Value = 5;
                }

                if (updatedWI.IsDirty)
                {
                    updatedWI.Save();
                }
            }
        }

    A big disadvantage to this method — the work item gets updated by the web service, thus if a user has the work item loaded on their screen, makes a change, and tried to save, it will fail and notify the user the work item has been updated by another user.  This scenario is very likely to happen since the user will have the work item on their screen during the initial save and may want to add additional data or update information on the work item.  They are forced to close and reopen the work item after each save.  For most organizations, this would be frustrating and probably disqualify this solution.

  3. Develop a client-side custom control.  This option is similar to the web service, but the logic lives on the client.  Using a custom field such as "SortOrder" you can assign a sort value based on the work item information.  The logic runs before the work item is saved, so only one update/save operation is required.  The advantage to this method is you don’t have the update problem as you do with the web service.  The disadvantage is that this control needs to be deployed to all your developer/client machines or else the sort logic won’t run and be assigned.

Based on all these options, the best option if you require advanced sorting logic is to develop a client-side custom control.

  • Share/Bookmark

Dallas VSTS User Group

Posted by Bryon on November 21st, 2008

So I went to the Visual Studio Team System user group meeting a couple nights ago here in Dallas.  It’s actually really great to have a group of smart people here in Dallas that have a lot of expertise and passion about VSTS / Team Foundation Server.  If you are interested in learning more about VSTS, visit http://www.dallasvsts.com/ for meeting times/locations.  The group meetings every month.

Ed Blankenship (VSTS Microsoft MVP) did a presentation on the new October release of Team Foundation Server 2008 Power Tools and the new features coming in VSTS 2010.  The new testing tools coming out with VSTS are really amazing — it’s a huge focus for this release.  VSTS testing tools have always lacked in the UI functional testing area.  The new release includes a tool called Camano (codename) that is specifically designed for testers to easily record UI tests, reports bugs, and save later for regression testing.

  • Share/Bookmark

Copyright © 2010 Bryon Brewer