diff --git a/MSStore.API/Packaged/Models/PagedResponse.cs b/MSStore.API/Packaged/Models/PagedResponse.cs index 9213ee1..0ab27f0 100644 --- a/MSStore.API/Packaged/Models/PagedResponse.cs +++ b/MSStore.API/Packaged/Models/PagedResponse.cs @@ -2,11 +2,13 @@ // Licensed under the MIT License. using System.Collections.Generic; +using System.Text.Json.Serialization; namespace MSStore.API.Packaged.Models { public class PagedResponse { + [JsonPropertyName("@nextLink")] public string? NextLink { get; set; } public List? Value { get; set; } public int TotalCount { get; set; } diff --git a/MSStore.API/Packaged/StorePackagedAPI.cs b/MSStore.API/Packaged/StorePackagedAPI.cs index 585870c..67e062e 100644 --- a/MSStore.API/Packaged/StorePackagedAPI.cs +++ b/MSStore.API/Packaged/StorePackagedAPI.cs @@ -5,7 +5,9 @@ using System.Collections.Generic; using System.Diagnostics.CodeAnalysis; using System.Globalization; +using System.Linq; using System.Net.Http; +using System.Runtime.CompilerServices; using System.Security.Cryptography.X509Certificates; using System.Text; using System.Text.Json; @@ -219,8 +221,7 @@ public async Task> GetApplicationsAsync(CancellationT { try { - var devCenterApplicationsResponse = await GetDevCenterApplicationsAsync(0, 100, ct); // TODO: pagination - return devCenterApplicationsResponse.Value ?? []; + return await GetAllPagesAsync(GetDevCenterApplicationsAsync, ct).ToListAsync(ct); } catch (Exception error) { @@ -384,8 +385,7 @@ public async Task> GetFlightsAsync(string productId, Cance { try { - var devCenterFlightsResponse = await GetFlightsAsync(productId, 0, 100, ct); // TODO: pagination - return devCenterFlightsResponse.Value ?? []; + return await GetAllPagesAsync((skip, top, token) => GetFlightsAsync(productId, skip, top, token), ct).ToListAsync(ct); } catch (Exception error) { @@ -663,5 +663,27 @@ public async Task FinalizePackageRolloutAsync(string productId, SourceGenerationContext.GetCustom().PackageRollout, ct); } + + private static async IAsyncEnumerable GetAllPagesAsync(Func>> pageFunc, [EnumeratorCancellation] CancellationToken ct = default) + { + int skip = 0; + const int top = 100; + PagedResponse? lastPage; + do + { + ct.ThrowIfCancellationRequested(); + + lastPage = await pageFunc(skip, top, ct); + skip += lastPage.Value?.Count ?? 0; + + foreach (var item in lastPage.Value ?? []) + { + ct.ThrowIfCancellationRequested(); + + yield return item; + } + } + while (!string.IsNullOrEmpty(lastPage.NextLink) && lastPage.Value?.Count > 0 && (lastPage.TotalCount <= 0 || skip < lastPage.TotalCount)); + } } }