为 MS GraphApi 创建批处理请求

问题描述 投票:0回答:1

我想优化对 MS GraphAPI 的 API 调用数量。

所以,我需要的是从我的日历中获取事件数量并与 graphAPI 日历事件同步。

数字可以从 0-1000(大约)变化

如何正确调用它?

以下是创建批量请求的示例:

    public async Task<IEnumerable<string>> ExecuteBatchRequest(IEnumerable<Func<Task<string>>> batchRequests)
    {
        var batchRequestContent = new BatchRequestContent();

        var requestIndex = 1;
        var result = new List<string>();

        foreach (var requestFunc in batchRequests)
        {
            var request = await requestFunc.Invoke();
            var httpRequestMessage = new HttpRequestMessage(HttpMethod.Get, request);
            batchRequestContent.AddBatchRequestStep(httpRequestMessage, requestIndex.ToString());
            requestIndex++;
        }

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

        foreach (var responseFunc in batchRequests)
        {
            var response = await batchResponse.GetResponseByIdAsync<string>(requestIndex.ToString());
            result.Add(response.Result);
            requestIndex++;
        }

        return result;
    }

您有更好的代码的想法吗?

.net-core azure-functions microsoft-graph-api batch-processing
1个回答
0
投票

如果您的日历中有

0-1000
事件,您可以使用
JSON ID format
创建一个类,然后在 Azure Functions 代码中调用它,如下所示:-

我已经与 Microsoft Graph API 用户复制了相同的场景,因为我的目录中有多个用户:-

我的Azure Functions代码:-

using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Net.Http;
using System.Threading.Tasks;
using Azure.Core;
using Azure.Identity;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Azure.WebJobs;
using Microsoft.Azure.WebJobs.Extensions.Http;
using Microsoft.Extensions.Logging;

namespace FunctionApp1
{
    public class User
    {
        public string Id { get; set; }
        public string DisplayName { get; set; }
        // Add other properties as needed based on the Graph API response
    }

    public class GraphApiResponse<T>
    {
        [JsonProperty("@odata.context")]
        public string Context { get; set; }

        public T Value { get; set; }
    }

    public static class Function1
    {
        [FunctionName("Function1")]
        public static async Task<IActionResult> Run(
            [HttpTrigger(AuthorizationLevel.Function, "get", Route = null)] HttpRequest req,
            ILogger log)
        {
            log.LogInformation("C# HTTP trigger function processed a request.");

            var token = await GetAccessToken("xxxxxxaf9038592395", "xxxxx26a31435cb", "xxxxxa2Hr3wUzLFlwpK4b4M");
            var users = await GetUsers(token);

            return new OkObjectResult(users);
        }

        private static async Task<string> GetAccessToken(string tenantId, string clientId, string clientSecret)
        {
            var credentials = new ClientSecretCredential(tenantId, clientId, clientSecret);
            var result = await credentials.GetTokenAsync(new TokenRequestContext(new[] { "https://graph.microsoft.com/.default" }), default);
            return result.Token;
        }

        private static async Task<List<User>> GetUsers(string token)
        {
            var httpClient = new HttpClient
            {
                BaseAddress = new Uri("https://graph.microsoft.com/v1.0/")
            };

            string URI = $"users";

            httpClient.DefaultRequestHeaders.Remove("Authorization");
            httpClient.DefaultRequestHeaders.Add("Authorization", "Bearer " + token);
            HttpResponseMessage response = await httpClient.GetAsync(URI);

            if (response.IsSuccessStatusCode)
            {
                var content = await response.Content.ReadAsStringAsync();
                var responseWrapper = JsonConvert.DeserializeObject<GraphApiResponse<List<User>>>(content);

                if (responseWrapper != null)
                {
                    return responseWrapper.Value;
                }
            }

            // Handle the failure case or empty response
            return new List<User>();
        }
    }
}

输出:-

enter image description here

enter image description here

对于日历事件:-

using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Net.Http;
using System.Threading.Tasks;
using Azure.Core;
using Azure.Identity;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Azure.WebJobs;
using Microsoft.Azure.WebJobs.Extensions.Http;
using Microsoft.Extensions.Logging;

namespace FunctionApp1
{
    public class Event
    {
        public string Id { get; set; }
        public string Subject { get; set; }
        // Add other properties as needed based on the Graph API response for events
    }

    public class GraphApiResponse<T>
    {
        [JsonProperty("@odata.context")]
        public string Context { get; set; }

        public T Value { get; set; }
    }

    public static class Function1
    {
        [FunctionName("Function1")]
        public static async Task<IActionResult> Run(
            [HttpTrigger(AuthorizationLevel.Function, "get", Route = null)] HttpRequest req,
            ILogger log)
        {
            log.LogInformation("C# HTTP trigger function processed a request.");

            var userId = "UserId"; // Replace with the actual user ID
            var calendarId = "CalendarId"; // Replace with the actual calendar ID
            var token = await GetAccessToken("YourTenantId", "YourClientId", "YourClientSecret");
            var events = await GetEvents(token, userId, calendarId);

            return new OkObjectResult(events);
        }

