How to get the next allowed state from the current state programmatically?
Hello,
I am wanting to write some code that will get the allowed transition values (for CoreField.State) for a work item given the current state.
I have tried both getting the WorkItemType and FieldDefinitions.AllowedValues, but this gives me all the AllowedValuesCollection for any state.
I see there is a function, WorkItem.GetNextState(string action), but I don't have any context to what the action is, or can be. Where can I get this information?
Here is a concrete example for the Agile Scenario WorkItemType (assume the scenario is currently in the Active state)...
WorkItemType wit = wi.Type;
FieldDefinition fd = wit.FieldDefinitions[CoreField.State];
foreach (string statein fd.AllowedValues)
Console.WriteLine(state);From this I get all of the states allowed, Active, Closed, Resolved. But you cannot change the state directly to Closed from the Active state.
Thanks in advance!
~Joe
[1566 byte] By [
JoePD] at [2008-2-28]
Here is a C# Console Application:
using Microsoft.TeamFoundation.Client; using Microsoft.TeamFoundation.WorkItemTracking.Client; using System; using System.Collections.Generic; using System.Text; using System.Xml; namespace WorkItemStates { class Program { static void Main(string[] args) { NextAllowedStateExample example = new NextAllowedStateExample(); Console.Write("\nPress any key to close the application."); Console.ReadKey(); } } class NextAllowedStateExample { public string TFSServername = "servername"; public string teamProjectName = "projectname"; private TeamFoundationServer tfs; public NextAllowedStateExample() { // connect to the Team Foundation Server ConnectToTFSServer(); // retrieve the first Work Item WorkItem workItem = GetFirstWorkItem(); // if the Work Item is succesfully retrieved if (workItem != null) { // show the next allowed states for this Work Item ShowAllowedStates(workItem); } } public void ConnectToTFSServer() { Console.WriteLine("Connecting to TFS Server..."); tfs = TeamFoundationServerFactory.GetServer(TFSServername); // authenticate with the current logged in user tfs.Authenticate(); } public WorkItem GetFirstWorkItem() { Console.WriteLine("Retrieving Work Item...\n"); WorkItem retWi = null; WorkItemStore store = (WorkItemStore)tfs.GetService(typeof(WorkItemStore)); // Check if we have any projects if (store.Projects.Count <= 0) return retWi; // Get the proper Team Project Project project = store.Projects[0]; if (project.StoredQueries.Count <= 0) return retWi; // query retrieves all work items for the specified team project string wiqlQuery = "SELECT [System.Id], [System.WorkItemType], [System.State], [System.AssignedTo], [System.Title] FROM WorkItems WHERE [System.TeamProject] = '" + teamProjectName + "' ORDER BY [System.WorkItemType], [System.Id]"; // execute the query and retrieve a collection of workitems WorkItemCollection workitems = store.Projects[0].Store.Query(wiqlQuery); // loop through work items if (workitems.Count > 0) { // select first Work Item retWi = workitems[0]; } return retWi; } public void ShowAllowedStates(WorkItem wi) { WorkItem workItem = wi; // show basic information Console.WriteLine("Select Work Item {0} ({1})", workItem.Id.ToString(), workItem.Title); Console.WriteLine("Current state: {0}", workItem.State); // to find possible next states, the Work Item type definition (XML based format) is used. // get Work Item type WorkItemType wit = workItem.Type; // get Work Item type definition XmlDocument witd = wit.Export(true); // retrieve the transitions node XmlNode transitionsNode = witd.SelectSingleNode("descendant::TRANSITIONS"); // for each transition definition (== possible next allowed state) foreach (XmlNode transitionNode in transitionsNode.SelectNodes("TRANSITION")) { // if the transition contains a next allowed state if (transitionNode.Attributes.GetNamedItem("from").Value == workItem.State) { // show the next allowed state Console.WriteLine("Allowed next state: {0}", transitionNode.Attributes.GetNamedItem("to").Value); // retrieve the reasons node XmlNode reasonsNode = transitionNode.SelectSingleNode("REASONS"); // for each state change reason foreach (XmlNode reason in reasonsNode.ChildNodes) { // show the reason Console.WriteLine("\t(Reason: {0})", reason.Attributes[0].Value); } } } } } } I've found a way to get the next allowed state from the current state using the object model:
public IList<string> GetStatesForState(string currentState) {
WorkItemStore store = (WorkItemStore)_server.GetService(typeof(WorkItemStore));
FieldFilterList filterList = new FieldFilterList();
FieldFilter filter = new FieldFilter(store.Projects[_currentProject].WorkItemTypes["Task"].FieldDefinitions[CoreField.State], currentState);
filterList.Add(filter);
AllowedValuesCollection allowedValues = store.Projects[_currentProject].WorkItemTypes["Task"].FieldDefinitions[CoreField.State].FilteredAllowedValues(filterList);
IList<string> values = new List<string>(allowedValues.Count);
foreach (string value in allowedValues)
{
values.Add(value);
}
return values;
}
However, I haven't found anything similar for getting the reasons for a particular transition. By the moment the only approach I've found is Mathijs' code.