01 – What are we trying to achieve? In this blog post I’ll be showing you how to add work item queries as favorites, it is also possible to use the same technique to add build definition as favorites. Once a shared query or build definition has been added as favorite it will show up on the team web access. In this blog post I’ll be showing you a work around in the absence of a proper API how you can add queries to team favorites. 02 – Disclaimer There is no official API for adding favorites programmatically. In the work around below I am using the Identity service to store this data in a property bag which is used during display of favorites on the team web site. This uses an internal data structure that could change over time, there is no guarantee about the key names or content of the values. What is shown below is a workaround for a missing API. 03 – Concept There is no direct API support for favorites, but you could work around it using the identity service in TFS. Favorites are stored in the property bag associated with the TeamFoundationIdentity (either the ‘team’ identity or the users identity depending on if these are ‘team’ or ‘my’ favorites). The data is stored as json in the property bag of the identity, the key being prefixed by ‘Microsoft.TeamFoundation.Framework.Server.IdentityFavorites’. References - Microsoft.TeamFoundation.WorkItemTracking.Client - using Microsoft.TeamFoundation.Client; - using Microsoft.TeamFoundation.Framework.Client; - using Microsoft.TeamFoundation.Framework.Common; - using Microsoft.TeamFoundation.ProcessConfiguration.Client; - using Microsoft.TeamFoundation.Server; - using Microsoft.TeamFoundation.WorkItemTracking.Client; Services - IIdentityManagementService2 - TfsTeamService - WorkItemStore 04 – Solution Lets start by connecting to TFS programmatically // Create an instance of the services to be used during the program
private static TfsTeamProjectCollection _tfs;
private static ProjectInfo _selectedTeamProject;
private static WorkItemStore _wis;
private static TfsTeamService _tts;
private static TeamSettingsConfigurationService _teamConfig;
private static IIdentityManagementService2 _ids;
// Connect to TFS programmatically
public static bool ConnectToTfs()
{
var isSelected = false;
var tfsPp = new TeamProjectPicker(TeamProjectPickerMode.SingleProject, false);
tfsPp.ShowDialog();
_tfs = tfsPp.SelectedTeamProjectCollection;
if (tfsPp.SelectedProjects.Any())
{
_selectedTeamProject = tfsPp.SelectedProjects[0];
isSelected = true;
}
return isSelected;
}
Lets get all the work item queries from the selected team project
static readonly Dictionary<string, string> QueryAndGuid = new Dictionary<string, string>();
// Get all queries and query guid in the selected team project
private static void GetQueryGuidList(IEnumerable<QueryItem> query)
{
foreach (QueryItem subQuery in query)
{
if (subQuery.GetType() == typeof(QueryFolder))
GetQueryGuidList((QueryFolder)subQuery);
else
{
QueryAndGuid.Add(subQuery.Name, subQuery.Id.ToString());
}
}
}
Pass the name of a valid Team in your team project and a name of a valid query in your team project. The team details will be extracted using the team name and query GUID will be extracted using the query name. These details will be used to construct the key and value that will be passed to the SetProperty method in the Identity service.
Key
“Microsoft.TeamFoundation.Framework.Server.IdentityFavorites..<TeamProjectURI>.<TeamId>.WorkItemTracking.Queries.<newGuid1>”
Value
"{"data":"<QueryGuid>","id":"<NewGuid1>","name":"<QueryKey>","type":"Microsoft.TeamFoundation.WorkItemTracking.QueryItem”}"
// Configure a Work Item Query for the given team
private static void ConfigureTeamFavorites(string teamName, string queryName)
{
_ids = _tfs.GetService<IIdentityManagementService2>();
var g = Guid.NewGuid();
var guid = string.Empty;
var teamDetail = _tts.QueryTeams(_selectedTeamProject.Uri).FirstOrDefault(t => t.Name == teamName);
foreach (var q in QueryAndGuid.Where(q => q.Key == queryName))
{
guid = q.Value;
}
if(guid == string.Empty)
{
Console.WriteLine("Query '{0}' - Not found!", queryName);
return;
}
var key =
string.Format(
"Microsoft.TeamFoundation.Framework.Server.IdentityFavorites..{0}.{1}.WorkItemTracking.Queries{2}",
new Uri(_selectedTeamProject.Uri).Segments.LastOrDefault(), teamDetail.Identity.TeamFoundationId,
g);
var value =
string.Format(
@"{0}""data"":""{1}"",""id"":""{2}"",""name"":""{3}"",""type"":""Microsoft.TeamFoundation.WorkItemTracking.QueryItem""{4}",
"{", guid, g, QueryAndGuid.FirstOrDefault(q => q.Value==guid).Key, "}");
teamDetail.Identity.SetProperty(IdentityPropertyScope.Local, key, value);
_ids.UpdateExtendedProperties(teamDetail.Identity);
Console.WriteLine("{0}Added Query '{1}' as Favorite", Environment.NewLine, queryName);
}
If you have any questions or suggestions leave a comment.
Enjoy!