Compartilhar via


Percorrer uma coleção com os SDKs do Microsoft Graph

Por motivos de desempenho, as coleções de entidades são frequentemente divididas em páginas e cada página é devolvida com um URL para a página seguinte. A classe PageIterator simplifica o consumo de coleções paginadas. O PageIterator processa a enumeração da página atual e o pedido de páginas subsequentes automaticamente.

Em alternativa, pode utilizar a @odata.nextLink propriedade para pedir manualmente páginas subsequentes.

Cabeçalhos de solicitação

Se enviar cabeçalhos de pedido adicionais no pedido inicial, esses cabeçalhos não serão incluídos por predefinição nos pedidos de página subsequentes. Se esses cabeçalhos precisam ser enviados em solicitações subsequentes, você deve defini-los explicitamente.

Iterar em todas as mensagens

O exemplo seguinte mostra a iteração de todas as mensagens na caixa de correio de um utilizador.

Dica

Este exemplo define um tamanho de página pequeno com o top parâmetro para fins de demonstração. Pode definir o tamanho da página até 999 para minimizar o número de pedidos necessários.

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();

Parar e retomar a iteração

Alguns cenários requerem a paragem do processo de iteração para efetuar outras ações. É possível colocar a iteração em pausa ao regressar false da chamada de retorno de iteração. A iteração pode ser retomada ao chamar o resume método no 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();
}

Pedir páginas subsequentes manualmente

Como alternativa à utilização da classe PageIterator, pode marcar manualmente a resposta de uma @odata.nextLink propriedade e pedir a página seguinte.

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;
    }
}

Tratamento de erros

Evitar erros directoryPageTokenNotFoundException

Ao paginar grandes conjuntos de dados, poderá deparar-se com o erro, o DirectoryPageTokenNotFoundException que impede a aplicação cliente de obter com êxito as páginas subsequentes. Este erro ocorre quando a aplicação cliente utiliza um token de uma operação de repetição para pedir a página seguinte de resultados.

Para evitar este erro, não utilize tokens de operações de repetição para pedidos de página subsequentes, uma vez que estes tokens não são garantidos como válidos para pedidos futuros. Em vez disso, mantenha o token da última resposta bem-sucedida e utilize-o para o pedido de página seguinte. Por conseguinte, o @odata.nextLink valor utilizado para a repetição deve ser utilizado para o pedido de página subsequente.

Cenário de exemplo

  1. Obtenha a Página 1 e receba um token "Token1".
  2. Utilize "Token1" para pedir a Página 2.
  3. Se encontrar um erro de rede, repita o pedido.
  4. Durante a repetição, recebe um novo token "RetryToken".
  5. Não utilize "RetryToken" para pedir a Página 3, pois pode causar o DirectoryPageTokenNotFoundException erro.
  6. Em vez disso, utilize "Token1" (o token da última resposta sem repetição bem-sucedida) para pedir a Página 3.