Retrieve Work Item Discussion History using Visual Studio Online's REST API

Published on
Reading time

At TechEd North America Microsoft announced the availability of a preview REST API for Visual Studio Online.  Anyone who has spent time around Team Foundation Server will know that it's always had a strongly-typed C# SDK which can be used to extract and manipulate work items held in TFS.  This REST API is new and will eventually be available for the on-premise hosted version of TFS.

In a lucky coincidence I'm doing some work that requires me to extract work item information for other purposes so I decided to give the API a whirl.  As you can see it went pretty well!

Strictly speaking, it isn't a complete Work Item as by default Attachments and History are both excluded.  Interestingly both of these tend to be pain points for other traditional tools to deal with too 🙂.

Luckily the new REST API offers support for retrieval of "Updates" which represent the set of fields changed on each update to the Work Item.  This can be any combination of fields or comments directly added to the history by users.

The demo code below shows how you can build out the history so it displays "Discussion Only" items and excludes all others.  As it's early days for the API maybe we'll see the sort of logic covered here wrapped in an API call so you don't need to parse these objects locally.

Once the entire solution is ready I'll post the source up on Github.  Note you'll need to enable the "Alternate Credentials" on your user profile to get this code working.

// utilising RestSharp and Json.NET - get via Nuget.

private WorkItem GetWorkItem(string workItemIdentifier)
  var restClient = new RestClient("");
  restClient.Authenticator = new HttpBasicAuthenticator("username", "password");

  // code removed here

  var changes = GetWorkItemHistoryComments(restClient, workItemIdentifier);

  // code removed here

private IEnumerable<WorkItemCommentChange> GetWorkItemHistoryComments(RestClient activeClient, string workItemIdentifier)
  var request = new RestRequest("/_apis/wit/workitems/{id}/updates");
  request.AddParameter("api-version", "1.0-preview");
  request.AddUrlSegment("id", workItemIdentifier);

  var response = activeClient.Execute(request);

  dynamic json = JObject.Parse(response.Content);

  var changes = new List<WorkItemCommentChange>();

  string revisionDate = string.Empty;
  string revisedBy = string.Empty;
  string comments = string.Empty;

  // each one of these represents a revision
  foreach(var val in json.value)
    // a revision contains multiple fields
    foreach(var ufield in val.fields)
      if ( == -4) // System.ChangedDate
        revisionDate = ufield.updatedValue; // "02/01/2014 01:21:00" (MM/dd/yyyy and UTC)

      if ( == 9) // System.ChangedBy
        revisedBy = ufield.updatedValue; // "Simon Waight"

      if( == 54) // System.History
        comments = ufield.updatedValue; // can be plain text or HTML
    // we only care about comments
      changes.Add(new WorkItemCommentChange
                      ChangeDate = DateTime.ParseExact(revisionDate,
                        "MM/dd/yyyy HH:mm:ss",
                        DateTimeStyles.AssumeUniversal | DateTimeStyles.AdjustToUniversal),
                      ChangedBy = revisedBy,
                      CommentText = comments
      comments = revisedBy = revisionDate = string.Empty;
  return changes;

public class WorkItemCommentChange
  public DateTime ChangeDate { get; set; }
  public string ChangedBy { get; set; }
  public string CommentText { get; set; }