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

如何在C#中获取Azure DevOps REST API的延续令牌以获取所有测试运行?

在C#中通过Azure DevOps REST API获取带延续令牌的所有测试运行

虽然官方客户端库的GetTestRunsAsync()方法没有直接支持延续令牌,但你可以直接调用Azure DevOps的REST API端点来实现分页获取所有测试运行——该API本身支持通过延续令牌进行分页。

实现步骤

  • 初始请求时指定$top参数(最大可设为100),获取第一页测试运行数据,同时从响应的Link头中提取延续令牌。
  • 循环使用延续令牌发起后续请求,直到响应头中不再包含rel="next"的链接,即表示所有数据已获取完毕。

C#代码示例

using System;
using System.Collections.Generic;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Threading.Tasks;
using System.Web;

public class TestRunFetcher
{
    private readonly HttpClient _httpClient;
    private readonly string _organization;
    private readonly string _project;
    private readonly string _apiVersion = "6.0";
    private readonly string _personalAccessToken;

    public TestRunFetcher(string organization, string project, string personalAccessToken)
    {
        _organization = organization;
        _project = project;
        _personalAccessToken = personalAccessToken;

        _httpClient = new HttpClient();
        _httpClient.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
        // 设置PAT认证
        var base64Token = Convert.ToBase64String(System.Text.Encoding.ASCII.GetBytes($":{_personalAccessToken}"));
        _httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Basic", base64Token);
    }

    public async Task<List<dynamic>> GetAllTestRunsAsync()
    {
        var allTestRuns = new List<dynamic>();
        string continuationToken = null;
        const int pageSize = 100;

        do
        {
            var requestUri = BuildRequestUri(pageSize, continuationToken);
            var response = await _httpClient.GetAsync(requestUri);
            response.EnsureSuccessStatusCode();

            // 获取测试运行数据
            var pageData = await response.Content.ReadAsAsync<dynamic>();
            allTestRuns.AddRange(pageData.value);

            // 解析Link头获取延续令牌
            continuationToken = ExtractContinuationToken(response.Headers);

        } while (!string.IsNullOrEmpty(continuationToken));

        return allTestRuns;
    }

    private string BuildRequestUri(int pageSize, string continuationToken)
    {
        var uriBuilder = new UriBuilder($"https://dev.azure.com/{_organization}/{_project}/_apis/test/runs");
        var query = HttpUtility.ParseQueryString(uriBuilder.Query);
        query["api-version"] = _apiVersion;
        query["$top"] = pageSize.ToString();
        if (!string.IsNullOrEmpty(continuationToken))
        {
            query["continuationToken"] = continuationToken;
        }
        uriBuilder.Query = query.ToString();
        return uriBuilder.ToString();
    }

    private string ExtractContinuationToken(HttpResponseHeaders headers)
    {
        if (!headers.TryGetValues("Link", out var linkValues))
        {
            return null;
        }

        foreach (var link in linkValues)
        {
            // Link头格式示例: <https://xxx?continuationToken=abc>; rel="next"
            var parts = link.Split(';');
            if (parts.Length < 2 || !parts[1].Trim().Equals("rel=\"next\"", StringComparison.OrdinalIgnoreCase))
            {
                continue;
            }

            var uriPart = parts[0].Trim().Trim('<', '>');
            var uri = new Uri(uriPart);
            var queryParams = HttpUtility.ParseQueryString(uri.Query);
            return queryParams["continuationToken"];
        }

        return null;
    }
}

关键说明

  • 认证方式:示例中使用个人访问令牌(PAT)进行认证,确保你的PAT拥有TestManagement.Read权限。
  • 分页参数:$top参数控制每页返回的最大数据量,最大值为100,设置合理的页大小可以减少请求次数。
  • 延续令牌解析:响应的Link头中包含下一页的链接,从中提取continuationToken参数即可发起下一页请求。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.24 16:18:35