使用 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 For MacOS 踩坑记

Visual Studio 2017 for Mac

使用Visual Studio 2013 For Java

visual studio里面的vb编写for循环,怎么设置变步长循环?

比较 Visual Studio 2015 和 Blend for Visual Studio [关闭]

Visual Studio 2013中使用Ribbon For WPF