Azure Function中PageIterator回调返回true报错:无法将Task<bool>转为bool
问题描述
从微软文档获取的Microsoft Graph获取用户的代码,在控制台应用中可正常运行,但部署到Azure Function后,PageIterator的回调函数返回true时出现无法从Threading.Tasks
用户提供的核心代码片段:
var pageIterator = PageIterator<User, UserCollectionResponse> .CreatePageIterator( graphclient, result, // 触发错误的回调 (rsl) => { Console.WriteLine(rsl.Mail); return true; }, (req) => { return req; });
问题原因
Azure Function的运行时环境对异步模式的要求比控制台应用更严格,PageIterator的回调函数在该环境下被要求返回Task<bool>类型,而非直接返回同步的bool值,控制台中允许的同步回调签名在此处无法匹配。
修复方案
1. 修改回调函数为异步形式
将同步回调改为异步,返回Task<bool>:
async (rsl) => { // 替换Console.WriteLine为Azure Function日志输出 log.LogInformation(rsl.Mail); return await Task.FromResult(true); }
2. 修复其他潜在问题
代码中还有两处可能导致Azure Function异常的问题,建议一并修复:
- 移除GraphServiceClient静态单例:当前静态单例会导致不同请求间凭据混用,每次请求应创建新实例:
public static async Task<GraphServiceClient> graphclient(string CID, string TID, string SID) { var accessToken = await adAccesToken(CID, TID, SID); var accessTokenProvider = new BaseBearerTokenAuthenticationProvider(new TokenProvider(accessToken)); return new GraphServiceClient(accessTokenProvider); }
- 异步获取AccessToken:原方法使用
.Result同步等待可能引发死锁,改为异步实现:
private static async Task<string> adAccesToken(string CID, string TID, string SID) { IEnumerable<string> scopes = new List<string>() { "https://graph.microsoft.com/.default" }; IConfidentialClientApplication app = ConfidentialClientApplicationBuilder.Create(CID) .WithClientSecret(SID) .WithTenantId(TID) .Build(); var result = await app.AcquireTokenForClient(scopes).ExecuteAsync(); return result.AccessToken; }
- 更新TokenProvider类:简化实现,直接传入已获取的Token:
private class TokenProvider : IAccessTokenProvider { private readonly string _accessToken; public TokenProvider(string accessToken) { _accessToken = accessToken; } public Task<string> GetAuthorizationTokenAsync(Uri uri, Dictionary<string, object> additionalAuthenticationContext = default, CancellationToken cancellationToken = default) { return Task.FromResult(_accessToken); } public AllowedHostsValidator AllowedHostsValidator { get; } = new AllowedHostsValidator(); }
3. 更新Run方法中的调用
调整GraphServiceClient的获取为异步:
var graphClient = await graphclient(ClientID, TenantID, SecretID); UserCollectionResponse result = await graphClient.Users.GetAsync((requestConfiguration) => { if (ReqPrm != null) { requestConfiguration.QueryParameters.Select = ReqPrm; } requestConfiguration.QueryParameters.Top = PageSize; if (FilterPrm != null) { requestConfiguration.QueryParameters.Filter = FilterPrm; } });
内容的提问来源于stack exchange,提问作者ardayz
相关产品推荐
相关产品推荐

