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

如何在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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.20 15:39:56