使用Microsoft Graph SDK与C#获取用户联系人时遇空引用异常
问题描述
我尝试通过Microsoft Graph SDK和C#读取Exchange Online中所有用户的联系人,但执行代码var graphResult = graphClient.Users.Request().GetAsync().Result; Console.WriteLine(graphResult[0].Contacts[0]);时触发NullReferenceException,尽管目标用户实际存在联系人。已在Azure AD中配置相关权限,且通过Graph Explorer登录该用户调用/me/contacts端点能正常获取到3个联系人,怀疑是权限问题但无法定位具体原因,以下是完整代码:
主类代码
using Microsoft.Graph; using Azure.Identity; using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using Microsoft.Identity.Client; using System.Data.SqlClient; namespace ExchangeTestAppKonsole { internal class Program { static void Main(string[] args) { getContacts(); Console.ReadLine(); } public static void getContacts() { var clientId = "de196208-b4d7-468f-8fa4-7328551566b9"; var clientSecret = "~uG8Q~~vrTGuaIPfzeIR9GUUpSK5aaG.KZTYGcnD"; var redirectUri = "https://global.consent.azure-apim.net/redirect"; var authority = "https://login.microsoftonline.com/0be300e6-91fd-4638-bcd1-40d742ef6ece/v2.0"; var cca = ConfidentialClientApplicationBuilder.Create(clientId) .WithAuthority(authority) .WithRedirectUri(redirectUri) .WithClientSecret(clientSecret) .Build(); // use the default permissions assigned from within the Azure AD app registration portal List<string> scopes = new List<string>(); scopes.Add("https://graph.microsoft.com/.default"); var authenticationProvider = new MsalAuthenticationProvider(cca, scopes.ToArray()); GraphServiceClient graphClient = new GraphServiceClient(authenticationProvider); var graphResult = graphClient.Users.Request().GetAsync().Result; Console.WriteLine(graphResult[0].Contacts[0]); } } }
认证提供者代码
using Microsoft.Graph; using Microsoft.Identity.Client; using System; using System.Collections.Generic; using System.Linq; using System.Net.Http.Headers; using System.Net.Http; using System.Text; using System.Threading.Tasks; namespace ExchangeTestAppKonsole { internal class MsalAuthenticationProvider : IAuthenticationProvider { private IConfidentialClientApplication _clientApplication; private string[] _scopes; public MsalAuthenticationProvider(IConfidentialClientApplication clientApplication, string[] scopes) { _clientApplication = clientApplication; _scopes = scopes; } public async Task AuthenticateRequestAsync(HttpRequestMessage request) { var token = await GetTokenAsync(); request.Headers.Authorization = new AuthenticationHeaderValue("bearer", token); } public async Task<string> GetTokenAsync() { AuthenticationResult authResult = null; authResult = await _clientApplication.AcquireTokenForClient(_scopes).ExecuteAsync(); return authResult.AccessToken; } } }
解决方案
1. 修复NullReferenceException的核心原因
Graph API默认仅返回用户的基础属性(如ID、DisplayName),不会自动加载Contacts这类嵌套资源,因此graphResult[0].Contacts为null,触发空引用异常。需通过Expand方法显式指定加载嵌套资源,或单独请求单个用户的联系人:
- 方式1:加载用户时同时扩展联系人(不建议批量操作,性能差)
var graphResult = graphClient.Users.Request().Expand(u => u.Contacts).GetAsync().Result; - 方式2:按需加载单个用户的联系人(推荐)
var users = await graphClient.Users.Request().GetAsync(); var firstUserContacts = await graphClient.Users[users[0].Id].Contacts.Request().GetAsync(); Console.WriteLine(firstUserContacts[0].DisplayName);
2. 验证权限配置
你使用的是客户端凭据模式(Confidential Client),需确认Azure AD应用注册的权限配置:
- 必须添加应用权限(而非委托权限):选择
Contacts.Read.All - 必须点击「授予管理员同意」,应用权限需管理员批准才能生效
- 注意:Graph Explorer使用的是委托权限(
Contacts.Read),仅适用于用户登录场景,与客户端凭据模式不兼容
3. 代码优化建议
- 避免用
.Result阻塞异步方法,改用async/await:static async Task Main(string[] args) { await getContacts(); Console.ReadLine(); } public static async Task getContacts() { // 省略其他初始化代码 var users = await graphClient.Users.Request().GetAsync(); var firstUserContacts = await graphClient.Users[users[0].Id].Contacts.Request().GetAsync(); Console.WriteLine(firstUserContacts[0].DisplayName); } - 客户端凭据模式无需设置
redirectUri,可移除该配置项:var cca = ConfidentialClientApplicationBuilder.Create(clientId) .WithAuthority(authority) .WithClientSecret(clientSecret) .Build();
内容的提问来源于stack exchange,提问作者flam3shadow
相关产品推荐
相关产品推荐

