Today Rob Caron announced a new Visual Studio Team Edition that provides many integrated tools to improve data-driven applications development: Visual Studio Team Edition for Database Professionals.
The first CTP of the product will be available in TechEd 06 and the final release is expected to ship by the end of this year.

From the Database Professionals Team Center:

“Visual Studio Team Edition for Database Professionals delivers a
market-shifting database development product designed to manage
database change, improve software quality through database testing and
bring the benefits of Visual Studio Team System and life cycle
development to the database professional.”

I can’t wait to try it out!

For more information check out the following resources:

I’m proud to annouce that Johnny Halife and I are going to collaborate with Alejandro Jack on the MSDN Webcast named Extending Visual Studio Team System he will be giving next week.

Summary:
Southworks S.R.L. is a leading early adopter of Microsoft Visual Studio Team System in the Latin American region. Come hear about their experiences with adopting, customizing, and extending Visual Studio Team System for teams ranging in size from three people to large-scale multi-partner teams of 50 or more. Recent changes in the local law required ISO certifications, which necessitated customizing and extending Visual Studio Team System to cope with requirements not covered by the standard process guidance. Join this webcast for insights into implementing, adapting, and extending Visual Studio Team System based on a successful large-scale real world experience.

Hope to meet you there!

Event Code: 1032295849
Event Name: MSDN Webcast: Extending Visual Studio Team System (Level 200)
Start Date: 5/23/2006
Start Time: 11:00 AM (GMT-08:00) Pacific Time (US & Canada)
End Date: 5/23/2006
End Time: 12:00 PM (GMT-08:00) Pacific Time (US & Canada)

Event Details & Registration

MSFWinBuild, the tool that compiles Process Guidance for Team System is finally available for download!

This tool is the one used by Microsoft to create MSF Agile and MSF for CMMI process guidances, it generates nice HTML files from XML sources that describe the guidance content.

Go get it from the GotDotNet workspace!

Important:

If you’re editing work item types, you will find useful having Intellisense in Visual Studio 2005:

  1. Open the Visual Studio Team System Integration folder from the VS 2005 SDK. The SDK can be downloaded from here.
  2. Navigate to Work Item Tracking.
  3. Copy the file WorkItemTypeDefinition.xsd included in Work Item Tracking Schemas.zip to “C:\Program Files\Microsoft Visual Studio 8\Xml\Schemas”, supposing you installed VS 2005 in the default location.

That’s it! Enjoy Intellisense! :)

After working with Visual Studio Team System at Southworks for some months, I noticed a common practice that some of us repeated frecuently: after creating a Work Item we use to send an email to the assigned user just with the subject: "Assigned WI #xxx". This was not only a boring task, but also innecessary and prone to errors. VSTS was born to be extended, so I started researching on how to extend it with my own artifacts to provide better user experience for the whole team at Southworks.

The result of this effort is a simple and effective solution: when a user A assigns a work item to a user B, B recieves automatically an email with the notice and all the information he needs about the work item assigned:

AutomaticallyRecievedEmail

Now let’s see how this was achieved.

Note: In this article I explain a way of extending VSTS. Similar results of the implemented solution can be achieved using Team Foundation Alerts, anyway, my goal is to provide you with an extensible open-source solution which you can take and adapt to your needs easily. I found Team Foundation Alerts somehow difficult -if not impossible- to extend or customize, so I hope my solution will help you when dealing with notifications in Team Foundation Server.

Extending Visual Studio Team System

VSTS has many extension points, for example:

  • Reporting. Eg.: extend TFS Warehouse.
  • Project Portal. Eg.: create new web parts.
  • Core Services. Eg.: link work items to other tool’s artifacts, subscrive to events.
  • Work Item Tracking. Eg.: write against object model.
  • Source Control. Eg.: create new police.
  • Build. Eg.: create new build tasks.
  • Others…

