Inserting Work Items using the TFS WorkItemServer Service

I needed to insert a Work Item into TFS at a specific state, rather than following the predefined state transitions.  Well, not just one work item, but thousands of them, since I’m working on migrating items from another system which is not yet supported by the TFS Integration Tools.  I had to write some custom migration code to get this done.  The TFS API does not allow you to bypass the rules specified by the Work Item Type Definition (rightly so), so I could approach this two different ways:

  • Insert all work items with the initial pre-configured state, and then update it multiple times until I get to the desired state.  This would’ve worked but it would also created unnecessary noise in history.
  • Call the TFS Web Service directly, which allows you to set a “BypassRules” value and it does exactly what it says: it bypasses WITD rules (not all, as you still need things like title, created by, etc).

I went with option 2.  Now, I don’t recommend that you do this unless you absolutely have to for a few very valid reasons:

  • These services are not documented by Microsoft
  • Microsoft reserves the right to change these web services on any future version of TFS. 
  • If you get an error from the web service, you’ll need to decipher it yourself. Some errors are easier to figure out, such as “The System.AreaID field must contain an integer greater than zero”.  But errors such as “Forcing rollback —> Forcing rollback —> Forcing rollback” will leave you digging through code for a while.

So, on to the code…

First, you need to reference Microsoft.TeamFoundation.WorkItemTracking.Proxy and Microsoft.TeamFoundation.Client.

Then you connect to your TFS Collection and then the WorkItemServer service:

   1:  TfsTeamProjectCollection collection = new TfsTeamProjectCollection(new Uri("http://TFSServer:8080/tfs/DefaultCollection"));
   2:  WorkItemServer svc = collection.GetService(typeof(WorkItemServer)) as WorkItemServer;

The service has a few methods, but the only one that you need to be concerned with is the “Update” method.  It deals with an XML package, which contains all the work item data that you are looking to insert.  This same method can also be used for updates (obvious, based on the name).

The XML package should look something like this:

   1:  <Package>
   2:      <InsertWorkItem ObjectType='WorkItem' BypassRules='1'>
   3:          <Columns>
   4:              <Column Column='System.AreaID' Type='Number'><Value>8Value>Column>
   5:              <Column Column='System.IterationID' Type='Number'><Value>12Value>Column>
   6:              <Column Column='System.WorkItemType' Type='String'><Value>BugValue>Column>
   7:              <Column Column='System.Title' Type='String'><Value>Your bugValue>Column>
   8:              <Column Column='System.State' Type='String'><Value>FixedValue>Column>
   9:              <Column Column='System.Reason' Type='String'><Value>MigratedValue>Column>
  10:              <Column Column='System.CreatedDate' Type='ServerDateTime'>Column>
  11:              <Column Column='System.CreatedBy' Type='String'><Value>Automated ProcessValue>Column>
  12:          Columns>
  13:          <InsertText FieldName='System.History' FieldDisplayName='History'>NOTE: This item was migratedInsertText>     
  14:      InsertWorkItem>
  15:  Package>

Something interesting to point out is that “InsertText” element.  If you want to add a comment to the history record for the insert, that’s how you should go about doing it.

The signature for the Update service method is:

public void Update(string requestId, XmlElement package, out XmlElement result, MetadataTableHaveEntry[] metadataHave, out string dbStamp, out IMetadataRowSets metadata);

This will get you your requesID: WorkItemServer.NewRequestId(). 

And you can retrieve your new work item ID from result.FirstChild.Attributes[“ID”].Value;

I hope this helps someone!

About esteban

Esteban is the Founder and Chief Technologist at Nebbia Technology, an ALM consulting and Azure-powered technology company. He is a software developer with a passion for ALM, TFS, Azure, and software development best practices. Esteban is a Microsoft Visual Studio ALM MVP and ALM Ranger, Pluralsight author, and the president of ONETUG (Orlando .NET User Group).

5 thoughts on “TFS 2010 Dashboards with SharePoint 2010 (MOSS)

  1. Jose Medero

    Hi Esteban, i am working on integrating my company’s TFS 2010 with a SharePoint 2010 portal. I have been looking that several blogs shows that when the configuration is done they get several dashboards. In my case the only dashboard that was created was “My Dashboard”. Wath do I need to get other dashboards like the ones mentioned in your article.

    I am working on a sharepoint 2010 farm single server test enviroment with my production TFS 2010. My configuration goes as follows:
    – TFS 2010 Standard
    – SharePoint 2010 Enterprise
    – Sql 2008 r2 Enterprise with Report Server in Integrated Mode.
    – SP has been integrated with reporting services.

  2. Esteban Garcia

    Do you see any errors in the Team Project creation log? I seem to remember running into this before, and I think it had to do with permissions during the creation of the Team Project, but I may be mistaken. Can you take a look at your log file and let me know?

  3. Bob Cronin

    I know this is an old post Esteban, but it saved me today. Thanks for publishing!

  4. Anurag Jain

    Hi Esteban, Thanks for this nice explanation, But i do have some other requirement.
    Lest say if we have WorkItemLinkFilters LinkType=”System.LinkTypes.Hierarchy” then WorkItemTypeFilters should be “Task” and if we have WorkItemLinkFilters LinkType=”System.LinkTypes.Hierarchy” then WorkItemTypeFilters should be “child” only. Is it possible to achieve ?

  5. Sankar

    This is working fine for active users.. How can I remove inactive user from Team Foundation Service Accounts using this command?

Leave a Reply

Your email address will not be published. Required fields are marked *

Are you human? *