        private static async Task<string> GetAccessToken(string tenantId, string clientId, string clientSecret)
        {
            var credentials = new ClientSecretCredential(tenantId, clientId, clientSecret);
            var result = await credentials.GetTokenAsync(new TokenRequestContext(new[] { "https://graph.microsoft.com/.default" }), default);
            return result.Token;
        }

        private static async Task<List<Event>> GetEvents(string token, string userId, string calendarId)
        {
            var httpClient = new HttpClient
            {
                BaseAddress = new Uri("https://graph.microsoft.com/v1.0/")
            };

            string URI = $"users/{userId}/calendars/{calendarId}/events";

            httpClient.DefaultRequestHeaders.Remove("Authorization");
            httpClient.DefaultRequestHeaders.Add("Authorization", "Bearer " + token);
            HttpResponseMessage response = await httpClient.GetAsync(URI);

            if (response.IsSuccessStatusCode)
            {
                var content = await response.Content.ReadAsStringAsync();
                var responseWrapper = JsonConvert.DeserializeObject<GraphApiResponse<List<Event>>>(content);

                if (responseWrapper != null)
                {
                    return responseWrapper.Value;
                }
            }

            // Handle the failure case or empty response
            return new List<Event>();
        }
    }
}

方法2:-

您可以利用下面的代码尝试在 Azure Function 中进行批处理来调用 Microsoft Graph API 并为您的获取日历事件 API 实现它:-

using System;
using System.Collections.Generic;
using System.Net.Http;
using System.Threading.Tasks;
using Azure.Core;
using Azure.Identity;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Azure.WebJobs;
using Microsoft.Azure.WebJobs.Extensions.Http;
using Microsoft.Extensions.Logging;
using Newtonsoft.Json;

namespace FunctionApp1
{
    public static class Function1
    {
        [FunctionName("Function1")]
        public static async Task<IActionResult> Run(
            [HttpTrigger(AuthorizationLevel.Function, "get", Route = null)] HttpRequest req,
            ILogger log)
        {
            log.LogInformation("C# HTTP trigger function processed a request.");

            var token = await GetAccessToken("83331f4e-7f45-4ce4-99ed-af9038592395", "c0c952e9-5254-45b5-b838-6d26a31435cb", "Fex8Q~i_cgyujE4aJ2dFkBa2Hr3wUzLFlwpK4b4M");
            var results = await GetResults(token);

            return new OkObjectResult(results);
        }

        private static async Task<string> GetAccessToken(string tenantId, string clientId, string clientSecret)
        {
            var credentials = new ClientSecretCredential(tenantId, clientId, clientSecret);
            var result = await credentials.GetTokenAsync(new TokenRequestContext(new[] { "https://graph.microsoft.com/.default" }), default);
            return result.Token;
        }

        private static async Task<string> GetResults(string token)
        {
            var httpClient = new HttpClient
            {
                BaseAddress = new Uri("https://graph.microsoft.com/v1.0/")
            };

            var batchRequests = new List<HttpRequestMessage>();
            const int numberOfRequests = 5; // Change this number based on your requirements

            for (int i = 0; i < numberOfRequests; i++)
            {
                string requestUrl = $"https://graph.microsoft.com/v1.0/users/{i}"; // Use absolute URI for each request

                var httpRequestMessage = new HttpRequestMessage(HttpMethod.Get, requestUrl);
                httpRequestMessage.Headers.Add("Authorization", "Bearer " + token);
                batchRequests.Add(httpRequestMessage);
            }

            var batchResponses = await SendBatchRequest(httpClient, batchRequests);

            // Process batch responses here (if needed)
            // For example, concatenate or structure the results in a specific way
            var aggregatedResult = string.Join("\n", batchResponses);

            return aggregatedResult;
        }

        private static async Task<List<string>> SendBatchRequest(HttpClient httpClient, List<HttpRequestMessage> batchRequests)
        {
            var batchEndpoint = "https://graph.microsoft.com/v1.0/$batch";

            var batchContent = new MultipartContent("mixed");
            foreach (var request in batchRequests)
            {
                var content = new HttpMessageContent(request);
                batchContent.Add(content);
            }

            var batchResponse = await httpClient.PostAsync(batchEndpoint, batchContent);

            var batchResponses = new List<string>();
            if (batchResponse.IsSuccessStatusCode)
            {
                var responseContent = await batchResponse.Content.ReadAsStringAsync();

                // Deserialize the batch response content to extract individual responses
                var batchResponseData = JsonConvert.DeserializeObject<Dictionary<string, object>>(responseContent);

                foreach (var responseItem in batchResponseData)
                {
                    // Extract and handle individual batch responses
                    var responseData = responseItem.Value as Dictionary<string, object>;
                    var responseBody = responseData["body"].ToString(); // Extract the response body
                    batchResponses.Add(responseBody);
                }
            }

            return batchResponses;
        }
    }
}

输出:-

enter image description here

© www.soinside.com 2019 - 2024. All rights reserved.