Team Foundation Server 11 has made it even easier to create a work item with a date prior to today. Awesome. So, why would you want to do this? Work with me here …
Maybe you are importing requirements, test cases, or bugs from another tool. Maybe you want to back-fill a Sprint backlog with tasks you were tracking by hand. Maybe you want to create a utility to automatically populate several sprints of work in order to generate and study the burndown and velocity reports. Ok, maybe that last one is just interesting for me as I’m writing my latest book.
Whatever the reason, the approach is not straightforward, so I thought I would share my failures (and ultimate success) with you.
Start here
- Download and install the various Beta products (or download Brian Keller’s VM).
- Start Visual Studio 11 Beta.
- Create a new C# console application (or class library, WPF app, Winforms app, etc.)
- Add assembly references and USING statements for Microsoft.TeamFoundation.Client and Microsoft.TeamFoundation.WorkItemTracking.Client.
Attempt #1: I tried the obvious #FAIL
TfsTeamProjectCollection tpc = new TfsTeamProjectCollection(new Uri(“http://vstfs:8080/tfs/scrum”));
tpc.EnsureAuthenticated();
WorkItemStore store = new WorkItemStore(tpc);
Project tp = store.Projects;
WorkItemType wit = tp.WorkItemTypes;
WorkItem wi = new WorkItem(wit);
wi.Title = “Task 123”;
wi.CreatedDate = DateTime.Parse(“01/01/2012”); // Cannot assign to this field; it is read-only; won’t even build
wi.Save();
Attempt #2: I tried using Fields collection instead #FAIL
TfsTeamProjectCollection tpc = new TfsTeamProjectCollection(new Uri(“http://vstfs:8080/tfs/scrum”));
tpc.EnsureAuthenticated();
WorkItemStore store = new WorkItemStore(tpc);
Project tp = store.Projects;
WorkItemType wit = tp.WorkItemTypes;
WorkItem wi = new WorkItem(wit);
wi.Title = “Task 123”;
wi.Fields.Value = DateTime.Parse(“01/01/2012”); // TF26194: The value for the field ‘Created Date’ cannot be changed
wi.Save();
Attempt #3: I tried using two distinct Save operations #FAIL
TfsTeamProjectCollection tpc = new TfsTeamProjectCollection(new Uri(“http://vstfs:8080/tfs/scrum”));
tpc.EnsureAuthenticated();
WorkItemStore store = new WorkItemStore(tpc);
Project tp = store.Projects;
WorkItemType wit = tp.WorkItemTypes;
WorkItem wi = new WorkItem(wit);
wi.Title = “Task 123”;wi.Save();
wi.Fields.Value = DateTime.Parse(“01/01/2012”);
wi.Save(); // TF237124: Work Item is not ready to save
Attempt #4: I explored the BypassRules flag on the WorkItemStore #FAIL
TfsTeamProjectCollection tpc = new TfsTeamProjectCollection(new Uri(“http://vstfs:8080/tfs/scrum”));
tpc.EnsureAuthenticated();WorkItemStore store = new WorkItemStore(tpc, WorkItemStoreFlags.BypassRules);
Project tp = store.Projects;
WorkItemType wit = tp.WorkItemTypes;
WorkItem wi = new WorkItem(wit);
wi.Title = “Task 123”;wi.Save(); // TF26212: Team Foundation Server could not save your changes.
wi.Fields.Value = DateTime.Parse(“01/01/2012”);
wi.Save();
This was a different error message, so I knew I was getting close. I traded emails with someone on the Visual Studio product group and he walked me in. It turns out that the user (or service account) running the above code must be a member of the Project Collection Service Accounts group. This can be set from either the Team Foundation Server Administration Console or from the web-based control panel. I opted for the web-based control panel and added my user account (Andy) to this group:
Attempt #5: Added user to the Project Collection Service Accounts group #SUCCESS
As you can see, I was able to successfully change the Created Date to 1/1/2012 on the second Save operation. The fact that I had to perform two saves is messy, but I can live with it. I’m told that you can set the System.ChangedDate field this way too, but I’m running into similar blocks. Maybe it’s not working yet in the beta. We’ll see.
Disclaimer: This feature is intended primarily for synchronization and migration tools. These tools should typically be running as a service account in order to bypass the WI rules. I don’t recommend adding an individual user (like I did above) to the Project Collection Service Accounts group except for developing and testing. One option would be to use impersonation (of the service account) when connecting to the TPC.