使用 API for Visual Studio Team Services 添加附件(之前是 Visual Studio Online)
Posted
技术标签:
【中文标题】使用 API for Visual Studio Team Services 添加附件(之前是 Visual Studio Online)【英文标题】:Adding Attachment using API for Visual Studio Team Services (was Visual Studio Online) 【发布时间】:2016-06-13 17:28:23 【问题描述】:我正在创建一个简单的 winform 应用程序,它可以使用提供的 API 在我的 Visual Studio Team Services 敏捷工作流中创建新的错误项。 The API Documentation
目前它可以创建一个新的bug,带有标题、标签和描述。
我希望能够添加文件附件,但由于某种原因这不起作用。
创建错误的代码如下
private static void createInitailItemPostObject()
AddUpdateProp("/fields/System.Title", newTaskItem.Title);
AddUpdateProp("/fields/System.Tags", newTaskItem.Tags);
AddUpdateProp("/fields/System.Description", newTaskItem.Description);
AddUpdateProp("/fields/System.History", "Upload first file");
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);
JSon 调用通过以下代码完成
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);
要添加附件,我似乎无法将以下代码转换为像我当前的代码一样工作。
function readBlob()
var files = document.getElementById('fileselect').files;
if (!files.length)
alert('Please select a file!');
return;
var file = files[0];
var filename = file.name;
var reader = new FileReader();
reader.onloadend = function (evt)
if (evt.target.readyState == FileReader.DONE)
// Post file content to server
$.ajax(
url: "http://fabrikam.visualstudio.com/DefaultCollection/_apis/wit/attachments?filename=" + filename + "&api-version=1.0",
data: evt.target.result,
processData: false,
contentType: "application/json",
type: "POST"
);
;
reader.readAsArrayBuffer(file);
还有其他人能够做到这一点吗?
我使用的 URL 是下面调用 API 的 URL
“https://[ACCOUNT].visualstudio.com/DefaultCollection/[Project]/_apis/wit/attachments?fileName=Test&api-version=1.0”
【问题讨论】:
【参考方案1】:下面的程序会在 VSO 中创建一个 Bug,并在 Bug 中附加一个附件。
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Configuration;
using OpenQA.Selenium;
using OpenQA.Selenium.Chrome;
using Logger;
using Microsoft.TeamFoundation.WorkItemTracking.WebApi;
using Microsoft.TeamFoundation.WorkItemTracking.WebApi.Models;
using Microsoft.VisualStudio.Services.Common;
using Microsoft.VisualStudio.Services.WebApi.Patch.Json;
using Microsoft.VisualStudio.Services.WebApi.Patch;
using Microsoft.VisualStudio.Services.WebApi;
using System.Net.Http.Headers;
using System.Net.Http;
using Newtonsoft.Json;
using System.IO;
using System.Collections;
using Newtonsoft.Json.Linq;
namespace CreateABugInVSOProgrammatically
static class ReportBug
static string _uri;
static string _personalAccessToken;
static string _project;
static string PathOfAttachment;
public static List<Params> ListParams;
static ReportBug()
_uri = ConfigurationManager.AppSettings["DynamicsUrl"];
_personalAccessToken = GetDecodedToken(ConfigurationManager.AppSettings["PAT"]);
_project = ConfigurationManager.AppSettings["ProjectName"];
private static List<Params> GetAllField(Fields fields)
List<Params> list = new List<Params>();
list.Add(new Params() Path = "/fields/System.Title", Value = fields.Title );
list.Add(new Params() Path = "/fields/Microsoft.VSTS.TCM.ReproSteps", Value = fields.ReproSteps );
list.Add(new Params() Path = "/fields/Microsoft.VSTS.Common.Priority", Value = fields.Priority );
list.Add(new Params() Path = "/fields/Microsoft.VSTS.Common.Severity", Value = fields.Severity );
list.Add(new Params() Path = "/fields/Microsoft.VSTS.Common.Issue", Value = fields.Issue );
list.Add(new Params() Path = "/fields/Microsoft.VSTS.MPT.Source", Value = fields.Source );
list.Add(new Params() Path = "/fields/System.State", Value = fields.State );
list.Add(new Params() Path = "/fields/Microsoft.VSTS.Common.HowFoundCategory", Value = fields.HowFoundCategory );
list.Add(new Params() Path = "/fields/Microsoft.VSTS.Common.Regression", Value = fields.Regression );
list.Add(new Params() Path = "/fields/System.AttachedFileCount", Value = fields.AttachedFileCount );
return list;
public static WorkItem CreateBugInVSO(IWebDriver driver, Fields fields)
try
PathOfAttachment = ScreenShotCapture.CaptureScreenShotOfCurrentBrowser(driver ,fields.PathOfFile);
ListParams.AddRange(GetAllField(fields));
Uri uri = new Uri(_uri);
string personalAccessToken = _personalAccessToken;
string project = _project;
VssBasicCredential credentials = new VssBasicCredential("", _personalAccessToken);
AttachmentReference attachment = UploadAttachment(uri, credentials);
ListParams.Add(new Params()
Path = "/relations/-",
Value = new
rel = "AttachedFile",
url = attachment.Url,
attributes = new comment = fields.Comments
);
JsonPatchDocument patchDocument = new JsonPatchDocument();
//add fields and their values to your patch document
foreach (var item in ListParams)
patchDocument.Add(
new JsonPatchOperation()
Operation = Operation.Add,
Path = item.Path,
Value = item.Value,
);
VssConnection connection = new VssConnection(uri, credentials);
WorkItemTrackingHttpClient workItemTrackingHttpClient = connection.GetClient<WorkItemTrackingHttpClient>();
WorkItem result = workItemTrackingHttpClient.CreateWorkItemAsync(patchDocument, project, "Bug").Result;
return result;
catch (AggregateException ex)
Log.Logger.Error("Error occurred while Creating bug in VSO" + ex);
return null;
// This method will upload attachment and return url for file and Id
private static AttachmentReference UploadAttachment(Uri uri, VssBasicCredential credentials)
try
VssConnection _tpc = new VssConnection(uri, credentials);
WorkItemTrackingHttpClient workItemTrackingHttpClient = _tpc.GetClient<WorkItemTrackingHttpClient>();
AttachmentReference attachment = workItemTrackingHttpClient.CreateAttachmentAsync(PathOfAttachment).Result;
// Save the attachment ID for the "download" sample call later
return attachment;
catch (Exception ex)
Log.Logger.Error("Error occurred while Attaching Attachment in bug" + ex);
return null;
public class Params
public string Path get; set;
public object Value get; set;
//This class contain all the fields that are mandatory to create a bug
public class Fields
public string Title get; set;
public string Priority get; set;
public string ReproSteps get; set;
public string Severity get; set;
public string Issue get; set;
public string Source get; set;
public string State get; set;
public string HowFoundCategory get; set;
public string Regression get; set;
public int AttachedFileCount get; set;
public string Comments get; internal set;
public string PathOfFile get; internal set;
【讨论】:
嗨,谢谢,这已经解决了我已经创建了一个我们现在使用的应用程序。我的代码在 GitHub 上,您可以将编译后的应用程序下载给我们。谢谢你【参考方案2】:正如您在示例代码中所见,您无需将项目放在 API 调用的 URL 中。尝试使用以下网址:
“https://[ACCOUNT].visualstudio.com/DefaultCollection/_apis/wit/attachments?fileName=Test&api-version=1.0”
【讨论】:
我已经看了好几个小时了。其他调用需要项目,但我猜附加文档不会存储在项目中。下一阶段,您将附件与任务错误链接。谢谢以上是关于使用 API for Visual Studio Team Services 添加附件(之前是 Visual Studio Online)的主要内容,如果未能解决你的问题,请参考以下文章
visual studio里面的vb编写for循环,怎么设置变步长循环?