Страница через коллекцию с помощью пакетов SDK Microsoft Graph

По соображениям производительности коллекции сущностей часто разбиваются на страницы, и каждая страница возвращается с URL-адресом следующей страницы. Класс PageIterator упрощает использование страничных коллекций. PageIterator обрабатывает перечисление текущей страницы и запрос последующих страниц автоматически.

Кроме того, можно использовать @odata.nextLink свойство для запроса последующих страниц вручную.

Заголовки запросов

Если вы отправляете дополнительные заголовки запросов в исходном запросе, эти заголовки не включаются по умолчанию в последующие запросы страницы. Если эти заголовки требуется отправлять в последующие запросы, их необходимо явно настроить.

Итерации по всем сообщениям

В следующем примере показано перебор всех сообщений в почтовом ящике пользователя.

Совет

В этом примере задается небольшой размер страницы с top помощью параметра для демонстрационных целей. Вы можете задать размер страницы до 999, чтобы свести к минимуму количество необходимых запросов.

var messages = await graphClient.Me.Messages
    .GetAsync(requestConfiguration =>
    {
        requestConfiguration.QueryParameters.Top = 10;
        requestConfiguration.QueryParameters.Select =
            ["sender", "subject", "body"];
        requestConfiguration.Headers.Add(
            "Prefer", "outlook.body-content-type=\"text\"");
    });

if (messages == null)
{
    return;
}

var pageIterator = PageIterator<Message, MessageCollectionResponse>
    .CreatePageIterator(
        graphClient,
        messages,
        // Callback executed for each item in
        // the collection
        (msg) =>
        {
            Console.WriteLine(msg.Subject);
            return true;
        },
        // Used to configure subsequent page
        // requests
        (req) =>
        {
            // Re-add the header to subsequent requests
            req.Headers.Add("Prefer", "outlook.body-content-type=\"text\"");
            return req;
        });

await pageIterator.IterateAsync();

Остановка и возобновление итерации

В некоторых сценариях для выполнения других действий требуется остановить процесс итерации. Можно приостановить итерацию, вернувшись false из обратного вызова итерации. Итерацию можно возобновить, вызвав resume метод в PageIterator.

int count = 0;
int pauseAfter = 25;

var messages = await graphClient.Me.Messages
    .GetAsync(requestConfiguration =>
    {
        requestConfiguration.QueryParameters.Top = 10;
        requestConfiguration.QueryParameters.Select =
            ["sender", "subject"];
    });

if (messages == null)
{
    return;
}

var pageIterator = PageIterator<Message, MessageCollectionResponse>
    .CreatePageIterator(
        graphClient,
        messages,
        (msg) =>
        {
            Console.WriteLine(msg.Subject);
            count++;
            // If we've iterated over the limit,
            // stop the iteration by returning false
            return count < pauseAfter;
        });

await pageIterator.IterateAsync();

while (pageIterator.State != PagingState.Complete)
{
    Console.WriteLine("Iteration paused for 5 seconds...");
    await Task.Delay(5000);
    // Reset count
    count = 0;
    await pageIterator.ResumeAsync();
}

Запрос последующих страниц вручную

В качестве альтернативы использованию класса PageIterator можно вручную проверка ответ для @odata.nextLink свойства и запросить следующую страницу.

var messages = await graphClient.Me.Messages
    .GetAsync(requestConfiguration =>
    {
        requestConfiguration.QueryParameters.Top = 10;
    });

while (messages?.Value != null)
{
    foreach (var message in messages.Value)
    {
        Console.WriteLine(message.Subject);
    }

    // If OdataNextLink has a value, there is another page
    if (!string.IsNullOrEmpty(messages.OdataNextLink))
    {
        // Pass the OdataNextLink to the WithUrl method
        // to request the next page
        messages = await graphClient.Me.Messages
            .WithUrl(messages.OdataNextLink)
            .GetAsync();
    }
    else
    {
        // No more results, exit loop
        break;
    }
}