Buck Hodges recently posted a blog that talked about a change that was made to the GetProjectProperties method between TFS 2005 and TFS 2008. To summarize:
In TFS 2005, a templateId was returned as an out parameter of the GetProjectProperties method on the ICommonStructureService interface. This information is no longer stored automatically in TFS 2008. In TFS 2008, the templateId parameter always returns -1.
The short of it is this: if an application, like the Project Server 2007 Connector, relied upon the templateId parameter to get the original process template information for a project, it is going to need to change. Specifically, the following changes will need to be made:
I describe each of these steps below.
In Buck's blog, a suggested workaround for simulating the functionality available with TFS 2005 is to modify your process templates to put the template name in the generic project properties property bag. In the properties element in the classification.xml, you can define name-value pairs to be created at project creation time, e.g.:
<property name="TemplateName" value="MSF Agile v4.0" />
The first step to modifying a process template, is to obtain it. To do this, right-click on the TFS server name in Team Explorer and download it to a location you can work on. The figure below shows how to do this using the Process Template Manager.
Once you have downloaded the process template, you can use your favorite XML editor to modify the classification.xml file per the strategy outlined above. The highlighted line in the figure below demonstrates how I have modified the out of the box Agile template.
Now, use the Process Template Manager to upload the template back to TFS. Once this has been competed, all projects created from this template from this point forward will contain an additional property named templateName.
Now that you can rely on the fact that a property named templateName will exist for a team project, you can use the projectproperties out parameter instead of templateId when calling the GetProjectProperties method on the ICommonStructureService interface. Your code for obtaining the template information used to look something like:
string name = String.Empty; string state = String.Empty int templateId = 0; ProjectProperty[] projectProperties = null; CommonStructureService.GetProjectProperties(projectUri, out name, out state, out templateId, out projectProperties); TemplateHeader[] headers = ProcessTemplates.TemplateHeaders(); List<TemplateHeader> templateHeaders = new List<TemplateHeader>(headers); TemplateHeader template = null; if ((null != templateHeaders) && (templateId > 0)) { template = templateHeaders.Find(delegate(TemplateHeader templateHeader) { return templateHeader.TemplateId == templateId; }); } return template;
Now, you will want to use the projectProperties instead of the templateId. So, the code following the call to GetProjectProperties should be changed to look more like:
List<ProjectProperty> projectPropertiesList = new List<ProjectProperty>(projectProperties); ProjectProperty templateNameProp = projectPropertiesList.Find(delegate(ProjectProperty property) { return property.Name.Equals("templateName"); }); if (null != templateNameProp) { string templateName = templateNameProp.Value; TemplateHeader[] headers = ProcessTemplates.TemplateHeaders(); List<TemplateHeader> templateHeaders = new List<TemplateHeader>(headers); TemplateHeader template = null; if (null != templateHeaders) { template = templateHeaders.Find(delegate(TemplateHeader templateHeader) { return templateHeader.Name.Equals(templateName); }); } } return template;
Now your application will be able to obtain the original process template for which a project was created.
So, now you can obtain template information for any project that was created from a process template modified per the process in the first step. But, what do you do about those projects that already exist? Well, you could create a tool that calls the UpdateProjectProperties method on the ICommonStructureService interface to add the name of the process template to the project properties. I've created such a tool which I will now describe.
When you start the tool, it will prompt you to connect to a TFS Server. You'll see a dialog like that below:
Once you successfully connect, the tool will iterate through the projects on the server and flag which ones do not have a templateName associated with them. If a project is okay, it will have a green flag next to it. Those that are still in need of a templateName property will have a red flag next to them. The figure below shows two projects; the first was created with a modified process template so it includes the templateName property; the second project was not.
Selecting the node a project will show the project properties for that project in he right pane. If the properties do not include a templateName property, then the Add TemplateName button will be enabled. Clicking this button will produce a dialog box from which you can select an existing template. Once selected, the name of the template will be added to the list of project properties for that project.
The changes won't be saved to the server yet. You must click the Apply Changes button to have the changes take effect for that project.
That's all there is to it. Hopefully, this description and tool will allow you to overcome any challenges you may have faced when migrating from TFS 2005 to 2008.