【问题标题】:Creating a new Team Project using the REST api使用 REST api 创建新的团队项目
【发布时间】:2015-10-23 00:17:15
【问题描述】:

我整个星期都在反对这个。 使用 REST api 创建一个新的团队项目。 我在任何地方看到的响应都是一样的,而且总是涉及到使用命令行和 xml。

但是为什么呢?

在 Visual Studio 在线页面上可以找到:

https://www.visualstudio.com/en-us/integrate/api/tfs/projects

(具体看标有“创建团队项目”的部分)

如果不能使用,为什么还会存在呢? 还是我错过了什么?

如果有人知道使用它的任何示例,我将不胜感激。

我一直在使用 Microsoft.TeamFoundation.WorkItemTracking.Client 命名空间等...并且一直很高兴地为项目创建新的工作项

我什至还设法使用 API 来下拉项目列表。 使用此示例中的代码(滚动到页面底部)

https://www.visualstudio.com/en-us/integrate/get-started/rest/basics

但我终生无法发布新的团队项目。

此时我愿意接受任何建议,我在这里创建了一个帐户只是为了询问(我喜欢这个网站):(

根据要求,一些代码:

static async Task<string> PostProjectAsync(HttpClient _client, string _apiUrl, string _apiVersion)
    {
        var responseBody = string.Empty;

        HttpContent hc = new StringContent(@"
            {
                ""name"": ""Testprojectfromconsole"",
                ""description"": ""Posted from console application using the tfs API""
            }
            ");
        //TODO: make a class that matches the json layout that the api is expecting
        //then see if you have any better luck with that instead of this horrid horrid mess

        ProjectPost newproj = new ProjectPost();
        newproj.Name = @"Test Project -From console";
        newproj.Description = @"Hopefully this has been posted from the console app, delete it later on if need be.";
        newproj.Capabilities.VersionControl.SourceControlType = @"TFS"; //probably wrong
        newproj.Capabilities.ProcessTemplate.TemplateTypeId = @"default"; //also probably wrong

        string json = JsonConvert.SerializeObject(newproj);

        try
        {
            using (HttpResponseMessage response = _client.PostAsync(_apiUrl + _apiVersion, hc).Result)
            {
                response.EnsureSuccessStatusCode();
                responseBody = await response.Content.ReadAsStringAsync();
            }
        }
        catch (Exception ex)
        {
            Console.WriteLine(ex.ToString());
        }

        return responseBody;
    }

目前我将一个名为“hc”的 HttpContent 传递给 postasync,但如果我将其切换为 json 对象,postasync 将停止工作(因为它想要 httpcontent 而不是 json)

在调用这个方法之前,客户端是这样设置的:

client.DefaultRequestHeaders.Accept.Add(
                new System.Net.Http.Headers.MediaTypeWithQualityHeaderValue("application/json"));



            //Set alternate credentials
            client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Basic",
                Convert.ToBase64String(
                    System.Text.ASCIIEncoding.ASCII.GetBytes(
                        string.Format("{0}:{1}", ALTUSERNAME, ALTPASSWORD))));

            Console.WriteLine("<--------------Getting projects from tfs!-------------->");
            Console.WriteLine("<----------------Hold on to your butts!---------------->");

            responseBody = await GetAsync(client, BASEURL + "projects", APIVERS);

            Console.WriteLine(responseBody.ToString());

            Console.WriteLine("<----------------Making a new project!----------------->");
            Console.WriteLine("<----------------Hold on to your butts!---------------->");

            responseBody = await PostProjectAsync(client, BASEURL + "projects", APIVERS);

            Console.WriteLine(responseBody.ToString());

哦,网址是这样的:

static string PN1 = @"Test Project -From Web";
    static string PN2 = @"Another Test Project -From Web";
    static string COL = @"DefaultCollection";

    static string BASEURL = "https://{0}.visualstudio.com/DefaultCollection/_apis/";

    // Get the alternate credentials that you'll use to access the Visual Studio Online account.
    static string ALTUSERNAME = "myusername";
    static string ALTPASSWORD = "mypassword!";



    //Your visual studio account name
    static string ACCOUNT = "ourserver";

    //Api version query parameter
    static string APIVERS = "?api-version=1.0";

【问题讨论】:

  • 您能否详细说明您尝试过的方法以及失败的原因?
  • 当我通过 httpContent 时,我的控制台输出告诉我错误代码 405,调查后表示方法不允许:/
  • 您可以尝试将 sourceControlType 更改为“TfVc”吗?
  • 是的!谢谢Lukkha (^_^)

标签: rest tfs azure-devops


【解决方案1】:

这是我使用的代码。这是为 .net 3.5 制作的,但我找到了 .net 4.5.1 的解决方案:

private const string PROJECT_TEMPLATE_AGILE = "adcc42ab-9882-485e-a3ed-7678f01f66bc";
private const string PROJECT_TEMPLATE_SCRUM = "6b724908-ef14-45cf-84f8-768b5384da45";
private const string PROJECT_TEMPLATE_CMMI = "27450541-8e31-4150-9947-dc59f998fc01";

VsoTeamProject project = new VsoTeamProject(
                        newFolderName,
                        comment,
                        new Capabilities(new VersionControl("Tfvc"), new ProcessTemplate(projectTemplateId)));

CreateTeamProject(project, "POST", false); // this calls PostResponse method

这里是主要方法:

private void PostResponse(VsoTeamProject project, string method, bool useProjectName)
        {
            string projectState = "wellFormed";
            if(method.Equals("DELETE"))
            {
                projectState = "deleting";
            }

            var requestUriString = ConstructUrl(
                useProjectName ? project.TeamProjectId : string.Empty,
                string.Empty,
                new Dictionary<string, object>());
            var httpWebRequest = (HttpWebRequest)WebRequest.Create(requestUriString);
            httpWebRequest.ContentType = "application/json";
            httpWebRequest.Method = method;
            string autorization = TFSImplementor.LoginName + ":" + TFSImplementor.Password;
            byte[] binaryAuthorization = Encoding.UTF8.GetBytes(autorization);
            autorization = Convert.ToBase64String(binaryAuthorization);
            autorization = "Basic " + autorization;
            httpWebRequest.Headers.Add("AUTHORIZATION", autorization);

            if(method.Equals("POST"))
            {
                using(var streamWriter = new StreamWriter(httpWebRequest.GetRequestStream()))
                {
                    string json = JsonConvert.SerializeObject(project);

                    streamWriter.Write(json);
                }
            }

            try
            {
                var httpResponse = (HttpWebResponse)httpWebRequest.GetResponse();
                if(httpResponse.StatusCode == HttpStatusCode.Accepted)
                {
                    Task<WebResponse> responseTask = Task.Factory.FromAsync<WebResponse>(httpWebRequest.BeginGetResponse, httpWebRequest.EndGetResponse, null);
                    using(var responseStream = responseTask.Result.GetResponseStream())
                    {
                        var reader = new StreamReader(responseStream);
                        var t = reader.ReadToEnd();
                        ProjectStatus json = JsonConvert.DeserializeObject<ProjectStatus>(t);
                        if(json.status.Equals("queued"))
                        {
                            while(true)
                            {
                                if(CheckTeamProjectState(project.ProjectName, true, projectState))
                                {
                                    break;
                                }
                            }
                        }
                    }
                }
            }
            catch(WebException e)
            {
                using(WebResponse response = e.Response)
                {
                    using(Stream data = response.GetResponseStream())
                    {
                        using(var reader = new StreamReader(data))
                        {
                            string text = reader.ReadToEnd();
                            Logger.Error(text);
                            Logger.Exception(e);
                            if(method.Equals("DELETE"))
                            {
                                throw new Exception("Failed to delete project, check log for more details");
                            }

                            throw new Exception("Failed to create project, check log for more details");
                        }
                    }
                }
            }
        }

以下是您可以使用的类:

private class VsoTeamProject
{
    #region Fields

    private readonly string m_name;

    private readonly string m_comment;

    private readonly string m_teamProjectId;

    private readonly Capabilities m_capabilities;

    #endregion

    #region Constructors

    public VsoTeamProject(string teamProjectId, string name)
    {
        m_teamProjectId = teamProjectId;
        m_name = name;
    }

    public VsoTeamProject(string projectName, string description, Capabilities capabilities)
    {
        m_name = projectName;
        m_comment = description;
        m_capabilities = capabilities;
    }

    #endregion

    #region Properties

    [JsonProperty("name")]
    protected internal string ProjectName
    {
        get
        {
            return m_name;
        }
    }

    [JsonProperty("description")]
    protected internal string Description
    {
        get
        {
            return m_comment;
        }
    }

    protected internal string TeamProjectId
    {
        get
        {
            return m_teamProjectId;
        }
    }

    [JsonProperty("capabilities")]
    protected internal Capabilities Capabilities
    {
        get
        {
            return m_capabilities;
        }
    }

    #endregion
}

private class ProjectStatus
{
    public string id { get; set; }

    public string status { get; set; }

    public string url { get; set; }

    public string name { get; set; }

    public string state { get; set; }

    public string message { get; set; }
}

private class Capabilities
{
    public Capabilities(VersionControl versionControl, ProcessTemplate template)
    {
        VersionControl = versionControl;
        ProcessTemplate = template;
    }

    [JsonProperty("processTemplate")]
    public ProcessTemplate ProcessTemplate { get; private set; }

    [JsonProperty("versioncontrol")]
    public VersionControl VersionControl { get; private set; }
}

private class VersionControl
{
    public VersionControl(object type)
    {
        SourceControlType = type;
    }

    [JsonProperty("sourceControlType")]
    public object SourceControlType { get; private set; }
}

private class ProcessTemplate
{
    public ProcessTemplate(string templateTypeId)
    {
        TemplateTypeId = templateTypeId;
    }

    [JsonProperty("templateTypeId")]
    public string TemplateTypeId { get; private set; }
}

我也有这个 PostResponse 方法用于从 VSO 中删除项目。它就像一个魅力。

【讨论】:

    【解决方案2】:

    我不知道您是否仍然对这个问题的答案感兴趣(现在已经 3 年了),但问题不在于您的代码:而是文档。

    当您使用 API 创建项目时,文档中列出的字段不会告诉您所有必填字段。

    如果您在 Postman 中尝试过请求,您会得到以下结果:

    消息:“提供给项目创建的项目信息无效。您必须提供所有且仅这些属性/功能:名称、描述、可见性、capabilities.versioncontrol.sourceControlType、capabilities.processTemplate.templateTypeId。”

    其中项目模板类型id = 6b724908-ef14-45cf-84f8-768b5384da45

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2016-09-03
      • 1970-01-01
      • 2016-02-13
      • 2012-12-30
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多