如何在Azure Durable Function中调用Microsoft Graph API?
在Azure Durable Function中调用Microsoft Graph API的实现方案
1. 配置依赖注入(DI)
首先在Function项目的Program.cs中注册所需服务(包括你参考示例中的ITokenValidationService、IGraphClientService,以及Microsoft Graph官方客户端GraphServiceClient):
var host = new HostBuilder() .ConfigureFunctionsWorkerDefaults() .ConfigureServices(services => { // 注册自定义验证与Graph客户端服务 services.AddScoped<ITokenValidationService, TokenValidationService>(); services.AddScoped<IGraphClientService, GraphClientService>(); // 注册Microsoft Graph客户端(根据你的认证方式调整,示例为客户端凭据模式) services.AddScoped<GraphServiceClient>(sp => { var credential = new ClientSecretCredential( Environment.GetEnvironmentVariable("TenantId"), Environment.GetEnvironmentVariable("ClientId"), Environment.GetEnvironmentVariable("ClientSecret")); return new GraphServiceClient(credential, new[] { "https://graph.microsoft.com/.default" }); }); }) .Build(); host.Run();
2. 在Durable Function中使用注入的服务
Durable Function支持两种方式获取服务,可根据习惯选择:
方式一:非静态类+构造注入(推荐,符合DI设计)
Durable Function并非强制要求静态类/方法,你可以将活动/编排函数定义为非静态类,通过构造函数直接注入所需服务:
public class GraphActivityFunctions { private readonly ITokenValidationService _tokenValidationService; private readonly IGraphClientService _graphClientService; private readonly ILogger _logger; // 构造函数注入服务与日志实例 public GraphActivityFunctions(ITokenValidationService tokenValidationService, IGraphClientService graphClientService, ILogger<GraphActivityFunctions> logger) { _tokenValidationService = tokenValidationService; _graphClientService = graphClientService; _logger = logger; } [Function("GetNewestMessage_Activity")] public async Task<Message> GetNewestMessageActivity([ActivityTrigger] string userToken) { // 复用示例中的令牌验证逻辑 var validatedToken = await _tokenValidationService.ValidateTokenAsync(userToken); if (!validatedToken.IsValid) { _logger.LogError("用户令牌无效"); throw new ArgumentException("无效令牌"); } // 获取认证后的Graph客户端并调用API var graphClient = _graphClientService.GetAuthenticatedClient(userToken); var messageResult = await graphClient.Me.Messages .OrderBy("receivedDateTime desc") .Take(1) .Request() .GetAsync(); return messageResult.FirstOrDefault(); } }
方式二:静态方法中通过FunctionContext获取服务
如果需要保留静态方法结构,可通过FunctionContext的GetService<T>()方法获取已注册的服务:
public static class StaticGraphActivityFunctions { [Function("GetNewestMessage_StaticActivity")] public static async Task<Message> GetNewestMessageActivity( [ActivityTrigger] string userToken, FunctionContext executionContext) { // 获取日志实例 var logger = executionContext.GetLogger("GetNewestMessage_StaticActivity"); // 获取注入的服务 var tokenValidationService = executionContext.GetService<ITokenValidationService>(); var graphClientService = executionContext.GetService<IGraphClientService>(); // 后续逻辑与非静态方式一致 var validatedToken = await tokenValidationService.ValidateTokenAsync(userToken); if (!validatedToken.IsValid) { logger.LogError("用户令牌无效"); throw new ArgumentException("无效令牌"); } var graphClient = graphClientService.GetAuthenticatedClient(userToken); var messageResult = await graphClient.Me.Messages .OrderBy("receivedDateTime desc") .Take(1) .Request() .GetAsync(); return messageResult.FirstOrDefault(); } }
3. 在编排函数中调用活动函数
无论采用静态还是非静态活动函数,编排函数都可以正常调用:
public static class GraphOrchestrator { [Function("GraphWorkflow_Orchestrator")] public static async Task<List<Message>> RunOrchestrator( [OrchestrationTrigger] TaskOrchestrationContext context) { var outputs = new List<Message>(); var userToken = context.GetInput<string>(); // 调用活动函数 outputs.Add(await context.CallActivityAsync<Message>("GetNewestMessage_Activity", userToken)); return outputs; } [Function("GraphWorkflow_HttpStart")] public static async Task<HttpResponseData> HttpStart( [HttpTrigger(AuthorizationLevel.Anonymous, "get", "post")] HttpRequestData req, [DurableClient] DurableTaskClient client, FunctionContext executionContext) { var logger = executionContext.GetLogger("GraphWorkflow_HttpStart"); // 读取请求中的用户令牌 var userToken = await req.ReadFromJsonAsync<string>(); // 启动编排流程 var instanceId = await client.StartNewAsync("GraphWorkflow_Orchestrator", userToken); logger.LogInformation("已启动编排实例,ID: '{instanceId}'.", instanceId); return client.CreateCheckStatusResponse(req, instanceId); } }
关键说明
- Durable Function无静态强制要求:从.NET 5+的Azure Functions隔离模型开始,完全支持非静态类与构造注入,这是更符合现代.NET开发的方式。
- 服务生命周期:注册为
Scoped的服务会在每个函数执行范围内创建实例,适配函数的无状态执行模型。 - 现有代码复用:你找到的示例中的
TokenValidationService和GraphClientService实现可直接复用,只需确保它们被正确注册到DI容器中。
内容的提问来源于stack exchange,提问作者Daniel
相关产品推荐
相关产品推荐

