Austin Agile DevOps

DevOps in the Cloud
posts - 70 , comments - 7 , trackbacks - 0

TFS 2012 API Create Alert Subscriptions

There were only a few post on this and I felt like really important information was left out:

  1. What the defaults are
  2. How to create the filter string

Here’s the code to create the subscription.

Get the Collection

public TfsTeamProjectCollection GetCollection(string collectionUrl)
        {
            try
            {
                //connect to the TFS collection using the active user
                TfsTeamProjectCollection tpc = new TfsTeamProjectCollection(new Uri(collectionUrl));
                tpc.EnsureAuthenticated();
                return tpc;
            }
            catch (Exception)
            {
                return null;
            }
        }

Use Impersonation

Because my app is used to create “support tickets” as stories in TFS, I use impersonation so the subscription is setup for the “requester.”  That way I can take all the defaults for the subscription delivery preferences.

public TfsTeamProjectCollection GetCollectionImpersonation(string collectionUrl, string impersonatingUserAccount)
        {
            // see: http://blogs.msdn.com/b/taylaf/archive/2009/12/04/introducing-tfs-impersonation.aspx
            try
            {
                TfsTeamProjectCollection tpc = GetCollection(collectionUrl);
                if (!(tpc == null))
                {
                    //get the TFS identity management service (v2 is 2012 only)
                    IIdentityManagementService2 ims = tpc.GetService<IIdentityManagementService2>();

                    //look up the user we want to impersonate
                    TeamFoundationIdentity identity = ims.ReadIdentity(IdentitySearchFactor.AccountName, 
                        impersonatingUserAccount, 
                        MembershipQuery.None, 
                        ReadIdentityOptions.None);

                    //create a new connection using the impersonated user account
                    //note: do not ensure authentication because the impersonated user may not have 
                    //windows authentication at execution
                    if (!(identity == null))
                    {
                        TfsTeamProjectCollection itpc = new TfsTeamProjectCollection(tpc.Uri, identity.Descriptor);
                        return itpc;
                    }
                    else
                    {
                        //the user account is not found
                        return null;
                    }
                }
                else
                {
                    return null;
                }
            }
            catch (Exception)
            {
                return null;
            }
        }

Create the Alert Subscription

public bool SetWiAlert(string collectionUrl, string projectName, int wiId, string emailAddress, string userAccount)
        {
            bool setSuccessful = false;
            try
            {
                //use impersonation so the event service creating the subscription will default to 
                //the correct account: otherwise domain ambiguity could be a problem
                TfsTeamProjectCollection itpc = GetCollectionImpersonation(collectionUrl, userAccount);

                if (!(itpc == null))
                {

                    IEventService es = itpc.GetService(typeof(IEventService)) as IEventService;

                    DeliveryPreference deliveryPreference = new DeliveryPreference();
                    //deliveryPreference.Address = emailAddress;
                    deliveryPreference.Schedule = DeliverySchedule.Immediate;
                    deliveryPreference.Type = DeliveryType.EmailHtml;

                    //the following line does not work for two reasons: 
                    //string filter = string.Format("\"ID\" = '{0}' AND \"Authorized As\" <> '[Me]'", wiId);

                    //1. the create fails because there is a space between Authorized As
                    //2. the explicit query criteria are all incorrect anyway
                    //   see uncommented line for what does work: you have to create the subscription mannually 
                    //   and then get it to view what the filter string needs to be (see following commented code)
                    
                    //this works
                    string filter = string.Format("\"CoreFields/IntegerFields/Field[Name='ID']/NewValue\" = '12175'" + 
                                                    " AND \"CoreFields/StringFields/Field[Name='Authorized As']/NewValue\"" + 
                                                    " <> '@@MyDisplayName@@'", projectName, wiId);

                    string eventName = string.Format("<PT N=\"ALM Ticket for Work Item {0}\"/>", wiId);

                    es.SubscribeEvent("WorkItemChangedEvent", filter, deliveryPreference, eventName);

                    ////use this code to get existing subscriptions: you can look at manually created 
                    ////subscriptions to see what the filter string needs to be
                    //IIdentityManagementService2 ims = itpc.GetService<IIdentityManagementService2>();
                    //TeamFoundationIdentity identity = ims.ReadIdentity(IdentitySearchFactor.AccountName, 
                    //    userAccount, 
                    //    MembershipQuery.None, 
                    //    ReadIdentityOptions.None);
                    //var existingsubscriptions = es.GetEventSubscriptions(identity.Descriptor);

                    setSuccessful = true;

                    return setSuccessful;
                }
                else
                {
                    return setSuccessful;
                }
            }
            catch (Exception)
            {
                return setSuccessful;
            }
        }

Print | posted on Wednesday, July 24, 2013 11:13 AM |

Feedback

No comments posted yet.
Post A Comment
Title:
Name:
Email:
Comment:
Verification:
 

Powered by: