You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

MS Graph v5.42.0分页获取邮件时修改页大小无效问题咨询

MS Graph v5.42.0分页获取邮件时无法修改页大小的问题

我使用MS Graph v5.42.0分页获取邮件,希望从包含70封邮件的文件夹中获取50封邮件。第一页按预期返回30封,但将第二页的页大小(Top)改为20后,仍返回30封。请问分页时无法修改页大小吗?

问题代码

int maxItemSize = 50;
int pageSize = 30;
if (maxItemSize <= pageSize)
    pageSize = maxItemSize;

string itemSearchFilter = GetItemFilters(messageClasses, onlyMailsWithAttachments,
    ignoredDomains, archiveSize, archiveDate, archiveAge, setFilterIgnoreSignedItems, setFilterNotKdxArchived, setFilterKdxArchived);

string expandValue = string.Format("singleValueExtendedProperties($filter = id eq '{0}' or id eq '{1}' or id eq '{2}' or id eq '{3}' or id eq '{4}')",
    MessageClassPropertyID1, DisplayToPropertyID1, DisplayCcPropertyID1, NativeBodyPropertyID, MessageSizePropertyID1);

List<Message> messages = new List<Message>();

var messagesResponse = await GraphServiceClient
    .Users[CurrentMailBoxAddress]
    .MailFolders[FolderId]
    .Messages
    .GetAsync((requestConfiguration) =>
    {
        requestConfiguration.QueryParameters.Top = pageSize;
        requestConfiguration.QueryParameters.Expand = new string[] { expandValue };
        requestConfiguration.QueryParameters.Filter = itemSearchFilter;
    });

while (messagesResponse.Value != null)
{
    messages.AddRange(messagesResponse.Value);

    if (messages.Count() >= maxItemSize)
        break;
    else
    {
        int messagesToBeRetrieved = maxItemSize - messages.Count();
        if (messagesToBeRetrieved <= pageSize)
        {
            // Resets the page size for the last request
            pageSize = messagesToBeRetrieved;
        }

        // If OdataNextLink has a value, there is another page
        if (!string.IsNullOrEmpty(messagesResponse.OdataNextLink))
        {
            messagesResponse = await GraphServiceClient
                .Users[CurrentMailBoxAddress]
                .MailFolders[FolderId]
                .Messages
                .WithUrl(messagesResponse.OdataNextLink)
                .GetAsync((requestConfiguration) =>
                {
                    requestConfiguration.QueryParameters.Top = pageSize;
                    requestConfiguration.QueryParameters.Expand = new string[] { expandValue };
                    requestConfiguration.QueryParameters.Filter = itemSearchFilter;
                });
        }
        else
        {
            // No more results, exit loop
            break;
        }
    }
}

原因分析

当使用WithUrl()方法传入@odata.nextLink进行分页请求时,该链接已经包含了第一页请求中的所有查询参数(包括$top=30)。此时在requestConfiguration中修改Top参数不会生效,因为Graph SDK会优先使用链接中已有的参数,忽略你在配置中设置的新值。

解决方案

方案1:修改分页链接中的$top参数

手动解析OdataNextLink,替换其中的$top值为所需的页数,再传入WithUrl():

if (!string.IsNullOrEmpty(messagesResponse.OdataNextLink))
{
    // 修改链接中的$top参数,若需更严谨可使用URL解析库处理
    string modifiedNextLink = messagesResponse.OdataNextLink.Replace("$top=30", $"$top={pageSize}");
    messagesResponse = await GraphServiceClient
        .Users[CurrentMailBoxAddress]
        .MailFolders[FolderId]
        .Messages
        .WithUrl(modifiedNextLink)
        .GetAsync((requestConfiguration) =>
        {
            requestConfiguration.QueryParameters.Expand = new string[] { expandValue };
            requestConfiguration.QueryParameters.Filter = itemSearchFilter;
        });
}

方案2:放弃@odata.nextLink,改用$skip参数(注意局限性)

如果查询结果总数不多,可以使用$skip跳过已获取的条目,同时设置新的$top:

// 替换原循环中的分页逻辑
int skippedItems = 0;
while (messages.Count < maxItemSize)
{
    int currentPageSize = Math.Min(pageSize, maxItemSize - messages.Count);
    var pageResponse = await GraphServiceClient
        .Users[CurrentMailBoxAddress]
        .MailFolders[FolderId]
        .Messages
        .GetAsync((requestConfiguration) =>
        {
            requestConfiguration.QueryParameters.Top = currentPageSize;
            requestConfiguration.QueryParameters.Skip = skippedItems;
            requestConfiguration.QueryParameters.Expand = new string[] { expandValue };
            requestConfiguration.QueryParameters.Filter = itemSearchFilter;
        });

    if (pageResponse.Value == null || !pageResponse.Value.Any())
        break;

    messages.AddRange(pageResponse.Value);
    skippedItems += pageResponse.Value.Count;
}

注意:Graph API对$skip有数量限制(通常超过1000条后不支持),邮件总数较大时建议优先用方案1。

方案3:调整初始页大小(最简单的业务适配)

如果业务允许,直接将初始页大小设为maxItemSize,一次性获取所需邮件:

int maxItemSize = 50;
int pageSize = maxItemSize; // 直接设置为目标数量

// 后续请求逻辑保持不变,第一页即可返回最多50封邮件

内容的提问来源于stack exchange,提问作者maffer1

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.29 20:00:16