Accessing TFS/VSTS 2017 programmatically
Being able to have access to the data in Team Foundation Server (TFS)/Visual Studio Team Services (VSTS) can be useful for automating processes where, for instance, you want to either create custom reports, or trigger certain actions based on certain conditions in your development process. Prior to TFS 2017 (and VSTS), the known method was to use the NuGet packages Microsoft.TeamFoundationServer.Client to perform such tasks. With the arrival of TFS 2017/VSTS, Microsoft introduced a REST API that can be used to access the same data. This is a great news as this enables multiple programming languages to access TFS/VSTS. In this post, I will show you how to access your data using both the package and through the API.
Accessing TFS/VSTS through the Client package
The examples I am showing uses the Microsoft.TeamFoundationServer.Client 15.X version. Version 14 differs slightly in how to get access to the various parts of TFS.
Here are the different sub-parts you can access along with their respective class.
Build: BuildHttpClient (Microsoft.TeamFoundationServer.Build.WebApi)
Chat: ChatHttpClient (Microsoft.TeamFoundationServer.Chat.WebApi)
Core (core tfs stuff includes project, process, team, etc): See Classes in Microsoft.TeamFoundationServer.Core.WebApi ending with HttpClient
Dashboards: DashboardHttpClient (Microsoft.TeamFoundationServer.Dashboards.WebApi)
Policy: PolicyHttpClient (Microsoft.TeamFoundationServer.Policy.WebApi)
Source Control (TFS): TfvsHttpClient (Microsoft.TeamFoundationServer.SourceControl.WebApi)
Source Control (GIT): GitHttpClient (Microsoft.TeamFoundationServer.SourceControl.WebApi)
Test: TestHttpClient (Microsoft.TeamFoundationServer.Test.WebApi)
Test Management: TestManagementHttpClient (Microsoft.TeamFoundationServer.TestManagement.WebApi)
Work: WorkHttpClient (Microsoft.TeamFoundationServer.Work.WebApi)
Work Item Tracking: WorkItemTrackingHttpClient (Microsoft.TeamFoundationServer.WorkItemTracking.WebApi)
To connect to a part of TFS/VSTS, for instance BuildServer or SourceControl, one can use the code below. The important part is the connection.GetClient<T> method which is the one responsible to give you access to the sub-parts.
1 2 3 4 5 6 |
var serverUrl = new Uri("https://yourserver.tfs.com/DefaultCollection/"); var clientCredentials = new VssCredentials(new WindowsCredential(new NetworkCredential("USERNAME", "PASSWORD", "DOMAIN"))); var connection = new VssConnection(serverUrl, clientCredentials); var buildServer = connection.GetClient<BuildHttpClient>(); // connect to the build server subpart var sourceControlServer = connection.GetClient<TfvcHttpClient>(); // connect to the TFS source control subpart |
Once you have the object instantiated, you should have access to all the underlying methods and stuff you can do.
For instance, the example below will grab all the changes between 2 build numbers in the project PROJECT, access the source control section of that project with the changeset Id (note that i set the includeDetails to true so that I can access extended properties of the changeset) and grab the check-in note whose name is My check-in note.
1 2 3 4 5 6 7 8 9 10 11 12 13 |
var changesets = buildServer.GetChangesBetweenBuildsAsync("PROJECT", 1,5).Result; foreach (var changeset in changesets) { var csDetail = sourceControlServer.GetChangesetAsync("PROJECT", Convert.ToInt32(changeset.Id.Replace("C", string.Empty).Trim()),includeDetails: true).Result; var checkinNote = csDetail.CheckinNotes?.FirstOrDefault(_ => _.Name == "My check-in note"); if (checkinNote != null) { Console.WriteLine("{0}: {1}", changeset.Id, changeset.Message); Console.WriteLine("Check-in note: {0}",checkinNote.Value); } else Console.WriteLine("Warning: {0} has no check-in note", changeset.Id); } |
Accessing TFS/VSTS through the REST API
The concepts stay the same when wanting to access the rest api of TFS/VSTS. Microsoft did a neat job in to document their REST Api in the documentation of Team Services.
What you have to understand with accessing the REST API however is that you need a token called the personal access token (PAT). To setup the personal access token, login to TFS/VSTS and go to your profile (icon in the right top corner), then click on the security link. You can then have access to view, add and expire tokens.
Make sure you grant the correct permissions for the sub-part in which you want to access. Keep your token somewhere safe, because you will not be able to have access to view the underlying token key once it has been generated. Personal Access Tokens max lifetime is a year. After a year, you will have to regenerate another token. For more details you can see this doc by Microsoft.
To access the rest api of team services through a web client, you need to base64 encode your personal access token and add it to the Authorization header Authorization: Basic BASE64PATSTRING
for each request you make.
https://{your_tfs_server}/DefaultCollection/_apis[/{area}]/{resource}?api-version={version}
For VSTS, the server uri is of the format {account}.visualstudio.com, where {account} is your team services account.
The {area} follow the sub-parts I spoke to above, like build, work, source control, etc. Refer to the documentation for the exact names.
The list below shows the HTTP verbs for the REST API and what they actually do.
Verb | Used for… |
---|---|
GET | Get a resource or list of resources |
POST | Create a resource OR Get a list of resources using a more advanced query |
PATCH | Update a resource |
PUT | Create a resource if it doesn’t exist or, if it does, update it |
DELETE | Delete a resource |
Here is an example on how to start a build through the REST API
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
var personalaccesstoken = "bXlfc3VwZXJfcGVyc29uYWxfYWNjZXNzX3Rva2Vu"; var base64Token = Convert.ToBase64String(Encoding.ASCII.GetBytes($":{personalaccesstoken}")); using (HttpClient client = new HttpClient()) { client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Basic", base64Token); var requestMessage = new HttpRequestMessage(HttpMethod.Post, "https://{your_tfs_server}/DefaultCollection/{project}/_apis/build/builds?api-version=2.0"); requestMessage.Content = new StringContent("{\"definition\": {\"id\":" + definitionId + "},\"sourceBranch\":\"$/BRANCH_NAME\"}", Encoding.UTF8, "application/json"); using (HttpResponseMessage response = client.SendAsync(requestMessage).Result) { response.EnsureSuccessStatusCode(); } } |
Be sure to replace {your_tfs_server}, {project} and BRANCH_NAME with your proper configurations.