如何在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
相关产品推荐
相关产品推荐

