Team Foundation Server 2010 – Eventing Service - Subscribing to events
Visual Studio Team System exposes number of opportunities to extend its features and functionality. Responding to events published by the Team Foundation Server (TFS) is one of the extensibility opportunities which may be used most extensively. TFS is a hive of activities related to configuration management, source control, work item tracking, builds etc. These activities can be treated as events and it is possible to write event handlers for many of these events. By handling such events we will be able to automate the tasks related to management of the project. For example, we can subscribe to Checkin event where the subscribing webservice will set the status of associated workitems to a custom value. Another example can be of creating a installer for output of build once the build completion event fires. A very interesting case could be to spawn workitems say of the type tasks in response to event of creation of other type of workitem like a scenario and link the spawned workitems to the scenario like workitem.
This article discusses:
- The events raised by TFS
- Using BisSubscribe.exe
- Filtering the events
- How a subscription can be created for an email
- How to create a subscription for a webservice
- Creating a subscription programmatically
Subscribing to events
TFS uses implementation of publisher – subscriber paradigm in which certain registered events are published when they are raised. Notification of those events, as and when they are raised, is made to the subscribers. TFS registers the subscription in its database. The process of registering a subscription for an event can be done either using a command line tool named BisSubscribe.exe or it can be done programmatically using the Team Foundation Object Model that is published by Microsoft. Subscriptions can be of two types. First type of subscription is an email subscription in which a preconfigured email is sent to the email address mentioned in the subscription. The second type of subscription is of a webservice which has a method named Notify. A parameter of Notify method provides the event specific data.
List of published events
When TFS is installed, numbers of events are registered for publishing. The list of them is as follows:
Build Completion Event
Build Status Changed Event
Note: Node related events refer to iterations and areas in the team project.
BisSubscribe.exe is a command line tool available with the installation of TFS. On TFS 2010 it is available at <System Drive>\Program Files\Microsoft Team Foundation Server 2010\Application Tier\Web Services\bin folder. While executing it takes following arguments:
eventType – Type of the event for which the subscription is being made. E.g. CheckinEvent, WorkItemChangedEvent. These names are case sensitive and are as mentioned in the Table 1.
address – Either the email address to which the notification email should be sent E.g. firstname.lastname@example.org or the URL of the webservice to be called e.g. http://TFS_Name/SubscribingWebService/Service.asmx
deliveryType – This can be either of EmailHtml, EmailPlaintext if the subscription is for email or Soap is the subscription is for webservice method. Soap is taken as the default delivery method.
server / domain – Name of TFS or http address of the TFS with port number (typically 8080). In TFS 2010, the only acceptable value is complete Uri of TFS, e.g. http://TfsName:8080/Tfs or http://TfsName:8080/Tfs/ProjectCollectionName . By providing the name of the project collection, events can be scoped for that collection only. If any project collection name is not provided then it automatically sets it to Default Project Collection.
filter – Optional filter expression which allows TFS to notify only events which match that filter
Filtering the events
Events can be filtered using some criterion in such a way that the events which fulfill that criterion only are notified to the subscriber. TFS uses a special language for setting the filter expressions. This filtering language may contain Event subtypes containing any number of simple fields. For example, E-mail me for Defect events when the ‘Defect Owner field = “user1” AND the Status field <> “Resolved”’”. It may contain normal equality checking operators, =, <>, <,>,<=,>=. It also additionally contains operators for matching with regular expression (Match) or for simple match (Like). An expression can be simple with only one operator or complex with multiple operators and sub expressions. Complex expression is formed with operators like AND, OR e.g. “Team Project = ‘Project 1’ AND PolicyOverrideComment <> ‘’ ”
Creating a email type of subscription
Example of creating an email type of subscription using BisSubscribe.exe tool where email needs to be in plain text would be
>C:\Program Files\Microsoft Visual Studio 2008 Team Foundation Server\TF Setup\BisSubscribe.exe /eventType BuildCompletionEvent /address email@example.com /deliveryType EmailPlaintext /domain http://tfsrtm:8080
>C:\Program Files\Microsoft Team Foundation Server 2010\Application Tier\Web Services\Bin\BisSubscribe.exe /eventType BuildCompletionEvent /address firstname.lastname@example.org /deliveryType EmailPlaintext /server http://tfs2010:8080/Tfs
If the email can be in html format with a filter for the Team Project named SEED_Automation then the same command would be
>C:\Program Files\Microsoft Visual Studio 2008 Team Foundation Server\TF Setup\BisSubscribe.exe /eventType BuildCompletionEvent /filter “Team Project=’SEED_Automation’” /address email@example.com /deliveryType EmailHtml /domain http://tfsrtm:8080
>C:\Program Files\Microsoft Team Foundation Server 2010\Application Tier\Web Services\Bin\BisSubscribe.exe /eventType BuildCompletionEvent /address firstname.lastname@example.org /deliveryType EmailHtml /server http://tfs2010:8080/Tfs
The template which will be used to create the email may look like this:
<head><title>TFS Security Subsystem Notification</title></head>
<body style="font-family:courier new; font-size:12px;">
<div>An access control list has been changed.</div>
<div> Object ID: <variable name="ObjectId" /></div>
<div> Action ID: <variable name="ActionId" /></div>
<div> SID: <variable name="Sid" /></div>
<div> Entry type: <variable name="EntryType" /></div>
<div> Change type: <variable name="ChangeType" /></div>
It may also be given in the .xsl format. If both are present then the precedence will be given to template.
Creating a subscription for webservice
A webservice which subscribes to an event needs to have a method with following signature:
[SoapDocumentMethod(Action="http://schemas.microsoft.com/TeamFoundation/2005/06/Services/Notification/03/Notify", RequestNamespace = " http://schemas.microsoft.com/TeamFoundation/2005/06/Services/Notification/03")]
public void Notify(string eventXml)
//Write your custom code here
//Use eventXml to extract event related fields and their values
"http://schemas.microsoft.com/TeamFoundation/2005/06/Services/Notification/03/Notify", RequestNamespace := " http://schemas.microsoft.com/TeamFoundation/2005/06/Services/Notification/03"), WebMethod(MessageName:=”Notify”)> _
Public Sub Notify(ByVal eventXml As String)
'Write your custom code here
'Use eventXml to extract event related fields and their values
Once such a webservice is ready, the subscription can be created with the command
>C:\Program Files\Microsoft Visual Studio 2005 Team Foundation Server\TF Setup\BisSubscribe.exe /eventType BuildCompletionEvent /filter “Team Project=’SEED_Automation’” /address http://TFS_Name/MyWebService/Service.asmx /deliveryType Soap /domain http://tfsrtm:8080
>C:\Program Files\Microsoft Team Foundation Server 2010\Application Tier\Web Services\Bin\BisSubscribe.exe /eventType BuildCompletionEvent /address http://SiteName/SubscribingWebServiceName/Service.asmx /deliveryType Soap /server http://tfs2010:8080/Tfs
Creating the subscription programmatically
We may create the subscription of all types programmatically instead of using the BisSubscribe tool. The code of the method which adds the subscription may look like this:
IEventService eventEndpoint = (IEventService)server.GetService(typeof(IEventService));
DeliveryPreference delPrev = new DeliveryPreference();
delPrev.Type = DeliveryType.EmailHtml;
delPrev.Schedule = DeliverySchedule.Immediate;
delPrev.Address = txtDeliveryAddress.Text;
string userId = txtDomain.Text + @"\" + txtUsername.Text;
eventEndpoint.SubscribeEvent(userId, "CheckinEvent", "TeamProject = '" + cboProject.SelectedItem + "' AND PolicyOverrideComment <> '' ", delPrev);
Dim eventEndpoint As IEventService = CType(server.GetService(GetType(IEventService)), IEventService)
Dim delPrev As New DeliveryPreference()
delPrev.Type = DeliveryType.EmailHtml
delPrev.Schedule = DeliverySchedule.Immediate
delPrev.Address = txtDeliveryAddress.Text
Dim userId As String = txtDomain.Text & "\" & txtUsername.Text
eventEndpoint.SubscribeEvent(userId, "CheckinEvent", "TeamProject = '" & cboProject.SelectedItem & "' AND PolicyOverrideComment <> '' ", delPrev)
The object model for this code is provided through the components Microsoft.TeamFoundation.dll, Microsoft.TeamFoundation.Client.dll and Microsoft.TeamFoundation.Common.dll.
This article provided an overview of how to achieve automation in project management when working with TFS. It described the process for subscribing to the published events using a tool BisSubscribe.exe as well as to do it programmatically. It also shows differences between command syntax for TFS 2008 and TFS 2010.
Subodh Sohoni is MCTS - Microsoft Team Foundation Server - Configuration and Development and also is a Microsoft Certified Trainer(MCT) since 2004. Subodh works as VP, Technology with SEED Infotech Ltd