Abstract: In my earlier article on “Spawn ‘Tasks’ in response to creation of ‘User Story’” we had seen how to use the Team Foundation Object Model in general and WorkItem Tracking APIs of TFS 2010 in particular.

In my earlier article on “Spawn ‘Tasks’ in response to creation of ‘User Story’” we had seen how to use the Team Foundation Object Model in general and WorkItem Tracking APIs of TFS 2010 in particular. I cannot help in writing the other end of the workflow which was started in that article. We dealt with the creation and linking of workitems in that article. Let us now see how to close the workitems which are linked with parent – child links.

Taking a case which I feel is very interesting one, we will close the child workitems as well as set the state of parent to ‘Resolved’ under certain conditions. It is very natural that if a ‘Requirement’ or ‘User Story’ is dropped due to any reason then the orphaned tasks should also be closed. If they remain in the ‘Active’ state then some work may get done against them without the requirement being present, which is to say the least is waste of efforts. Another perspective to it is if all the ‘Tasks’ which implement a ‘Requirement’ or ‘User Story’ are closed then the parent workitem should reflect the actual state it is in which is ‘Resolved’. These activities can be done manually but that may lead to chance of omission. Not to leave anything to chance, I would like to do these things automatically as soon as some events take place. Now, what is better way of taking action on some events than to create some event handler!

We will implement two workflows in the same event handler since both are to be executed against the same event, ‘WorkItemChanged’. The first workflow is:

·User closes a ‘Task’

·Event handler gets the parent ‘User Story’ of the task – I firmly believe that there should not be any tasks lying around which cannot be linked to a ‘Requirement’ or ‘User Story’.

·Event Handler now gets all the children ‘Tasks’ of this ‘User Story’

·State of these children is checked and if all are closed then state of the parent ‘User Story’ is set to ‘Resolved’

Let us create some code for this in the ‘Notify’ method of the subscribing webservice. We will begin with converting the event related data passed as parameter of the type string into a XML document which can be queried. The XPath Queries that we will make first will filter out all events which do not have ‘Task’ being closed.

Now we will get a collection of all the links from this task to other workitems. Workitems can have links to other workitems as well as to other artefacts. In the earlier versions of TFS we used to work with Linking Service which was not easy to manoeuvre. We now have a link type for workitems and another link type for all other artefacts. We will off course create the collection of workitem links. Once we have that collection then we can go through all the links to find the link to the parent workitem.

We will now create the instance of the parent workitem and get the collection of links from it in turn. These links are to the children which are other tasks for the implementation of parent. We will then go through all of those to check the status of each of them and if we find that status of all of them is set to ‘Closed’ then we will set the status of the parent to ‘Resolved’ and save it.

C#

WorkItem Parent = WIStore.GetWorkItem(ParentLink.TargetId);

WorkItemLinkCollection AllLinksToParent = Parent.WorkItemLinks;

bool AllChildrenWorkItemsClosed = true;

foreach (WorkItemLink child in AllLinksToParent)

{

if (WIStore.GetWorkItem(child.TargetId).State != "Closed")

AllChildrenWorkItemsClosed = false;

}

if (AllChildrenWorkItemsClosed)

{

Parent.State = "Resolved";

Parent.Save();

}

}

VB.NET

Dim Parent As WorkItem = WIStore.GetWorkItem(ParentLink.TargetId)

Dim AllLinksToParent As WorkItemLinkCollection = Parent.WorkItemLinks

Dim AllChildrenWorkItemsClosed AsBoolean = True

ForEach child As WorkItemLink In AllLinksToParent

If WIStore.GetWorkItem(child.TargetId).State <> "Closed" Then

AllChildrenWorkItemsClosed = False

EndIf

Next child

If AllChildrenWorkItemsClosed Then

Parent.State = "Resolved"

Parent.Save()

EndIf

}

After creating code for first workflow let us now work on the second workflow.

·User sets the status of the ‘User Story’ to ‘Closed’, may be because the requirement is dropped or is found to be not a requirement at all.

·Event handler finds out the tasks which were created to implement the ‘User Story’

·Status of all those tasks is set to ‘Closed’

This is a much simpler workflow to implement. We will first filter out all the events where event is not for ‘User Story’ with the status ‘Closed’. Then we will create the instance of Team Foundation Server, WorkItem Store and the workitem of the type ‘User Story’ which is passed in the parameter to the event handler.

Now we will find all the links to children and one by one set the status ofeachof them to ‘Closed’. WorkItemLinkCollection AllLinksToClosingStory = ClosingStory.WorkItemLinks

ForEach link As WorkItemLink In AllLinksToClosingStory

Dim RelatedTask As WorkItem = WIStore.GetWorkItem(link.TargetId)

RelatedTask.State = "Closed"

RelatedTask.Save()

Next link

EndIf

}

Catch ex As Exception

ThisLog.WriteEntry(ex.Message + ex.InnerException.Message)

EndTry

}

That was the skeleton of the code for very interesting two workflows. You may have to flesh in the validations, setting other properties of workitems and error checking etc. but this can be a jumping board for creating your customized applications for the purpose. Some salient points are:

1.Hierarchical workitems and links of different types (Parent – Child, Predecessor – Successor) are a new addition in TFS 2010.

2.In TFS 2010 Beta 1 there is a bug due to which you will need to create code in .NET 2.0 only. An indirectly referenced assembly Microsoft.TeamFoundation.WorkItemTracking.Client.DataStore.dll is incompatible with .NET 4.0 so you have to build and host your webservice in .NET 2.0. This is tricky and takes lots of efforts in Team Suite 2010. Easiest way out that I can suggest is to create the webservice in VS / Team Suite 2008, giving the reference to TFS 2010 assemblies.

3. TFS 2010 assemblies which are needed ( Microsoft.TeamFoundation.Client.dll and Microsoft.TeamFoundation.WorkItemTracking.Client.dll) are now in the C:\Program Files\Microsoft Visual Studio 10\Common7\IDE\RefereceAssemblies and not in the PrivateAssemblies folder.

Subodh is a consultant and corporate trainer. He has overall 28+ years of experience. His specialization is Application Lifecycle Management and Team Foundation Server. He is Microsoft MVP – VS ALM, MCSD – ALM and MCT. He has conducted more than 300 corporate trainings and consulting assignments. He is also a Professional SCRUM Master. He guides teams to become Agile and implement SCRUM. Subodh is authorized by Microsoft to do ALM Assessments on behalf of Microsoft. Follow him on twitter @subodhsohoni

Feedback - Leave us some adulation, criticism and everything in between!