If you have used links in work item tracking, you might have wondered if you could add your own link type. In V1 we do have linking extensibility model and the purpose of post is to walkthrough how to use it. Example of custom link could be a link to items in other products, documents, test cases stored in other systems, workitems themselves with different meaning etc and there are many possibilities. Below is screenshot of how the dialog with customlink will look like when someone clicks “Add” from link from links control:
I attached a sample in this post to demo this.
How Linking Extensibility works at high level:
- TFS has a registration service that keeps track of types of links available. New link types can be added to the registration by using “TfsReg.exe” tool and giving link type info as xml file.
- When the links are available in Registration service, RegisteredLinkTypeCollection property of WorkItemStore object in workitem object model lists those new types.
- When user presses “Add Link” button in links control, the UI looks in registry to see if UI controls for the new types are installed in client box. The registry location is: HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\VisualStudio\8.0\WorkItemTracking\LinkExtensibility. If linktype is found under that key, it reads AssemblyName and TypeName and creates an instance of the type specified. The type is expected to implement IDialogControl interface. Now user can use the custom links control to select the link type – typically with a custom browser dialog.
- The links are shown in LinksControl. The description for custom links is obtained by checking if a webservice exists for the linktype by asking Registration service. If a webservice is registered, GetArtifacts method is called to get description of the links.
- When user double clicks on custom link, first UI checks to see if a service that implements IClientLinking is installed. If so, it is called to open the link. If not, a webview of the link is attempted.
For detailed information on linking extensibility, download VS SDK from http://msdn.microsoft.com/vstudio/extend and check out the samples and documents under "VisualStudioTeamSystemIntegration\Work Item Tracking\Team Foundation Core Services". The collectibles sample there shows linking extensibility in further detail and depth.
Limitations of linking extensibility:
Custom link types can be defined and work items can be associated with custom link types in either direction. But presently there is no support for querying on those relationships using query builder UI or wiql engine. There isn’t a way to specify business rules on link associations. You could enforce complex rules using our document events in UI, but those won’t take effect on OM or backend. If your need is to create custom link between workitems themselves for dependency management etc this implementation with V1 linking extensibility may be very limiting for your needs. We are investigating building rich experience for creating & querying work item links keeping in mind common scenarios for future.
Implementing extended link type:
Registering custom link type:
First the link type name and artifact names need to be decided. Artifact is an item that gets linked with artifacts in TFS such as work items, changesets, version control files, test results etc. To check the linktypes and artifacts already in TFS, go to application tier machine and view this webservice: http://localhost:8080/Services/v1.0/Registration.asmx?op=GetRegistrationEntries . Leave toolid blank and press invoke to see all registration information. If you look at WorkItem artifact, all outbound links are under OutboundLinkTypes element and each one is shown in links control. Your link type needs to be added under that element.
To modify/add elements to the registration, a tool named “TfsReg.exe” is available under “<Drive>:\Program Files\Microsoft Visual Studio 2005 Team Foundation Server\Tools” folder in server. An xml file with changes to registration can be passed to TfsReg. The sample has an xml file that registers a custom link and an artifact. Update your link type to the server and verify its existence by viewing registration xml again in application tier.
Building UI to add/edit link type to work item:
When users chooses custom link in “add link” dialog, it needs to show custom UI for browsing/picking item of that link type. Create a new usercontrol project to build that control (Choosing VSIP project is better if double-click support is needed). The sample can also be used as starting point. The control needs to implement below interface (in Microsoft.TeamFoundation.WorkItemTracking.Controls dll)
public interface Microsoft.TeamFoundation.WorkItemTracking.Controls.IDialogControl
// Initializies the control with host, edit/add mode and existing link if it is in edit mode
void Initialize(IDialogControlHost controlHost, DisplayMode displayMode, Link link);
// Return link object with data obtained from user. If UI validation fails, return null to keep the dialog open.
// Return localized display name for link type. If supporting single link type, ignore parameter.
string GetDisplayName(string linkTypeName);
IDialogControlHost provides information such as TFS server, workitem object etc that can be used in the control. IServiceProvider can be used if document service is used inside control.
After the control is built, it has to be registered in client in registry. Below are registry keys to be added from sample:
Handling opening of custom links in LinksControl:
Now user can add a link of your type. When user doubleclicks on that link, what happens can be customized as well! To do that, a VSIP package needs to be registered that implements IClientLinking and provides ClientLinking service. See readme file in sample for example code on how to implement it. IClientLinking has ExecuteDefaultAction method that will be called when user opens a link. Items from other apps can be opened by using shell-execute.
Handling opening of custom links when outside VSIP:
If VSIP plugin is not implemented, or if links control is opened from excel for example, then ClientLinking service implementation is of no use. Checkout external addressability section in linking extensibility VSSDK documentation to provide a web viewer for those items. Work item for example comes with web viewer and you might have seen its link in work item alert emails. Basically when link cannot be opened in VS, a link below is attempted to be opened: http://<ServerName>:8080/<toolname>/<linktype>.aspx?artifactMoniker=<data>
Implementing webservices for linktypes:
You would notice now that the description for links show up as ugly uri. If ILinkingProvider.GetArtifacts is implemented in a webservice & registered, then we could see friendly description. Collectibles samples shows implementation of that webservice well.
Deploying custom link assemblies:
Deployment is unfortunately not xcopy because 1) it needs registry entries and 2) if VSIP package is used, it needs calling “devenv /setup”. I found VS’s setup project to be easy enough to deploy the assemblies, registry-entries and also VSIP packages. Some operations can be done by using custom actions in setup package. The built msi files can be distributed to users. Important Note: Because of a bug, if client bits are not installed but server has link types, we get ugly “null reference” exception when opening work items and links in that item do not get shown. If not all users can install custom link controls, then you might not want to use this extensibility for above reason. This will be fixed in future versions.
You built and deployed, but the new link type doesn’t show up in links control – how to troubleshoot? Here is a serial way to troubleshoot:
- Check registration entries. View the registration webservice output first from AT, and then write a script in wit object model to walk WorkItemStore.RegisteredLinkTypes collection to make sure the new type is in that collection.
- Check registry is looked at: I found regmon (from sysinternals.com) very useful to see if the registry key for my custom link type is searched for. May be it is just spelling mistake or wrong type name used.
- Check assembly is searched: If regmon shows that correct registry key is read, I would use filemon (from sysinternals) to make sure the assembly folder as I gave was searched, and assembly was loaded. Fuslogvw is great to debug assembly loading issues.
<%//This posting is provided "AS IS" with no warranties of any kind and confers no rights. Use of samples included in this posting is subject to the terms specified at http://www.microsoft.com/info/cpyright.htm %>