Introduction
We have starting using Visual Studio Team Foundation Services to manage our Agile workload, but I wanted to make sure the tester has a simple and quick way of reporting bugs\features.
Looking around, there are a number of web based applications, which focus on Website logging. We develop desktop application and these solutions did not work good enough for our needs.
Due to this, I created a new simple desktop application, which uses the Visual Studio Team Foundation Services APIs, to create a bug add attachment and notes.
This has given me a good feel on how to use the Visual Studio Team Foundation Services APIs and I want to pass on what I have learned.
Using the Code
The solution uses HTTPClient
and JsonConvert.SerializeObject
to do JSON calls.
Convert the Data Class object from a Data
class to a HTTPContent
, which then can be used by JSON.
public static System.Net.Http.HttpContent ConvertDataClassToJason(object dataClass)
{
string wiPostDataString = JsonConvert.SerializeObject(dataClass);
return new System.Net.Http.StringContent
(wiPostDataString, Encoding.UTF8, "application/json-patch+json");
}
The below method uses HTTPClient
to Post or Patch calls and retrieve a result using the APIs.
Post example:
public static async void Post(string url, System.Net.Http.HttpContent wiPostDataContent,
string returnType, JSONReturnCallBack callBack)
{
string responseString = String.Empty;
try
{
using (System.Net.Http.HttpClient client = new System.Net.Http.HttpClient())
{
client.DefaultRequestHeaders.Accept.Add
(new System.Net.Http.Headers.MediaTypeWithQualityHeaderValue("application/json"));
client.DefaultRequestHeaders.Authorization =
new AuthenticationHeaderValue
("Basic",Convert.ToBase64String
(System.Text.ASCIIEncoding.ASCII.GetBytes
(string.Format("{0}:{1}", username, password))));
using (System.Net.Http.HttpResponseMessage response =
client.PostAsync(url, wiPostDataContent).Result)
{
response.EnsureSuccessStatusCode();
string ResponseContent = await response.Content.ReadAsStringAsync();
responseString = ResponseContent;
}
}
}
catch(Exception ex)
{
Console.WriteLine(ex.ToString());
Console.ReadLine();
}
callBack(responseString,returnType);
}
Patch call
This need a Library added to your Visual studio. You can do this by using nuget.
https://www.nuget.org/packages/Microsoft.VisualStudio.Services.Client
Code snippet to be added
Creating an Work Item
The below example, will take you through the below points
- Adding new work item
- Attaching a file
- Upload file
- Attach to work item
Create a new item
This will show you how to create a simple item within your project on your VSO account
Create the Parameters
When you create an item you need the Title, Description and Tags
private static void createInitailItemPostObject()
{
AddUpdateProp("/fields/System.Title", newTaskItem.Title);
AddUpdateProp("/fields/System.Tags", newTaskItem.Tags);
AddUpdateProp("/fields/System.Description", newTaskItem.Description);
}
private static void AddUpdateProp( string field, string value)
{
DataObjectsProject.VSOJasonWorkItemPostData wiPostData = new DataObjectsProject.VSOJasonWorkItemPostData();
wiPostData.op = "add";
wiPostData.path = field;
wiPostData.value = value;
wiPostDataArr.Add(wiPostData);
}
Data Class used to hold the parameters
public class VSOJasonWorkItemPostData
{
public string op;
public string path;
public string value;
}
Sending the Item
Send the Item to VSO to create an work item. This method will return a Id as well as a few other fields.
string NewWorkItem =
"https://[Account].visualstudio.com/DefaultCollection/[Project]/_apis/wit/workitems/$Task?api-version=1.0";
Models.Helpers.JASONHelper.Post(newWorkItem, Models.Helpers.JASONHelper.ConvertDataClassToJason
(wiPostDataArr), "createtask", new Models.Helpers.JASONHelper.JSONReturnCallBack(jsonReturn));
The JSON call return a string, below will convert the string to a usable object
public static VSOJasonWorkItemReturnData ConvertDataClassToWorkItemReturnDataObject(string jasonString)
{
var wiPostDataString =
JsonConvert.DeserializeObject<VSOJasonWorkItemReturnData>(jasonString);
return wiPostDataString;
}
The data object class used
public class VSOJasonWorkItemReturnData
{
[JsonProperty(PropertyName = "id")]
public int Id { get; set; }
[JsonProperty(PropertyName = "rev")]
public int Rev { get; set; }
[JsonProperty(PropertyName = "fields")]
public JsonArrayAttribute Fields { get; set; }
[JsonProperty(PropertyName = "links")]
public JsonArrayAttribute Links { get; set; }
}
Send attachment
You first need to upload an attachment to your Visual Studio Team Foundation Services account.
string responseString = String.Empty;
try
{
using (System.Net.Http.HttpClient client = new System.Net.Http.HttpClient())
{
client.DefaultRequestHeaders.Authorization =
new AuthenticationHeaderValue("Basic",
Convert.ToBase64String
(System.Text.ASCIIEncoding.ASCII.GetBytes(getConnectionDetails())));
FileStream files = new FileStream(filepath, FileMode.Open);
StreamContent streamcontent = new StreamContent(files);
using (System.Net.Http.HttpResponseMessage response =
client.PostAsync(SetURL(url),streamcontent).Result)
{
response.EnsureSuccessStatusCode();
responseString = await response.Content.ReadAsStringAsync();
}
}
}
catch (Exception ex)
{
Console.WriteLine(ex.ToString());
Console.ReadLine();
}
Attach the attachment
Once you have sent the attachment, you then need to attach the attachment to the required work item.
try
{
using (HttpClient client = new System.Net.Http.HttpClient())
{
StringBuilder msg = new StringBuilder();
msg.Append("[{");
msg.Append("\"op\": \"add\",");
msg.Append("\"path\": \"/relations/-\",");
msg.Append("\"value\": {");
msg.Append("\"rel\": \"AttachedFile\",");
msg.Append(String.Format("\"url\": \"{0}\",", attachmentUploadReturnObject.URL));
msg.Append("\"attributes\": {");
msg.Append(String.Format("\"comment\": \"{0}\"", comment));
msg.Append("}");
msg.Append("}");
msg.Append("}]");
wiPostDataContent = new System.Net.Http.StringContent(msg.ToString(),
Encoding.UTF8, "application/json-patch+json");
client.DefaultRequestHeaders.Accept.Add
(new System.Net.Http.Headers.MediaTypeWithQualityHeaderValue
("application/json-patch+json"));
client.DefaultRequestHeaders.Authorization =
new AuthenticationHeaderValue("Basic", Convert.ToBase64String
(System.Text.ASCIIEncoding.ASCII.GetBytes(getConnectionDetails())));
using (System.Net.Http.HttpResponseMessage response =
client.PatchAsync(SetURL(url), wiPostDataContent).Result)
{
response.EnsureSuccessStatusCode();
string ResponseContent = await response.Content.ReadAsStringAsync();
responseString = ResponseContent;
}
}
}
catch (Exception ex)
{
Console.WriteLine(ex.ToString());
Console.ReadLine();
}
Points of Interest
You can have a look at the application in more detail:
- Published version from the online site
- See the code within the downloadable
- Look at the code within the GitHub repo
Published Application: http://bugs.coopsmill.com
GitHUB: https://github.com/chriscooper01/VSODesktop.git
The API Documentation: https://www.visualstudio.com/en-us/docs/integrate/api/overview
History
- 28th June, 2016: Initial version