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:
- Modify your process templates so that the name of the process template is stored within the project's properties.
- Modify the application so the name of the template is retrieved from the project properties instead of relying on the templateId .
- Modify any existing projects so the name of the process template is stored within the project's properties.
I describe each of these steps below.
Modifying your process templates
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.
Modifying your application
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.
Modifying existing team projects
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.
Its been a little longer than I wanted it to be since I've blogged. Over the past few weeks, I've been trying my best to answer many of your questions related to installing the Connector while also fixing any issues that many of you have reported. By the way, thanks to all who reported issues -- these will only help to improve the experience for everyone that uses the Connector. In an effort to proactively answer several of the questions you may have when installing and configuring the Connector, I've put together the most frequently asked questions. As soon as the codeplex site is updated, I'll include the link to them (as well as answers to them
) here.
So, now that the Connector has been released and more than a few of you have it up and running, you may be asking:
- What's a typical "day in the life" when using the Connector?
- How do I use the Connector Administrative UI?
- What's really happening underneath the covers? How is information passed back and forth?
Over the next few blogs, I will begin to scratch the surface of the Connector and try to explain what it does and how it works. Eventually, I will dive into its depths and walk you through how you can extend and customize the Connector to serve your company's specific needs. For now, let's start at the basics.
After you have successfully installed the Connector, one of the first things you will probably notice is the Connector's Administrative web site. The Home page for the Connector Site shows the projects that have currently been associated such that synchronization can take place. Initially, this should be empty and appear like this:
However, if you see a screen that looks similar to this:
then something is wrong with the way the Connector has been configured. Check the Application Event Log and search for the handlingInstanceId displayed in the error message. This should give you a decent indication of what went wrong. Check out the FAQs mentioned earlier in this blog to see if any of those resolve your issues. More often than not, it is an authorization issue connecting to Project Server.
If you can see the home page as displayed in the first figure, then the next action you'll want to take is to associate a Project Server project and a Team Foundation Server project together. These projects must already exists; that is, the Connector will not create the projects for you. It would not be difficult to extend the Connector so that it could create Project Server projects; however, there is a bit of 'black magic' needed to automatically create TFS projects. Still, if this is a feature that is greatly desired, please let me know -- we could probably get it on the list for the next major release of the Connector.
To create an association between a Project Server project and a TFS project, click the "Create new project association" button. That will take you to a page that looks like this:
The first drop-down box on this page lists all the published projects within Project Server that have not already been associated with a TFS team project. The second drop-down box lists all TFS team projects that have not already been associated with a Project Server project. The check boxes allow different methods for creating the initial associations between the assignments within the Project Server project and the WorkItems within the TFS project. Here is a brief description of each:
| Option | Description |
| Auto-create WorkItems From currently enabled assignments | Creates WorkItems within the TFS team project for all assignments in the Project Server project that have the custom field "AutoSync to External System" marked as "Yes". It will also create an association between the Project Server assignment and the new WorkItem. Selecting this option will unselect the "Manually determine WorkItem-Assignment associations" option. |
| Auto-create assignments from current WorkItems | Creates tasks and assignments within the Project Server project for all active WorkItems within the TFS project. It will also set the custom field "AutoSync to External System" to "Yes" for all new assignments. It will also create an association between the new Project Server assignment and the WorkItem. Selecting this option will unselect the "Manually determine WorkItem-Assignment associations" option. |
| Manually determine WorkItem-Assignment associations | Does not automatically create any new assignments or WorkItems. This option will create an association between the two projects and direct the user to a page where specific assignments and WorkItems can be selected. Selecting this option will unselect and disable both of the previous options. |
Selecting either of the first two options and clicking the Save button will redirect the user back to the home page. The project association should now appear on the page and it will usually be locked so that no modifications can be made to it while it is creating the new assignments/WorkItems and corresponding associations. The following figure shows the home page with a few projects that have been associated and one that is currently in the 'locked' state.
Eventually, the project association should come out of the locked state. The home page is set to automatically refresh every so often to show its state as well as any new WorkItems that may be pending approval (more on that in the next blog). You can change how many seconds the page waits before refreshing by modifying the ProjectListRefreshInterval setting within the Connector Web Site's web.config file:
<setting name="ProjectListRefreshInterval" serializeAs="String">
<value>30</value>
</setting>
Every once in a while, the project association might get 'stuck' in a locked state due to some error that has occurred. I am currently working on a more elegant solution to resolve this; however, for now you can unlock a project association a few different ways. First, check the Application Event Log to ensure that it is truly stuck due to some error. If you see that an error has occurred, you can either unlock it by going to the ProjectsAssociation table in the PS2007ProviderDb database and changing the value for the IsLocked field to false or by finding the ID for the ProjectAssociation (in this same table) and calling the LockProjectAssociation web method in the PS2007ProviderAdministration web service (shown below) with the enableLock parameter set to false. The latter is preferred as any future modifications I make to this process will go through this service. But for now, they just do pretty much the same thing.
Assuming everything works okay and the project association becomes unlocked, you'll see several different options available to you for each project association. You can view any WorkItem changes that are pending approval in order to be sent to Project Server (more on this in the next blog), view the current associations between assignments and WorkItems, delete the project association, or see a hierarchical view of the assignments in Project Server including information about their corresponding Workitems. Let's dive into viewing the assignment associations now. To do this, click the "Details..." link for a project association. It should take you to a page that looks like this:
This page shows you the assignments and WorkItems that are currently associated and affords you the ability to delete this association should you wish. Any changes made to any of these assignments in Project Server (aside from changing the value for 'AutoSync to External System' to No) will automatically be propagated to its corresponding WorkItem in TFS. By default, any changes made to one of this WorkItems in TFS will be marked as pending approval by the Connector Administrator before it is sent to Project Server. You can configure the Connector Web Service to have WorkItems automatically sent to Project Server; i.e., not require approval by the Connector Administrator, by setting approvalNeeded to false in the service's web.config file:
...
<SynchronizationManagerProviders>
<add approvalNeeded="false" workItemWinsConflict="false" tfsServerUri="http://vstsr-epm-tfs:8080"
resourceGroupName="Contributors" pendingQueueDb="ConnectorDb"
...
Clicking the "Create new assignment association" button will take you to a page that allows you to select any WorkItems that are not closed or resolved and are not already associated with an assignment and associate them with any published, unassociated assignment. There are two ways to choose the assignment and WorkItem you want to associate; by WorkItem or by Assignment. When the page is first displayed, it provides the option of having WorkItems drive the process.
The reason that there are two ways to drive how to create an assignment association is that the items that appear in the second drop-down list are filtered according to the WorkItem type for the item selected in the first drop-down list. For example, in the figure above, a WorkItem of type Task is selected in the WorkItem drop-down list. Therefore, the Task drop-down is filtered to only show assignments that equate to having a WorkItem of type Task. Now, you may be wondering, "Project Server does not have the concept of WorkItem Types for assignments; how can the Connector do this?" This is where the Project Server assignment custom fields comes into play -- specifically the Enterprise WorkItem Type custom field. When the Project Server part of the Connector was installed, this custom field was created. If the Enterprise WorkItem type is not set for an assignment, it will default to Task. However, this can be changed by modifying the value just as you would any other custom field within Project. The figure below shows the Task Usage View within MS Project; this view allows for changes at both the Task level as well as the Assignment level. In the figure below there are thirteen assignments -- eight are tasks, two are requirements, and three are bugs:
The mappings between the Enteprise WorkItem Types within Project Server and the TFS WorkItem Types is maintained within the configuration for the Connector Web Service. The snippet below shows the mappings for Bug to Bug, Quality of Service Requirement to Quality of Service Requirement, Requirement to Scenario, and Task to Task for the out of the box MSF Agile process template.
<workItemMappings>
<add processTemplate="MSF for Agile Software Development - v4.0" name="MSF for Agile Software Development - v4.0 Mapping">
<workItemTypeMappings>
<add partnerWorkItemType="Bug" tfsWorkItemType="Bug" name="Bug Mapping">
<fieldMappings>... </fieldMappings>
</add>
<add partnerWorkItemType="Quality Of Service Requirement" tfsWorkItemType="Quality Of Service Requirement" name="QOS Requirement Mapping">
<fieldMappings>...
</fieldMappings>
</add>
<add partnerWorkItemType="Requirement" tfsWorkItemType="Scenario" name="Scenario Mapping">
<fieldMappings>...
</fieldMappings>
</add>
<add partnerWorkItemType="Task" tfsWorkItemType="Task" name="Task Mapping">
<fieldMappings>...
Alternatively, because the engine for the Connector Service just leverages a new application block named the TFS Connector Application Block, this configuration could also be viewed and modified using the Enterprise Library Configuration Tool.
After adding the associations and submitting them, the Connector will redirect to the home page again. From there, you can also view the hierarchy information and respond to WorkItems that are pending approval. And that's where I'll pick up in my next blog...
HTH,
Lenny
Well, we've done it! I have had my head buried deep in the sand for some time now working countless hours on the PS2007-TFS Connector, but I am both happy and relieved to say that we have released it to the public. You can find it at http://www.codeplex.com/pstfsconnector.
Documentation on the Connector is sparse right now. I will be working on revising design documents and text over the next few weeks as I also battle any bugs that arise. However, I thought I would take this opportunity to introduce you to the Connector and provide a brief overview of what it is and how it works. Hopefully, I will whet your appetite to find out more about it. In the blogs that follow this, I will dive deeper into the depths of the Connector.
What is its purpose?
If you just want one sentence to sum up what it does, the Connector synchronizes WorkItems within a TFS Project with Assignments within a PS2007 Project. Of course, there is more involved than that. Resources often need to be created and added to project teams, data needs to be transformed as it moves back and forth, different actions within the WorkItem approval process need to be considered, etc. But in a nutshell, its purpose is to synchronize WorkItems with Assignments.
This capability allows project managers to see, in 'real time' the status of tasks and issues as they are being worked on by developers. Likewise, it allows developers the ability to work with greater agility as assignments are added, removed, or updated by project managers.
How does it work? (Very high level)
The Connector takes advantage of new features within Project Server 2007 that have been built to ease integration with it. Namely, these are the PSI web methods and the ability to extend Project Server 2007 with custom Event Handlers. The PSI methods are used to update information within and read information from Project Server. The Event Handlers are used to send notifications to the Connector when assignments have been created, accepted, and rejected, and projects have been checked in, published, and deleted.
Figure 1 - High-level design of the Connector
Within TFS, a subscription is created for the WorkItemChangedEvent and the Connector is notified when changes occur within associated projects within TFS.
The Connector manages the associations between the WorkItems within TFS and the assignments within Project Server for projects that a user of the Connector has identified. As changes occur within one system, data is transformed such that the other system can readily consume it. The 'magic' really happens in the way the data is mapped and modified as it moves back and forth between systems.
In my next blog, I will walk you through a simple 'day in the life' of a WorkItem (within the Connector).
Hope this helps,
Lenny
I've released a version of the Data Mapping Application Block for EntLib 2.0 on the DMAB gotdotnet workspace. Please check it out and let me know what you think.
What's next?
I have two things planned. One, I plan to upgrade all the code samples the I wrote for EntLib 1.1. up to EntLib 2.0. Secondly, I am working on an artefact generator (AG) for the Data Mapping Block that snaps into Jezz Santos' eFx framework.
If you're not familiar with the work Jezz is doing, you should check it out at his blog.
Well folks, now that the EntLib book is signed, sealed, and delivered, I know longer have a legitimate excuse for not blogging. So this begins my journey into the realm of the blogosphere.
I guess it makes sense to begin this journey by answering questions that some of you have asked me about the book. The most common questions are "where can I get the code" and "why is this book on EntLib 1.1. and not 2.0?"
I'll take the easy one first :-). You can now find the code on this page or at the Addison-Wesley site for the book . Please let me know if you have any questions with the code; I am more than happy to help you out if I can.
Now, the harder question. "Why is the book primarily about EntLib 1.1 when EntLib 2.0 has already been released?" Believe me, this was not an easy decision to make. A primary reason is that it took me a long time to write the book and, as a novice to authoring a book, I had no idea how much more time it takes get a book published than it does to click 'Post' on this blog and have it immediately available. The book was actually complete prior to EL 2.0's release. Still, that is no excuse because I had more than enough notice and information to create a 2.0 book before the release.
The truth is that there are two reasons the book is primarily about EL 1.1. The first is that both I and the publisher believe that there is a need for such a book. I still visit many customers that are still using EL 1.1. Even if they are using .NET 2.0 many customers are still working with the July 2005 version of EntLib. And many still have questions about it. If the book were only on 2.0 then all of these folks would not have the book to use as a reference.
Additionally, many of the concepts behind Enterprise Library have remained the same. The primary purpose for Enterprise Library 2.0 was to align it with the .NET 2.0 framework. Not to redesign. Without question, the primary change between 1.1. and 2.0 is in the way configuration is handled (and thus the inclusion of ObjectBuilder). The patterns that are used in the Enterprise Library blocks still remain primarily the same.
Lastly, to revamp the book for 2.0 would have taken more time. IMO, the book was already long overdue. So, in the end, the publisher and I agreed that the book would not be delayed to incorporate EL 2.0.
Still, I know that there are many who want a 2.0 book to explain how configuration has changed with the introduction of ObjectBuilder and the enhancements in the .NET framework, how the Data Access Application Block and Logging Application Block have been enhanced, and to explain the depracations that have occurred within the Security Application Block. I think the book can be revamped for a second edition that focuses on these changes. It would probably take a couple months of writing (and editing). If you also believe such a revision is valuable, please let me know. It will really come down to whether Addison-Wesley believes there are enough folks out there that would buy such a book to justify the cost of producing it.
Well, I hope that provides some answers to the common questions about the book. I hope this blog will take on a life of its own and I will let it run however you folks gear it. My latest ventures have been deep into the innards of VSTS and TFS so I plan to do some blogging about that (unless you folks would rather hear about other stuff). I'm also (obviously) a HUGE proponent of the p&p artifacts, so I'm always jazzed to talk about those too.