Note that creating a custom process template, defining new work item types, creating reports, etc. are not listed here because they are customization examples. In this article I will discuss about extending VSTS (which involves development activities) rather than customizing it (which generally can be achieved by using provided tools).

From the list shown above, we will focus in the Core Services and build our solution using the Eventing Service.

Eventing Service

The Eventing Service is an extensible asynchronous publish/subscribe event notification system included in VSTS. It is used in two different scenarios:

  1. Integration of loosely coupled services/systems.
  2. User notification of events.

In both scenarios, there exists one or more publishers and cero or more subscribers for events. Subscribers may define filter expressions, so that notifications to subscribers are delivered only if the filter condition is true.

In scenario N-1, the mechanism used for notification is SOAP. This simply implies that when an event is fired, subscribed web services will be invoked (if they match the event filter). Note that these web services must have a specific (and simple) signature, but we will talk about this later. As regards scenario N-2, the notification mechanism is e-mail: every user subscribed to an event will recieve an e-mail with event-specific information when it is delivered.

VSTS includes built-in events but, if you need more functionality, you can register events raised from your own applications. Some of the built-in events included in RC are:

Event Name Fired when…
BuildCompletionEvent a build has completed.
CheckInEvent files are being checked in to source control.
WorkItemChangedEvent a work item has been changed.

To find a list of all events that your version of VSTS can fire, have a look at this post [1].

At a first glance, the scenario N-2 seems to be the one that fits our situation, but actually it doesn’t. As I said before, user notification of events means that each subscribed user will recieve an e-mail per each subscription when the event is fired. But this also means that when subscribing to an event, we have to know which user will have a work item assinged to - which is impossible at that moment. That’s why our situation fits scenario N-1: we need to process event data before sending an e-mail to the assigned user.

Having said this, we are ready to move to next level: solution design.

Solution Design

Our solution will take advantage of the Eventing Service described recently by subscribing a custom web service to the WorkItemChangedEvent. Every time a work item is changed, the web service will be invoked with the event information. This information includes the old and new values of the work item’s common and changed fields. Then, the web service will check some bussiness rules, look in the Active Directory for the email address of the assigned user and finally, send the notification email.

It is said that a picture tells more than a thousands words… so here is solution diagram:

Solution Design

Implementation

The Web Service

First we need to create the web service that will listen to the WorkItemChangedEvent. Every web service subscribed to the Eventing Service must have the 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")][WebMethod]public void Notify(string eventXml, string tfsIdentityXml) { //… }

When TFS calls the web service, the eventXml string will hold all the event information in a XML format that matches the schema defined for the event. If you want to see the schema for the WorkItemChangedEvent, click here. To see other events’ schemas, see this post [1]. As regards the tfsIdentityXml string, it will only hold the caller TFS address.

Here is my implementation of the web method:

