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

使用Microsoft Graph API批量创建日历休假事件遇无报错退出问题

问题:Microsoft Graph API批量创建日历休假请求无报错直接退出

我尝试通过Microsoft Graph API为用户日历批量创建休假请求,按照官方文档实现了批量请求,也试过HTTP请求方式,两种方式都出现无报错直接退出的情况。已经遵守了每批最多4个请求的限制。

调试时,程序仅执行到将每个事件转为POST请求的循环,在首次尝试添加批量请求步骤时停止,无任何报错。Graph Client在其他非批量操作中可正常工作。


批量创建事件的实现函数

public static async void PostTimeOffToCalendar(string upn, string udn, GraphServiceClient graphClient, List<DateTime> timesOff)
{
    var calendarPosts = new List<Event>();
    foreach (var date in timesOff)
    {
        Event requestBody = new()
        {
            Subject = $"Out of Office (PTO) - {udn}",
            Body = new ItemBody
            {
                ContentType = BodyType.Html,
                Content = "Scheduled time off."
            },
            Start = new DateTimeTimeZone
            {
                DateTime = date.AddHours(8).ToString(),
                TimeZone = TimeZoneInfo.Local.StandardName
            },
            End = new DateTimeTimeZone
            {
                DateTime = date.AddHours(17).ToString(),
                TimeZone = TimeZoneInfo.Local.StandardName
            },
            IsOnlineMeeting = false,
            IsAllDay = false,
            ShowAs = FreeBusyStatus.Oof,
            IsReminderOn = true,
            ReminderMinutesBeforeStart = 30
        };
        calendarPosts.Add(requestBody);
    }
    foreach(var thing in calendarPosts)
    {
        Console.WriteLine(thing.Body.Content);
    }
    int maxNoBatchItems = 4;
    List<BatchRequestContent> batches = new();
    BatchRequestContent batchRequestContent = new(graphClient);
    List<string> requestPostIds = new();
    foreach (Event e in calendarPosts )
    {
        var postEventRequest = graphClient.Users[upn].Events.ToPostRequestInformation(e);
        string requestPostId = await batchRequestContent.AddBatchRequestStepAsync(postEventRequest);
        requestPostIds.Add(requestPostId);
        if (calendarPosts.IndexOf(e) > 0 && ((calendarPosts.IndexOf(e) + 1) % maxNoBatchItems == 0))
        {
            batches.Add(batchRequestContent);
            batchRequestContent = new BatchRequestContent(graphClient);
        }
    }
    if (batchRequestContent.BatchRequestSteps.Count < maxNoBatchItems)
    {
        batches.Add(batchRequestContent);
    }

    if (batches.Count == 0 && batchRequestContent != null)
    {
        batches.Add(batchRequestContent);
    }
    List<BatchResponseContent> batchResponses = new();
    foreach (BatchRequestContent batch in batches)
    {                
        batchResponses.Add(await graphClient.Batch.PostAsync(batch));
    }
    foreach (var batchResponse in batchResponses)
    {
        foreach(var postID in requestPostIds)
        {
            var res = await batchResponse.GetResponseByIdAsync<Event>(postID);
            Console.WriteLine(res.Body + ";" + res.Id);
        }
    }
}

Graph Client创建函数

public static GraphServiceClient CreateGraphClient(Settings settings)
{
    string[] scopes = new[] { "https://graph.microsoft.com/.default" };

    TokenCredentialOptions graphOptions = new()
    {
        AuthorityHost = AzureAuthorityHosts.AzurePublicCloud
    };
    ClientSecretCredential clientSecretCredential = new(
        settings.TenantId, settings.ClientId, settings.ClientSecret, graphOptions);
    GraphServiceClient graphClient;
    try
    {
        graphClient = new GraphServiceClient(clientSecretCredential, scopes);
    }
    catch
    {
        throw; // Re-throw the caught exception without additional handling
    }
    return graphClient ?? throw new Exception("Microsoft Graph Client not initialized correctly.");
}

解决建议

  • 修改异步方法返回类型:把async void改为async Task,async void仅适用于事件处理场景,普通异步方法使用它会导致调用方无法等待执行完成,程序可能提前退出。调用该方法时需确保用await等待执行结束。
  • 修复分批逻辑的索引问题:calendarPosts.IndexOf(e)在列表存在重复对象时会返回错误索引,改用循环计数器跟踪当前位置:
    int index = 0;
    foreach (Event e in calendarPosts )
    {
        var postEventRequest = graphClient.Users[upn].Events.ToPostRequestInformation(e);
        string requestPostId = await batchRequestContent.AddBatchRequestStepAsync(postEventRequest);
        requestPostIds.Add(requestPostId);
        index++;
        if (index > 0 && index % maxNoBatchItems == 0)
        {
            batches.Add(batchRequestContent);
            batchRequestContent = new BatchRequestContent(graphClient);
        }
    }
    
  • 添加异常捕获与日志:在异步方法中包裹try-catch块,输出异常信息以排查隐藏错误:
    public static async Task PostTimeOffToCalendar(string upn, string udn, GraphServiceClient graphClient, List<DateTime> timesOff)
    {
        try
        {
            // 原方法逻辑
        }
        catch (Exception ex)
        {
            Console.WriteLine($"错误信息: {ex.Message}\n调用栈: {ex.StackTrace}");
            throw;
        }
    }
    
  • 规范日期格式:date.AddHours(8).ToString()可能生成不符合Graph要求的格式,改用ISO 8601标准格式:date.AddHours(8).ToString("yyyy-MM-ddTHH:mm:ss")
  • 验证时区标识符:TimeZoneInfo.Local.StandardName可能不是Graph认可的时区ID,建议使用TimeZoneInfo.Local.Id获取标准时区标识符,或直接指定如"China Standard Time"这类Graph兼容的时区名称。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.20 16:42:46