Making Batch Post request to the Microsoft Graph API of Calendar events

764 Views Asked by At

I am trying to schedule multiple time off requests on users' calendars using the Graph API.

I followed the instructions provided in this link: https://learn.microsoft.com/en-us/graph/sdks/batch-requests?tabs=csharp

I also attempted to use the HTTP request method, but the results were the same - exiting with no error code.

I made sure to comply with the batch limit of 4 requests per batch, as outlined in the Graph Docs: https://learn.microsoft.com/en-us/graph/throttling-limits#outlook-service-limits-for-json-batching

My function is as shown below.

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

My graph client is created as such.

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.");
        }

In debug mode it only makes it to the foreach loop of making each event a post request and stops at the first attempt of making it into step. Program exists without error.

My graph client functions for all other processes besides batching.

Does anyone have experience with event batches and has encountered this? Any tips or guidance would be appreciated.

1

There are 1 best solutions below

0
On

Your request fails for me because of the way (or the lack of) your formating the datetime string in the event. Eg you should make sure there ISO or RFC format or the Graph won't accept them eg

                Start = new DateTimeTimeZone
                {
                    DateTime = date.AddHours(8).ToString("s", System.Globalization.CultureInfo.InvariantCulture),
                    TimeZone = TimeZoneInfo.Local.StandardName
                },
                End = new DateTimeTimeZone
                {
                    DateTime = date.AddHours(17).ToString("s", System.Globalization.CultureInfo.InvariantCulture),
                    TimeZone = TimeZoneInfo.Local.StandardName
                },

You also probably don't want do this

 var res = await batchResponse.GetResponseByIdAsync<Event>(postID);

When you do have an error in one more of your batch requests this will fail as it won't return an Event just a response with the error.