调用Microsoft Graph API获取Azure AD用户时出现ODataError异常
Azure AD调用Microsoft Graph获取用户时出现ODataError的解决方案
错误信息
System.AggregateException: One or more errors occurred. (Exception of type 'Microsoft.Graph.Models.ODataErrors.ODataError' was thrown.) ---> Microsoft.Graph.Models.ODataErrors.ODataError: Exception of type 'Microsoft.Graph.Models.ODataErrors.ODataError' was thrown. at Microsoft.Kiota.Http.HttpClientLibrary.HttpClientRequestAdapter.ThrowIfFailedResponse(HttpResponseMessage response, Dictionary`2 errorMapping, Activity activityForAttributes) at Microsoft.Kiota.Http.HttpClientLibrary.HttpClientRequestAdapter.SendAsync[ModelType](RequestInformation requestInfo, ParsableFactory`1 factory, Dictionary`2 errorMapping, CancellationToken cancellationToken) at Microsoft.Kiota.Http.HttpClientLibrary.HttpClientRequestAdapter.SendAsync[ModelType](RequestInformation requestInfo, ParsableFactory`1 factory, Dictionary`2 errorMapping, CancellationToken cancellationToken) at Microsoft.Graph.Users.UsersRequestBuilder.GetAsync(Action`1 requestConfiguration, CancellationToken cancellationToken) --- End of inner exception stack trace --- at System.Threading.Tasks.Task.ThrowIfExceptional(Boolean includeTaskCanceledExceptions) at System.Threading.Tasks.Task`1.GetResultCore(Boolean waitCompletionNotification) at System.Threading.Tasks.Task`1.get_Result() at Xlp.Domain.Services.GraphService1.GetAllUsersAsync() in C:\Users\Shashikantpawar\Desktop\XLP\backend\src\XLP.Domain\Services\GraphService1.cs:line 26 at Xlp.Api.Controllers.ClientsController.Get() in C:\Users\Shashikantpawar\Desktop\XLP\backend\src\Xlp.Api\Controllers\V1\ClientsController.cs:line 40 at lambda_method5(Closure , Object ) at Microsoft.AspNetCore.Mvc.Infrastructure.ActionMethodExecutor.AwaitableObjectResultExecutor.Execute(IActionResultTypeMapper mapper, ObjectMethodExecutor executor, Object controller, Object[] arguments) at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.<InvokeActionMethodAsync>g__Awaited|12_0(ControllerActionInvoker invoker, ValueTask`1 actionResultValueTask) at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.<InvokeNextActionFilterAsync>g__Awaited|10_0(ControllerActionInvoker invoker, Task lastTask, State next, Scope scope, Object state, Boolean isCompleted) at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.Rethrow(ActionExecutedContextSealed context) at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.Next(State& next, Scope& scope, Object& state, Boolean& isCompleted) at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.InvokeInnerFilterAsync() --- End of stack trace from previous location --- at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.<InvokeNextResourceFilter>g__Awaited|25_0(ResourceInvoker invoker, Task lastTask, State next, Scope scope, Object state, Boolean isCompleted) at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.Rethrow(ResourceExecutedContextSealed context) at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.Next(State& next, Scope& scope, Object& state, Boolean& isCompleted) at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.InvokeFilterPipelineAsync() --- End of stack trace from previous location --- at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.<InvokeAsync>g__Awaited|17_0(ResourceInvoker invoker, Task task, IDisposable scope) at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.<InvokeAsync>g__Awaited|17_0(ResourceInvoker invoker, Task task, IDisposable scope) at Microsoft.AspNetCore.Routing.EndpointMiddleware.<Invoke>g__AwaitRequestTask|6_0(Endpoint endpoint, Task requestTask, ILogger logger) at Microsoft.AspNetCore.Authorization.AuthorizationMiddleware.Invoke(HttpContext context) at Swashbuckle.AspNetCore.SwaggerUI.SwaggerUIMiddleware.Invoke(HttpContext httpContext) at Swashbuckle.AspNetCore.Swagger.SwaggerMiddleware.Invoke(HttpContext httpContext, ISwaggerProvider swaggerProvider) at Microsoft.AspNetCore.Diagnostics.DeveloperExceptionPageMiddleware.Invoke(HttpContext context) HEADERS ======= Accept: */* Connection: keep-alive Host: localhost:5224 User-Agent: PostmanRuntime/7.28.4 Accept-Encoding: gzip, deflate, br Postman-Token: 2bb4e39a-686e-4072-af4f-9c85b3760bc2
原代码
public async Task<List<Microsoft.Graph.Models.User>> GetAllUsersAsync() { var clientId = _configuration.GetValue<string>("AzureAd:ClientId"); var tenantId = _configuration.GetValue<string>("AzureAd:TenantId"); var clientSecret = _configuration.GetValue<string>("AzureAd:ClientSecret"); var clientSecretCredential = new ClientSecretCredential(tenantId, clientId, clientSecret); GraphServiceClient graphServiceClient = new GraphServiceClient(clientSecretCredential); var users = graphServiceClient.Users.GetAsync().Result; return users.Value; }
解决步骤
1. 配置正确的应用权限
客户端凭据模式(无用户上下文)需要使用Application类型的权限,且必须由管理员同意:
- 登录Azure门户,进入
Azure AD->应用注册-> 你的应用 - 切换到
API权限,点击添加权限-> 选择Microsoft Graph->应用权限 - 搜索并添加
User.Read.All权限,然后点击授予管理员同意(必须完成此步骤,否则权限不生效)
2. 修复异步调用问题
原代码使用.Result阻塞异步任务,会导致异常被包装在AggregateException中,无法直接查看ODataError的具体详情。改用await调用:
public async Task<List<Microsoft.Graph.Models.User>> GetAllUsersAsync() { var clientId = _configuration.GetValue<string>("AzureAd:ClientId"); var tenantId = _configuration.GetValue<string>("AzureAd:TenantId"); var clientSecret = _configuration.GetValue<string>("AzureAd:ClientSecret"); var clientSecretCredential = new ClientSecretCredential(tenantId, clientId, clientSecret); GraphServiceClient graphServiceClient = new GraphServiceClient(clientSecretCredential); var users = await graphServiceClient.Users.GetAsync(); return users.Value; }
3. 验证凭据正确性
确认配置文件中的ClientId、TenantId、ClientSecret完全匹配Azure应用注册中的信息:
ClientId是应用的"应用程序(客户端)ID"TenantId是目录(租户)IDClientSecret是在应用注册证书和密码中生成的客户端密码,不是密钥ID
4. 捕获并解析ODataError详情
添加异常捕获逻辑,获取具体错误码和描述,便于精准排查:
public async Task<List<Microsoft.Graph.Models.User>> GetAllUsersAsync() { var clientId = _configuration.GetValue<string>("AzureAd:ClientId"); var tenantId = _configuration.GetValue<string>("AzureAd:TenantId"); var clientSecret = _configuration.GetValue<string>("AzureAd:ClientSecret"); var clientSecretCredential = new ClientSecretCredential(tenantId, clientId, clientSecret); GraphServiceClient graphServiceClient = new GraphServiceClient(clientSecretCredential); try { var users = await graphServiceClient.Users.GetAsync(); return users.Value; } catch (Microsoft.Graph.Models.ODataErrors.ODataError odataError) { // 记录或输出具体错误信息 var errorCode = odataError.Error.Code; var errorMessage = odataError.Error.Message; throw new InvalidOperationException($"Graph API调用失败: {errorCode} - {errorMessage}", odataError); } }
内容的提问来源于stack exchange,提问作者Shashikant Pawar
相关产品推荐
相关产品推荐

