Automate “Get Latest Version” from Visual Studio Team Services #VSTS
If you use Visual Studio Team Services – previously known as “Visual Studio Online” to manage your source control, and you find yourself frequently exporting zip files, and copying them to deployment, you might be pleased to know there is an extensive API that allows you do a “Get Latest Version” from C#
So, first off you need to create an app with VSTS here;
https://app.vsaex.visualstudio.com/app/register
You’ll need to have a publicly accessible HTTPS website for the callback. I’ve just used https://<mydomain>/callback.aspx – I selected all the available scopes, but you can be more selective.
Once registered, you’ll get your Oauth credentials, and slot them into your web.config
<appSettings>
<add key=”app_id” value=”….”/>
<add key=”app_secret” value=”….”/>
<add key=”client_secret” value=”…..”/>
<add key=”Authorize_URL” value=”https://app.vssps.visualstudio.com/oauth2/authorize?mkt=en-US”/>
<add key=”Access_Token_URL” value=”https://app.vssps.visualstudio.com/oauth2/token?mkt=en-US”/>
<add key=”Scopes” value=”vso.build_execute vso.code_full vso.code_status vso.codesearch vso.connected_server vso.dashboards vso.dashboards_manage vso.entitlements vso.extension.data_write vso.extension_manage vso.gallery_acquire vso.gallery_manage vso.graph_manage vso.identity_manage vso.loadtest_write vso.machinegroup_manage vso.memberentitlementmanagement_write vso.notification_diagnostics vso.notification_manage vso.packaging_manage vso.profile_write vso.project_manage vso.release_manage vso.security_manage vso.serviceendpoint_manage vso.symbols_manage vso.taskgroups_manage vso.test_write vso.wiki_write vso.work_full vso.workitemsearch”/>
<add key=”RemoteLogCat” value=”…..”></add>
<add key=”RemoteScope” value=”$/….”></add>
<add key=”LocalWorkSpace” value=”F:\….\”></add>
<add key=”accountName” value=”…..”></add>
<add key=”projectName” value=”…..”></add>
</appSettings>
I’ve removed sensitive data above, but each setting is as follows:
- app_id, app_secret, client_secret – Displated after creating your app on VSTS
- RemoteLogCat – optional, from RemoteLogCat.com
- RemoteScope – The path where the root of your website resides on TFS
- LocalWorkSpace – The file path where the website will be downloaded to locally
- accountName – your account on VSTS
- projectName – the project within your account on VSTS
Then, the first step is to request consent to access your account on VSTS, which you can do a redirect link as follows;
var strUrl = “https://app.vssps.visualstudio.com/oauth2/authorize”;strUrl += “?client_id=” + ConfigurationManager.AppSettings[“app_id”];strUrl += “&response_type=Assertion”;strUrl += “&state=any”;strUrl += “&scope=” + ConfigurationManager.AppSettings[“Scopes”];strUrl += “&redirect_uri=https://…./callback.aspx”;Response.Redirect(strUrl);

var strCode = Request.QueryString[“code”];var strClientSecret = ConfigurationManager.AppSettings[“client_secret”];var strCallbackUrl = “https://…./callback.aspx”;var strTokenUrl = “https://app.vssps.visualstudio.com/oauth2/token”;var strPostData = GenerateRequestPostData(strClientSecret, strCode, strCallbackUrl);var wc = new WebClient();wc.Headers[“Content-Type”] = “application/x-www-form-urlencoded”;try{var strJson = wc.UploadString(strTokenUrl, strPostData);Response.Write(strJson);Response.Write(“<hr>”);var jObject = JObject.Parse(strJson);var strAccessCode = jObject[“access_token”].ToString();//BuildLocalWorkSpaceTree(strAccessCode);//GetLastChangeSet(strAccessCode);}catch(WebException ex){var resp = new StreamReader(ex.Response.GetResponseStream()).ReadToEnd();Response.Write(resp);}
privatestaticstring GenerateRequestPostData(string appSecret, string authCode, string callbackUrl){return String.Format(“client_assertion_type=urn:ietf:params:oauth:client-assertion-type:jwt-bearer&client_assertion={0}&grant_type=urn:ietf:params:oauth:grant-type:jwt-bearer&assertion={1}&redirect_uri={2}”,HttpUtility.UrlEncode(appSecret),HttpUtility.UrlEncode(authCode),callbackUrl);}
privatevoid BuildLocalWorkSpaceTree(string bearer){var strLocalWorkspace = ConfigurationManager.AppSettings[“LocalWorkSpace”];var strAccountName = ConfigurationManager.AppSettings[“accountName”];var strRemoteScope = ConfigurationManager.AppSettings[“RemoteScope”];DeleteAllFilesAndFoldersInPath(strLocalWorkspace);var strItemsUrl = “https://{0}.visualstudio.com/_apis/tfvc/items?scopePath={1}&recursionLevel=Full&api-version=5.0-preview.1”;strItemsUrl = string.Format(strItemsUrl, strAccountName, strRemoteScope);var wc = new WebClient();wc.Headers[“Authorization”] = “Bearer ” + bearer;var strItemsJson = wc.DownloadString(strItemsUrl);Response.Write(“<hr>”);var jObject = JObject.Parse(strItemsJson);foreach (var jItem in jObject[“value”]){var strRemotePath = jItem[“path”].ToString();var strLocalPath = strRemotePath.Replace(strRemoteScope, strLocalWorkspace).Replace(“/”, @”\”);Response.Write(“Creating ” + strLocalPath + “<br>”);Response.Flush();if (jItem[“isFolder”] != null){Directory.CreateDirectory(strLocalPath);}else{var strItemUrl = “https://{0}.visualstudio.com/_apis/tfvc/items?download=true&path={1}&api-version=5.0-preview.1”;strItemUrl = string.Format(strItemUrl, strAccountName, HttpUtility.UrlEncode(strRemotePath));var raw = wc.DownloadData(strItemUrl);File.WriteAllBytes(strLocalPath,raw);}}}