[SoapDocumentMethod(Action = 
    "http://schemas.microsoft.com/TeamFoundation/
    2005/06/Services/Notification/03/Notify",RequestNamespace="http://schemas.microsoft.com/TeamFoundation/2005/    06/Services/Notification/03")][WebMethod]public void Notify(string eventXml, string tfsIdentityXml) {    // Load the recieved XML into a XMLDocument
    XmlDocument eventXmlDoc = new XmlDocument();    eventXmlDoc.LoadXml(eventXml);    XmlElement eventData = eventXmlDoc.DocumentElement;

    // Validate event data
    if (eventData != null && ValidateEventData(eventData))    {        // Get assigned user’s name from event data
        string toName = GetDisplayName(eventData);

        // Retrieve assigned user’s e-mail address from Active Directory        string toAddress = GetAddress(toName);

        // If the e-mail addres was found in AD, send the e-mail
        if (toAddress != String.Empty)            SendMail(new MailAddress(toAddress, toName),                                     eventData, GetBody(eventXml));    }}

As you can see, the logic is quite simple. I suggest you to watch the source code for more details. Anyway, some methods deserve more detailed explanation:

  • ValidateEventData(XmlElement eventData): As the web method will be invoked whenever a work item is changed (see section Subscribing to WorkItemChangedEvent below), we need to check if the Assigned To field has changed and that the user that changed the work item is not the same as the assigned user. You don’t need to recieve an email notification if you assigned the work item to yourself, do you? Here is the code:

    private bool ValidateEventData(XmlElement eventData){    // Check if the Assigned To field changed
        XmlNode assignedTo = eventData        .SelectSingleNode("ChangedFields/StringFields/Field[ReferenceName='System.AssignedTo']");
    
        if (assignedTo != null)    {        // Check that the assigned user is different to the user that changed the work item
            XmlNode changedBy = eventData            .SelectSingleNode("CoreFields/StringFields/Field[ReferenceName='System.ChangedBy']");
    
            return (assignedTo.SelectSingleNode("NewValue").InnerText !=                  changedBy.SelectSingleNode("NewValue").InnerText);    }    else
            return false;}
  • GetAddress(string userDisplayName): This method is in charge of accessing the Active Directory [2] in current domain to retrieve user’s e-mail address given its Display Name. Note that since the RC version of Team Foundation Server the Display Name is what VSTS uses to identify a user. Besides, take into account that you will need read access to the AD.

    private string GetAddress(string userDisplayName){    // Bind DirectorySearcher to current domain
        DirectorySearcher searcher = new DirectorySearcher();
    
        // We only need user email
        searcher.PropertiesToLoad.Add("mail");
    
        // Set the filters. We only want Users whose Display Name is userDisplayName
        searcher.Filter = String.Format("(&(displayName={0})(objectCategory=person)((objectClass=user)))"                                   , userDisplayName);
    
        // Retrieve results
        SearchResultCollection results = searcher.FindAll();
    
        // Check if the user was found
        if (results.Count > 0)    {        // Check if the user has the email set in AD
            ResultPropertyValueCollection values = results[0].Properties["mail"];        if (values.Count > 0)            return values[0].ToString();        else
                return String.Empty;    }    else
            return String.Empty;}
  • GetBody(string eventXml): To create the e-mail body, I used an adapted version of the XSL transformation that TFS uses when sending user notifications by e-mail. Supposing you installed TFS in the default directory, the xsl file can be found in C:\Program Files\Microsoft Visual Studio 2005 Team Foundation Server\Web Services\Services\v1.0\Transforms\WorkItemChangedEvent.xsl. I ommited method implementation here because it’s just an XSL transformation. Anyway, the full source code is available in the download package.

    A useful feature to keep in mind is that TFS exposes a nice and complete web page that allows you to visualize work items from your web browser. The URL of this page is stored in the DisplayUrl node of the eventXml string, so you should use it! If you have never seen this web page, just point your browser to http://[TFS]:8080/WorkItemTracking/WorkItem.aspx?artifactMoniker=[WorkItem#].

    VisualizingWorkItems

Subscribing to the WorkItemChangedEvent

We have the web service complete, but it will never get called if we don’t subscribe it to the Eventing Service!

The process of subscribing to events can be done in two different ways: calling a TFS web service (http://[TFS]:8080/services/v1.0/Eventservice.asmx) or using the TFS object model. Independently from the method you choose, you need to call the SubscriveEvent method and supply the following parameters (from VS SDK 2005):

  • userId is an arbitrary string for identifying the user. It is used for looking up subscriptions by owner. In Beta 3, the Project Alerts set in Team Explorer use e-mail addresses for the userId. For the final release, the system will use SIDs.

  • eventType is the fully qualified name of the event type to which the user is subscribing.

  • filterExpressions is string that describes how to filter through many instances of this event type. Only events that match the filter are delivered.

  • DeliveryPreference is a structure that has the following format. It describes how an event that matches the eventType and filterExpression is to be delivered. The filtering language is discussed in greater detail in a later section.
    class DeliveryPreference
    {
    	enum Type;   	// EmailHtml, EmailPlaintext Soap.
    	enum Schedule;	// Immediate, Daily or Weekly.
    	string Address;	// Email address or SOAP URL depending                         //on the Type or other identifying string.
    }

This time I used the TFS Object Model, so here is a code snippet for subscribing to the WorkItemChangedEvent (not included in the download package):

using Microsoft.TeamFoundation.Client;using Microsoft.TeamFoundation.Server;

// …

// Connect to TFS
TeamFoundationServer tfsServer = TeamFoundationServerFactory.GetServer    (ConfigurationManager.AppSettings["TFSServer"], new UICredentialsProvider());tfsServer.Authenticate();

// Get Eventing Service
IEventService eventService = (IEventService)tfsServer.GetService(typeof(IEventService));

// Set delivery preferences
DeliveryPreference dPref = new DeliveryPreference();dPref.Schedule = DeliverySchedule.Immediate;dPref.Address = ConfigurationManager.AppSettings["WSAdress"];dPref.Type = DeliveryType.Soap;

// Subscribe to event
string userId = ConfigurationManager.AppSettings["Subscriber"];string filter = String.Empty;eventService.SubscribeEvent(userId, "WorkItemChangedEvent", filter, dPref).ToString();

Note: It’s important to notice that we didn’t use any subscription filter in this solution, altough it would be desirable and would avoid using unnecessary network bandwidth. For instance, I thought of a filter expression like this: "notify me only if the old value of the Assigned To field is different to the new value of the Assigned To field."  The big obstacle for doing this is that the language used to write event filter expressions in Visual Studio (VSEFL) is a bit limited. You can’t make comparissons between two fields in a work item. You are only allowed to make comparisons between a field and a constant. Check out this forum thread for more information.

Concluding…

In this article I tried to show you, in simple words, one means of extending VSTS. With current lack of official documentation about this topic, I hope this article will help you save time understanding a bit more about Visual Studio Team System. Take into account that there exist many other ways of customizing and extending VSTS. Keep an eye on this blog as I will be posting about them as I go on with my research.

Next Steps

If you enjoyed extending VSTS, don’t miss these useful links. You will find a lot of information about Customizing & Extending VSTS!

Sources

Download them from here.


Footnotes

  1. Marcel Vries, Team System MVP. Blog: http://blogs.infosupport.com/marcelv/.

  2. If you want more information about using Active Directory in your applications, I recommend you to visit:

Here I’ll post useful resources I find when making research about Customizing & Extending Visual Studio Team System. Please, if you have another resource that is not listed here let me know!

General

TFS Warehouse & Reporting

Bloggers

Martin Woodward has written another useful post related to Source Control in Visual Studio Team System.
In this opportunity, he talks about the lock types and gives some advises on when to use each one.

Don’t miss it! TFS Source Control Lock Types.

Tim Noonan posted a couple of registry settings that will boost up the performance of Visual Studio Team System.

Personally I found very useful the setting that will prevent Team Explorer and Source Control from connecting automatically to a Team Foundation Server when Visual Studio starts:
Simply create a DWORD value called “AutoLoadServer” under HKEY_CURRENT_USER\Software\Microsoft\VisualStudio\8.0\TeamFoundation and set it to 0.

Link:
http://blogs.msdn.com/hippietim/archive/2006/03/14/551320.aspx

Those who are used to working with Subversion know the great tool the blame command is: it helps you to know who modified every single line in a file and when (in what revision).


Now you can have this feature in Team Foundation Server, luckily!


Don’t miss this post from Buck Hodges, he talks about the Annotate (Blame) tool included in the Visual Studio 2005 SDK - March 2006 CTP for v2.

Team System Widgets

February 21st, 2006

Richard Hundhausen (author of the book “Working with Microsoft (r) Visual Studio(r) 2005 Team System”) recently published a useful “list of various Visual Studio 2005 and Team Foundation Server add-ins, add-ons,
widgets, and extensibility solutions”.

Check it out at http://www.accentient.com/widgets.aspx.