Microsoft.Graph SDK 连接到用户的 OneDrive 但项目 returns NULL

Microsoft.Graph SDK connects to user's OneDrive but Items returns NULL

我正在使用 Microsoft.Graph SDK 在 C# 中编写一个实用程序来连接和读取用户的 OneDrive。我创建了应用程序注册,授予应用程序 Files.Read.All 权限,并给予管理员同意 per the documentation.

我能够连接到 OneDrive 的 Graph 和元数据:

List<string> scopes = new List<string>();
scopes.Add("https://graph.microsoft.com/.default");

var authenticationProvider = new MsalAuthenticationProvider(cca, scopes.ToArray());
GraphServiceClient graphClient = new GraphServiceClient(authenticationProvider);

var drive = await graphClient.Users[userId].Drive
    .Request()
    .GetAsync();

它似乎正确连接到 OneDrive,正如 return 正确数据的属性所证明的那样,例如 QuotaOwner,等等

问题是 Items 对象为空,因此我无法读取任何驱动器项目:

我尝试使用 returned 驱动器 ID 直接访问驱动器,但收到相同的结果:

var driveById = await graphClient.Drives[drive.Id]
    .Request()
    .GetAsync();

我找到的几个示例并未表明任何其他请求选项或缺少权限。那么如何访问 OneDrive 项目?

这个问题的解决方案在评论中给出了,所以为了完整起见,我把它写在这里。

原始代码:

var rootDrive = await GraphClient.Users[UserId].Drive.Request().GetAsync();

此 returns 用户 OneDrive 的元数据,但未捕获 Children。但是,我们稍后会需要此信息,因此最终解决方案同时使用此参考和更新后的代码。

更新代码:

为此,您需要引用驱动器的根目录及其 Children:

var driveItems = await GraphClient.Users[UserId].Drive
                                                .Root
                                                .Children
                                                .Request()
                                                .GetAsync();

这样做 returns IDriveItemChildrenCollectionPage:

处理 CHILDREN:

对于小样本,标准的 foreach 可以正常工作,但对于较大的集合,您需要实施 PageIterator(我还没有这样做)。要获取此 driveItem 的 children,您将需要根元素的驱动器 ID 以及当前的 driveItem.Id:

var children = await GraphClient.Drives[rootDriveId].Items[item.Id].Children.Request().GetAsync()

总的来说,它看起来像这样:

public async Task ListOneDrive()
{
    var rootDrive = await GraphClient.Users[UserId].Drive.Request().GetAsync();

    var driveItems = await GraphClient.Users[UserId].Drive
                                                    .Root
                                                    .Children
                                                    .Request()
                                                    .GetAsync();

    foreach (var item in driveItems)
    {
        await ListDriveItem(rootDrive.Id, item);
    }
}

public async Task ListDriveItem(string rootDriveId, DriveItem item, int indentLevel = 1)
{
    StringBuilder sb = new StringBuilder();
    for (int i = 0; i < indentLevel; i++)
    {
        sb.Append($"  ");
    }

    if (item.Folder != null)
    {
        Console.WriteLine($"{sb.ToString()}> {item.Name}/");

        var children = await GraphClient.Drives[rootDriveId].Items[item.Id].Children.Request().GetAsync();
        foreach (var child in children)
        {
            await (ListDriveItem(rootDriveId, child, indentLevel + 1));
        }
    }
    else if (item.File != null)
    {
        Console.WriteLine($"{sb.ToString()}  {item.Name}");
    }
}

此示例来自使用递归调用向下钻取所有文件夹的控制台应用程序。如上所述,这两种方法都应该有一个 PageIterator。