I have the following code: It works completely as expected, but I feel there is a better way to refactor it out.
The flow is as follows:
- Call the end point with 1 page
- Get the total number of results.
- If total count of items more than
itemsPerPage
. - Call the API more times till results from all pages are returned, join them together as single invoice list
- Append with initial request and send back.
Do I need GetAllInvoices
function? Reason it is kept there is because I believe the responsibility of calling each pages of API does not belong to main function.
public async Task<IEnumerable<Invoice>> GetAllInvoicesAsync()
{
const string endPoint = @"foo/{0}/invoices?pageNum={1}&itemsPerPage={2}";
const int itemsPerPage = xxx;
InvoiceCollection response = await _apiClient
.GetAsync<InvoiceCollection>(string.Format(endPoint, _apiClient.OrgId, 1, itemsPerPage));
if (response?.TotalCount > itemsPerPage)
{
var allInvoices = (await GetAllInvoices(endPoint,response.TotalCount, itemsPerPage))
.SelectMany(i => i.Invoices?? Enumerable.Empty<Invoice>());
response.Invoices = (response.Invoices ?? Enumerable.Empty<Invoice>()).Concat(allInvoices);
}
return response?.Invoices;
}
private async Task<List<InvoiceCollection>> GetAllInvoices(string endPoint,int totalCount, int itemsPerPage)
{
var totalPages = (int)Math.Ceiling(totalCount / (double)itemsPerPage);
var tasks = new List<Task<InvoiceCollection>>();
for (int currentPage = 2; currentPage<=totalPages;currentPage++)
{
tasks.Add(_apiClient
.GetAsync<InvoiceCollection>(string.Format(endPoint, _apiClient.OrgId, currentPage, itemsPerPage)));
}
var response = new List<InvoiceCollection>(await Task.WhenAll(tasks));
return response;
}
public class InvoiceCollection
{
[JsonProperty("foo")]
public IEnumerable<Invoice> Invoices { get; set; }
public int TotalCount { get; set; }
}