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

Microsoft Graph批量请求中CreateLink(POST)请求卡住问题解决

问题描述

批量请求始终在与POST请求CreateLink()相关的代码处卡住,不清楚如何在批量请求中正确处理POST请求,微软文档指出批量请求中的POST请求与GET请求处理方式不同。原代码如下:

public async Task<OneDriveFile> BulkFileImportAsync(string DriveID, string Path)
{
    OneDriveFile oneDriveFile = new OneDriveFile();

    try
    {

        var fileInfoRequest = _graphServiceClient.Me.Drives[DriveID].Root
                    .ItemWithPath(Path)
                    .Request();
        var fileEditRequest = _graphServiceClient.Me.Drives[DriveID].Root
                    .ItemWithPath(Path)
                    .CreateLink("edit", "users", null, null, null, true)
                    .Request();
        var fileViewRequest = _graphServiceClient.Me.Drives[DriveID].Root
                    .ItemWithPath(Path)
                    .CreateLink("view", "users", null, null, null, true)
                    .Request();
        var fileThumbnailRequest = _graphServiceClient.Me.Drives[DriveID].Root
                    .ItemWithPath(Path).Thumbnails
                    .Request();

        // Build the batch
        var batchRequestContent = new BatchRequestContent();

        var fileInfoRequestId = batchRequestContent.AddBatchRequestStep(fileInfoRequest);
        var fileEditRequestId = batchRequestContent.AddBatchRequestStep(fileEditRequest);
        var fileViewRequestId = batchRequestContent.AddBatchRequestStep(fileViewRequest);
        var fileThumbnailRequestId = batchRequestContent.AddBatchRequestStep(fileThumbnailRequest);

        var returnedResponse = await _graphServiceClient.Batch.Request().PostAsync(batchRequestContent);

        var fileInfo = await returnedResponse
                   .GetResponseByIdAsync<DriveItem>(fileInfoRequestId);
        var fileEdit = await returnedResponse
                   .GetResponseByIdAsync<Permission>(fileEditRequestId);
        var fileView = await returnedResponse
                   .GetResponseByIdAsync<Permission>(fileViewRequestId);
        var fileThumbnail = await returnedResponse
                    .GetResponseByIdAsync<IDriveItemThumbnailsCollectionPage>(fileThumbnailRequestId);

        oneDriveFile.Path = Path;
        oneDriveFile.WebURL = fileInfo.WebUrl;
        oneDriveFile.EditURL = fileEdit.AdditionalData["webUrl"].ToString();
        oneDriveFile.ViewURL = fileEdit.AdditionalData["webUrl"].ToString();
        oneDriveFile.ThumbnailURL = fileThumbnail.CurrentPage[0].Large.Url;

    }
    catch (ServiceException ex)
    {
        Console.WriteLine($"Error doing batch update: {ex.ToString()}");
    }

    return oneDriveFile;
}

问题原因

Graph批量请求中,GET请求可直接通过AddBatchRequestStep传入请求对象,但POST请求(如CreateLink)需要携带请求体。直接传递IRequest对象时,批量请求框架可能未正确提取POST的请求体内容,导致请求卡住或失败。

解决方案

对于POST类型的请求,需先获取对应的HttpRequestMessage,再包装为BatchRequestStep添加到批量请求中。修改后的代码如下:

public async Task<OneDriveFile> BulkFileImportAsync(string DriveID, string Path)
{
    OneDriveFile oneDriveFile = new OneDriveFile();

    try
    {
        var fileInfoRequest = _graphServiceClient.Me.Drives[DriveID].Root
                    .ItemWithPath(Path)
                    .Request();
        var fileEditRequest = _graphServiceClient.Me.Drives[DriveID].Root
                    .ItemWithPath(Path)
                    .CreateLink("edit", "users", null, null, null, true)
                    .Request();
        var fileViewRequest = _graphServiceClient.Me.Drives[DriveID].Root
                    .ItemWithPath(Path)
                    .CreateLink("view", "users", null, null, null, true)
                    .Request();
        var fileThumbnailRequest = _graphServiceClient.Me.Drives[DriveID].Root
                    .ItemWithPath(Path).Thumbnails
                    .Request();

        // Build the batch
        var batchRequestContent = new BatchRequestContent();

        // GET请求直接添加
        var fileInfoRequestId = batchRequestContent.AddBatchRequestStep(fileInfoRequest);
        var fileThumbnailRequestId = batchRequestContent.AddBatchRequestStep(fileThumbnailRequest);

        // POST请求需要先获取HttpRequestMessage,再添加到批量
        var fileEditRequestMsg = await fileEditRequest.GetHttpRequestMessageAsync();
        var fileEditRequestId = batchRequestContent.AddBatchRequestStep(new BatchRequestStep(fileEditRequestMsg));

        var fileViewRequestMsg = await fileViewRequest.GetHttpRequestMessageAsync();
        var fileViewRequestId = batchRequestContent.AddBatchRequestStep(new BatchRequestStep(fileViewRequestMsg));

        var returnedResponse = await _graphServiceClient.Batch.Request().PostAsync(batchRequestContent);

        var fileInfo = await returnedResponse
                   .GetResponseByIdAsync<DriveItem>(fileInfoRequestId);
        var fileEdit = await returnedResponse
                   .GetResponseByIdAsync<Permission>(fileEditRequestId);
        var fileView = await returnedResponse
                   .GetResponseByIdAsync<Permission>(fileViewRequestId);
        var fileThumbnail = await returnedResponse
                    .GetResponseByIdAsync<IDriveItemThumbnailsCollectionPage>(fileThumbnailRequestId);

        oneDriveFile.Path = Path;
        oneDriveFile.WebURL = fileInfo.WebUrl;
        oneDriveFile.EditURL = fileEdit.AdditionalData["webUrl"].ToString();
        // 修复原代码逻辑错误:使用fileView的webUrl赋值给ViewURL
        oneDriveFile.ViewURL = fileView.AdditionalData["webUrl"].ToString();
        oneDriveFile.ThumbnailURL = fileThumbnail.CurrentPage[0].Large.Url;

    }
    catch (ServiceException ex)
    {
        Console.WriteLine($"Error doing batch update: {ex.ToString()}");
    }

    return oneDriveFile;
}

关键修改点

  1. POST请求处理:对CreateLink生成的POST请求,调用GetHttpRequestMessageAsync()获取完整请求消息,再通过BatchRequestStep包装后添加到批量请求,确保请求体被正确携带。
  2. 修复逻辑bug:原代码中错误地将fileEdit的webUrl同时赋值给EditURL和ViewURL,修改为使用fileView的对应值。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.09 23:35:21