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

Azure Function调用Microsoft Graph API时遭遇CS0021错误求助

解决Azure Function调用Microsoft Graph API时的CS0021错误

错误原因

该错误是由于Microsoft Graph SDK版本差异导致的语法不兼容,同时你的代码中还存在匿名授权模式下身份信息获取的潜在问题:

  • v5.x版本的Graph SDK使用.GetAsync()直接发起请求,而v4及以下版本需要.Request().GetAsync()
  • 当HttpTrigger设置为AuthorizationLevel.Anonymous时,ClaimsPrincipal大概率无法获取到有效用户声明

解决方案

第一步:确认Graph SDK版本并匹配对应语法

根据你使用的SDK版本选择对应代码:

情况1:使用Microsoft Graph SDK v5.x

确保已安装Microsoft.Graph v5+ NuGet包,调整代码如下:

using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Azure.WebJobs;
using Microsoft.Azure.WebJobs.Extensions.Http;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.Logging;
using Newtonsoft.Json;
using System.Security.Claims;
using Azure.Identity;
using Microsoft.Graph;
using System.Linq;

namespace AZFunction1
{
    public static class Function1
    {
        [FunctionName("Function1")]
        public static async Task<IActionResult> Run(
            [HttpTrigger(AuthorizationLevel.Anonymous, "get", "post", Route = null)] HttpRequest req,
            ILogger log, ClaimsPrincipal claimIdentity)
        {
            var options = new TokenCredentialOptions
            {
                AuthorityHost = AzureAuthorityHosts.AzurePublicCloud
            };

            var clientSecretCredential = new ClientSecretCredential(
                Constants.TenantId, Constants.AppId, Constants.ClientSecret, options);

            var graphClient = new GraphServiceClient(clientSecretCredential, Constants.scopes);

            // 尝试从ClaimsPrincipal获取用户ID或UPN(匿名模式下可能为空)
            var userId = claimIdentity?.Claims.FirstOrDefault(c => c.Type == ClaimTypes.NameIdentifier)?.Value;
            var userUpn = claimIdentity?.Claims.FirstOrDefault(c => c.Type == ClaimTypes.Upn)?.Value;

            log.LogInformation($"User ID: {userId}, UPN: {userUpn}");

            if (string.IsNullOrEmpty(userId) && string.IsNullOrEmpty(userUpn))
            {
                log.LogError("无法获取有效用户标识符");
                return new BadRequestObjectResult("无效的用户身份信息");
            }

            try
            {
                User user;
                if (!string.IsNullOrEmpty(userId))
                {
                    user = await graphClient.Users[userId].GetAsync();
                }
                else
                {
                    user = await graphClient.Users[userUpn].GetAsync();
                }
                var json = JsonConvert.SerializeObject(user);
                return new OkObjectResult(json);
            }
            catch (ServiceException ex)
            {
                log.LogError($"获取用户信息失败: {ex.Message}, 错误代码: {ex.Error.Code}");
                return new StatusCodeResult(StatusCodes.Status500InternalServerError);
            }
        }
    }
}

情况2:使用Microsoft Graph SDK v4.x及以下

确保已安装Microsoft.Graph v4.x或更低版本NuGet包,调整代码如下:

using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Azure.WebJobs;
using Microsoft.Azure.WebJobs.Extensions.Http;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.Logging;
using Newtonsoft.Json;
using System.Security.Claims;
using Azure.Identity;
using Microsoft.Graph;
using System.Linq;

namespace AZFunction1
{
    public static class Function1
    {
        [FunctionName("Function1")]
        public static async Task<IActionResult> Run(
            [HttpTrigger(AuthorizationLevel.Anonymous, "get", "post", Route = null)] HttpRequest req,
            ILogger log, ClaimsPrincipal claimIdentity)
        {
            var options = new TokenCredentialOptions
            {
                AuthorityHost = AzureAuthorityHosts.AzurePublicCloud
            };

            var clientSecretCredential = new ClientSecretCredential(
                Constants.TenantId, Constants.AppId, Constants.ClientSecret, options);

            var graphClient = new GraphServiceClient(clientSecretCredential, Constants.scopes);

            // 尝试从ClaimsPrincipal获取用户ID或UPN(匿名模式下可能为空)
            var userId = claimIdentity?.Claims.FirstOrDefault(c => c.Type == ClaimTypes.NameIdentifier)?.Value;
            var userUpn = claimIdentity?.Claims.FirstOrDefault(c => c.Type == ClaimTypes.Upn)?.Value;

            log.LogInformation($"User ID: {userId}, UPN: {userUpn}");

            if (string.IsNullOrEmpty(userId) && string.IsNullOrEmpty(userUpn))
            {
                log.LogError("无法获取有效用户标识符");
                return new BadRequestObjectResult("无效的用户身份信息");
            }

            try
            {
                User user;
                if (!string.IsNullOrEmpty(userId))
                {
                    user = await graphClient.Users[userId].Request().GetAsync();
                }
                else
                {
                    user = await graphClient.Users[userUpn].Request().GetAsync();
                }
                var json = JsonConvert.SerializeObject(user);
                return new OkObjectResult(json);
            }
            catch (ServiceException ex)
            {
                log.LogError($"获取用户信息失败: {ex.Message}, 错误代码: {ex.Error.Code}");
                return new StatusCodeResult(StatusCodes.Status500InternalServerError);
            }
        }
    }
}

第二步:解决额外潜在问题

  1. 授权级别调整:如果需要获取真实用户身份,将AuthorizationLevel.Anonymous改为AuthorizationLevel.User,并配置Azure AD身份验证,确保请求携带有效身份令牌。
  2. 权限配置:确认Azure AD应用注册已添加User.Read.All(应用权限)或User.Read(委派权限),并完成管理员同意。
  3. Constants验证:确保Constants.TenantId、Constants.AppId、Constants.ClientSecret、Constants.scopes配置正确,scopes格式为https://graph.microsoft.com/.default(应用权限)或https://graph.microsoft.com/User.Read(委派权限)。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.21 20:53:13