使用C#的GraphServiceClient调用Me.GetAsync()时为何抛出OperationCanceledException?
解决调用GraphServiceClient.Me.GetAsync()抛出OperationCanceledException的问题
以下是针对该问题的排查和解决方向:
1. 确认访问令牌的权限范围
确保你的OAuthSettings.Scopes包含User.Read或User.ReadBasic.All权限,/me端点需要至少这两个权限之一才能正常返回用户信息。可以本地解码令牌(比如用jwt.ms工具离线解析),查看scp字段确认是否包含所需权限。
2. 传递取消令牌到MSAL请求
你的TokenProvider实现中,GetAuthorizationTokenAsync方法接收了cancellationToken参数,但调用MSAL的ExecuteAsync时未传递该令牌,可能导致请求被外部取消时无法正确响应。修改代码如下:
public async Task<string> GetAuthorizationTokenAsync(Uri uri, Dictionary<string, object> additionalAuthenticationContext = default, CancellationToken cancellationToken = default) { var accounts = await _PCA.GetAccountsAsync(); AuthenticationResult result; try { // 传递cancellationToken到静默获取请求 result = await _PCA.AcquireTokenSilent(_Scopes, accounts.FirstOrDefault()).ExecuteAsync(cancellationToken); return result.AccessToken; } catch (MsalUiRequiredException ex) { var interactiveRequest = _PCA.AcquireTokenInteractive(_Scopes); interactiveRequest = interactiveRequest.WithParentActivityOrWindow(AuthUIParent); // 传递cancellationToken到交互式获取请求 result = await interactiveRequest.ExecuteAsync(cancellationToken); return result.AccessToken; } }
3. 调整GraphClient的超时时间
默认HttpClient超时较短,可能导致请求未完成就被取消。可以手动配置超时时间:
var httpClient = new HttpClient(); httpClient.Timeout = TimeSpan.FromSeconds(30); // 根据需要调整超时时长 var authenticationProvider = new BaseBearerTokenAuthenticationProvider(new TokenProvider()); var GraphClient = new GraphServiceClient(httpClient, authenticationProvider); var user = await GraphClient.Me.GetAsync();
4. 处理账户为空的边界情况
当accounts.FirstOrDefault()返回null时,静默获取令牌会抛出异常,若此时UI上下文异常导致交互式登录无法正常触发,可能引发流程卡住最终导致取消异常。添加空值检查优化逻辑:
var accounts = await _PCA.GetAccountsAsync(); var account = accounts.FirstOrDefault(); if (account == null) { // 直接触发交互式登录 var interactiveRequest = _PCA.AcquireTokenInteractive(_Scopes); interactiveRequest = interactiveRequest.WithParentActivityOrWindow(AuthUIParent); result = await interactiveRequest.ExecuteAsync(cancellationToken); return result.AccessToken; } // 继续静默获取逻辑 try { result = await _PCA.AcquireTokenSilent(_Scopes, account).ExecuteAsync(cancellationToken); return result.AccessToken; } catch (MsalUiRequiredException ex) { // 交互式登录逻辑 var interactiveRequest = _PCA.AcquireTokenInteractive(_Scopes); interactiveRequest = interactiveRequest.WithParentActivityOrWindow(AuthUIParent); result = await interactiveRequest.ExecuteAsync(cancellationToken); return result.AccessToken; }
内容的提问来源于stack exchange,提问作者Christian Steuten
相关产品推荐
相关产品推荐

