C# 为什么在尝试向TFS发送REST请求时出现404错误?

C# 为什么在尝试向TFS发送REST请求时出现404错误?,c#,rest,tfs,C#,Rest,Tfs,我正试图通过RESTAPI在本地TFS中创建任务,但总是出现404错误。有人知道我是否使用了正确的URI,正确的URI是什么,或者我是否做了其他错误的事情吗 出于这个原因,我遵循了上的各种教程并下载了他们的示例项目。但这些都没有帮我摆脱我的404。 TFS的基本URI是正确的,我可以通过浏览器处理它 JsonPatchDocument createStoryRequest = new JsonPatchDocument(); createStoryRequest.Add( new

我正试图通过RESTAPI在本地TFS中创建任务,但总是出现404错误。有人知道我是否使用了正确的URI,正确的URI是什么,或者我是否做了其他错误的事情吗

出于这个原因,我遵循了上的各种教程并下载了他们的示例项目。但这些都没有帮我摆脱我的404。 TFS的基本URI是正确的,我可以通过浏览器处理它

JsonPatchDocument createStoryRequest = new JsonPatchDocument();
createStoryRequest.Add(
        new JsonPatchOperation()
        {
          Operation = Operation.Add,
          Path = "/fields/System.Title",
          Value = storyToCreate.Fields.Title
        }
    );

using (HttpClient client = new 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}", "", ApiCredentials.tfsAuthenticationToken))));
  Task postJsonTask = Task.Run(async () =>
  {
    using (HttpResponseMessage response = await client.PostAsJsonAsync(
      "https://my_tfs_server/tfs/DefaultCollection/_apis/wit/workitems/$task?api-version=4.1",
      createStoryRequest))
    {
      response.EnsureSuccessStatusCode();
      string responseBody = await response.Content.ReadAsStringAsync();
      System.Console.WriteLine(responseBody);
    }
  });
  Task.WaitAll(new Task[] { postJsonTask});
}
我希望在我的TFS上创建一个故事/任务/任何东西,但无论我尝试什么,我总是得到一个404

谢谢你的帮助

编辑1: 谢谢大家帮助我!解决方案是API的版本:TFS2018仅支持API版本4.0,并且在给出另一个API版本时,将给出所述的404错误。 并使用以下代码(以及RestSharp NuGet包):


根据4.1版的API说明,可以找到正确的POST命令:

POST https://{instance}/{collection}/{project}/_apis/wit/workitems/${type}?api-version=4.1
因此,与您的样本相比,我认为您错过了收集后的项目名称

所以应该是这样的:

using (HttpResponseMessage response = await client.PostAsJsonAsync(
      "https://my_tfs_server/tfs/DefaultCollection/PROJECTNAME/_apis/wit/workitems/$task?api-version=4.1",
      createStoryRequest))
    {
      response.EnsureSuccessStatusCode();
      string responseBody = await response.Content.ReadAsStringAsync();
      System.Console.WriteLine(responseBody);
    }
编辑
因此,必须调整URL以包含项目名称: “$task?api version=4.1”,其中“PROJECTNAME”应为团队项目的名称。
如果在没有项目名称的情况下使用,您似乎会得到一个404,如果您指定一个不存在的项目,您会得到一些错误,即该项目不存在

Edit2:
根据您的TFS版本,TFS与TFS 2018 RTM相关,根据github,TFS 2018 RTM支持版本4.0中的REST API。
到目前为止使用的示例使用的是api版本4.1,显然它不受支持。
RESTAPI 4.1之前的文档有点隐藏,但是这应该提供正确的规范。似乎您必须提供一个补丁请求:

PATCH https://{instance}/DefaultCollection/{project}/_apis/wit/workitems/${workItemTypeName}?api-version={version}
请求主体应包含JSON格式的字段值:

[
{
    "op": "add",
    "path": { string }
    "value": { string or int, depending on the field }
},
{
    "op": "add",
    "path": "/relations/-",
    "value":
    {
        "rel": { string },
        "url": { string },
        "attributes":
        {
            { name/value pairs }
        }
    }
}
]

因此,api版本应为4.0


EDIT3:(通过问题海报)我的媒体类型也错了。“application/json”将导致“错误请求”响应。正确的媒体类型是“application/json patch+json”。

你得到的是404,因为“找不到页面”就是404。你能点击浏览器上的URL吗?在tfs URL中,你是否也放了
:8080
?我得到了它以将项目列表返回给我。刚刚将行替换为:using(httpresponsemessageresponse=wait client.GetAsync(ApiCredentials.tfsBaseUri+“_api/projects”)@Liam No,我无法在浏览器中点击url:403禁止。(因为我打开了令牌身份验证,而我无法使用浏览器进行令牌身份验证)@Shaykibaramczyk否,因为我使用令牌身份验证,它只在ssl上工作,这意味着正确的端口将是443。我试过了,结果完全一样。嗨!谢谢你抽出时间!是的,这正是我在描述中发布的链接。不幸的是,答案仍然是:404。嗨,对不起,我错过了那个链接。当然,您是否用实际的项目名称替换了“PROJECTNAME”字符串并进行了尝试?至少在我的Azure DevOps实例中,这是有效的,而离开ProjectName会导致像你一样的404。没问题,我很感谢能得到任何答案!我用我的项目名替换了项目名。在中间有空间的项目有问题吗?我的项目名是“示例项目”。你在使用云计算版本吗?我在本地使用它,2018版16.122.27102.1(Tfs2018)“返回404。很抱歉暂时放弃我的专业精神,但是:你这个了不起的混蛋!你做到了!(好吧,至少现在我得到了一个400:糟糕的请求)但那是认真的!现在,我只需要让json的东西工作,我是黄金!非常感谢你!
[
{
    "op": "add",
    "path": { string }
    "value": { string or int, depending on the field }
},
{
    "op": "add",
    "path": "/relations/-",
    "value":
    {
        "rel": { string },
        "url": { string },
        "attributes":
        {
            { name/value pairs }
        }
    }
}