About the author

J Sawyer is a developer based in Houston, TX and loves to write code, especially ASP.NET and other web-related stuff. He is currently working on implementing Team Foundation Server at a large energy company in Houston and is loving that too.

He also loves to ride his Yamaha FZ1. And sometimes his Ninja 650.

But he doesn't code and ride at the same time. That would be bad.

Exporting Work Items for a Project Template

February 3, 2010 4:33 PM

There comes a time in every TFS implementation where you need to create your own set of default project work items in your template. You can do this straight in the XML by editing workitems.xml in your process template’s Work Item Tracking folder. I said you could, not that you’d actually want to! You can also use the Process Editor to add them one at a time like you do with the Team Foundation client. Uggh. Wouldn’t it be better just to use Excel to put them into a scratch, temporary TF Project? I certainly think so; I can enter work items in Excel a lot faster than I can in the TF Client (or in the Process Editor).

I did some looking about thinking that someone must have solved this already and posted some code, open source, whatever. There was one result that looked promising but … the URL didn’t work (so I’m not posting it here). <Heavy Sigh>

Oh well, time to pop open Visual Studio and start coding …

It turned out that it was pretty easy, in fact. In the sample below, you take a raw work item query (in WIQL) and get the list of work items that you want to export with the columns that you also want to export. The order doesn’t matter. From there, you execute the query against the Work Item Store to get the list of work items. Loop over them and write to XML in the format that the project template uses.

It is, for the most part, really that simple. There are only 2 things that you really have to watch out for. First, the project name should be replaced with a marker for the target project name  ($$PROJECTNAME$$). Second, you need to make sure that the field is applicable to the work item type. This is something that you need to be especially aware of if you have multiple work item types in your default work item set. With all of that … I am proud to present to you … the actual code (exception handling removed for clarity … put yours in!)

public void Export(
    string serverName, string projectName, string filePath, string WIQL)
{
    TeamFoundationServer tfs = TeamFoundationServerFactory.GetServer(
                            serverName, 
                            new UICredentialsProvider() );
    tfs.Authenticate();
    WorkItemStore store = 
        (WorkItemStore)tfs.GetService(typeof(WorkItemStore));
    WorkItemCollection workItems = store.Query(WIQL);
    using (System.IO.Stream output = 
        System.IO.File.Open(filePath, 
            System.IO.FileMode.Create, 
            System.IO.FileAccess.ReadWrite))
    {
        using (XmlWriter writer = XmlWriter.Create(output))
        {
            writer.WriteStartDocument(true);
            writer.WriteStartElement("WORKITEMS");
            WriteWorkItems(projectName, workItems, writer);
            writer.Flush();
            writer.Close();
        }
        
    }
}

private static void WriteWorkItems(string projectName, 
    WorkItemCollection workItems, XmlWriter writer)
{
    for (int i = 0; i < workItems.Count; i++)
    {
        var workItem = workItems[0];
        writer.WriteStartElement("WI");
        writer.WriteAttributeString("type", workItem.Type.Name);
        foreach (FieldDefinition field in workItems.DisplayFields)
        {
            if (workItem.Fields.Contains(field.Name))
            {
                writer.WriteStartElement("FIELD");
                writer.WriteAttributeString("refname", field.ReferenceName);
                writer.WriteAttributeString("value", 
                    workItem.Fields[field.Name].Value.ToString().Replace(
                            projectName, "$$PROJECTNAME$$"));
                writer.WriteEndElement();
            }
        }
        writer.WriteEndElement();
    }
}
In the immortal words of Porky Pig … That’s all folks!

Tags:

TFS