You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用C#调用Azure DevOps REST API提交文件至分支遇Method Not Allowed错误

问题描述

调用PostAsync提交数据时收到Method Not Allowed错误,响应体提示:

The requested resource does not support http method 'POST'

需求是实现等效于创建本地分支、添加带内容的文件、git add、commit、push的操作,部署在本地服务器,查阅文档后认为接口应该支持POST请求。

提交代码:

public async Task<CreateCommitResponse> CreateCommitFileCommitAsync(string repositoryName, string branch, string fileContent, string comment, string fileName)
{
    var pat = m_serverPats[m_adoSspServer];

    // Retrieve repository info
    var repositoryInfos = await GetRepositoryByNameAsync(repositoryName);
    if (repositoryInfos == null)
    {
        Tools.LogError($"Could not get repository 'm_adoSspRepo' infos");
        return new CreateCommitResponse() { Created=false,ErrorMessage= $"Could not get repository 'm_adoSspRepo' infos" };
    }

    string endpoint = $"https://{m_adoSspServer}/{m_adoSspProject}/_apis/git/repositories/{repositoryInfos.Id}/pushes?api-version=7.1-preview.1";

    // Fetch the latest commit ID for the target branch
    var latestCommitId = await GetLatestCommitIdAsync(repositoryInfos.Id, branch);
    if (latestCommitId == null)
    {
        Tools.LogError($"Could not fetch the latest commit for branch '{branch}'");
        return new CreateCommitResponse() { Created = false, ErrorMessage = $"Could not fetch the latest commit for branch '{branch}'" };
    }

    // Create the first commit (e.g., adding a README.md file)
    var commitData = new
    {
        commits = new[]
        {
            new
            {
                comment = comment,
                changes = new[]
                {
                    new
                    {
                        changeType = "add",
                        item = new
                        {
                            path = $"/{fileName}"
                        },
                        newContent = new
                        {
                            content = fileContent,
                            contentType = "rawText"
                        }
                    }
                }
            }
        },
        refUpdates = new[]
        {
            new
            {
                name = $"refs/heads/{branch}", // Creating the main branch
                oldObjectId = latestCommitId
            }
        }
    };

    // Serialize the commit payload
    string jsonContent = JsonConvert.SerializeObject(commitData);

    using (var client = new HttpClient())
    {
        // Set up HTTP client
        client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
        client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Basic",
            Convert.ToBase64String(Encoding.ASCII.GetBytes($":{pat}")));

        // Make the POST request to create the first commit and the main branch
        var response = await client.PostAsync(endpoint, new StringContent(jsonContent, Encoding.UTF8, "application/json"));

        if (response.StatusCode != System.Net.HttpStatusCode.OK)
        {
            Tools.LogError($"Failed to create commit and branch: {response.StatusCode} - {response.ReasonPhrase}");
            return new CreateCommitResponse() { Created = false, ErrorMessage = $"Failed to create commit and branch: {response.StatusCode} - {response.ReasonPhrase}" };
        }
    }
    return new CreateCommitResponse() { Created = true, ErrorMessage = null };
}

获取分支最新Commit ID的代码:

private async Task<string?> GetLatestCommitIdAsync(string repositoryId, string branchName)
{
    string endpoint = $"https://{m_adoSspServer}/{m_adoSspProject}/_apis/git/repositories/{repositoryId}/commits?searchCriteria.itemVersion.version={branchName}&$top=1&api-version=7.1-preview.1";

    using (var client = new HttpClient())
    {
        // Set up HTTP client with authorization headers
        client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
        client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Basic",
            Convert.ToBase64String(Encoding.ASCII.GetBytes($":{m_serverPats[m_adoSspServer]}")));

        // Make the GET request to retrieve the latest commit ID
        var response = await client.GetAsync(endpoint);
        if (response.StatusCode != System.Net.HttpStatusCode.OK)
        {
            Tools.LogError($"Failed to retrieve latest commit ID for branch '{branchName}': {response.StatusCode} - {response.ReasonPhrase}");
            return null;
        }

        var content = await response.Content.ReadAsStringAsync();
        dynamic result = JsonConvert.DeserializeObject(content);
        JArray valuesArray = (JArray)result["value"];
        string commitId = valuesArray[0]["commitId"].ToString();
        return commitId;
    }
}

问题分析与解决

1. 分支创建逻辑错误

你的需求是创建新分支,但当前代码中GetLatestCommitIdAsync是去查询目标分支的最新Commit ID——如果这个分支在远程还不存在,这个接口会返回空,导致流程中断。正确的做法是:

  • 基于一个已存在的基础分支(比如main/master)获取最新Commit ID,作为新分支的起点;
  • 如果是从空仓库创建第一个分支,oldObjectId应设为全0的SHA值:0000000000000000000000000000000000000000

2. API版本选择问题

你使用的7.1-preview.1是预览版API,可能存在接口行为不稳定或路径变更的情况。建议切换到稳定版API(比如7.0或7.2),Pushes API的POST方法在稳定版中是明确支持的。

3. 错误信息排查不充分

当前代码仅打印了状态码和原因短语,没有读取响应体的详细错误内容。修改错误处理逻辑,添加读取响应体的代码:

if (response.StatusCode != System.Net.HttpStatusCode.OK)
{
    var errorContent = await response.Content.ReadAsStringAsync();
    Tools.LogError($"Failed to create commit and branch: {response.StatusCode} - {response.ReasonPhrase}. Details: {errorContent}");
    return new CreateCommitResponse() { Created = false, ErrorMessage = $"Failed to create commit and branch: {response.StatusCode} - {response.ReasonPhrase}. Details: {errorContent}" };
}

这能帮你获取更具体的服务器错误提示,精准定位问题根源。

4. 分支不存在时的refUpdates配置

如果是创建全新分支,refUpdates中的oldObjectId需要设置为你要基于的父Commit ID(比如基础分支的最新ID),而不是目标分支的ID(因为目标分支还不存在)。

5. 路径格式问题

检查path = $"/{fileName}"是否符合仓库的路径规范,有些场景下不需要开头的斜杠,需确保路径相对于仓库根目录的正确性。


内容的提问来源于stack exchange,提问作者pf12345678910

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.13 16:21:06