Search code examples
c#.net-coreazure-active-directorymicrosoft-graph-api

Fetching user list with manager info throwing error "Exception of type 'Microsoft.Graph.Models.ODataErrors.ODataError' was thrown." in MS GRAPH


I am using Microsoft.Graph(5.24) in .net core 6 to fetch all user list along with their Manger names. I do not want to run separate request for it. Till now I have used below mentioned code which is giving error to me.

List<UserProfile> list = new List<UserProfile>(); 
var clientSecretCredential = new ClientSecretCredential(
  tenantId, clientId, clientSecret);
var tokenRequestContext = new TokenRequestContext(scopes);
TokenCredential tokenCredential = clientSecretCredential;
GraphServiceClient graphServiceClient = new GraphServiceClient(tokenCredential, scopes, baseUrl);
var result = await graphServiceClient.Users.GetAsync((requestConfiguration) =>
{
    requestConfiguration.QueryParameters.Expand = new string[] { "manager(displayName)" };
    requestConfiguration.QueryParameters.Search = $"\"mail:{useremail}\" OR \"onPremisesSamAccountName:{useremail}\" OR \"displayname:{useremail}\" OR \"employeeId:{useremail}\"";
    requestConfiguration.QueryParameters.Orderby = new string[] { "displayName" };
    requestConfiguration.QueryParameters.Count = true;
    requestConfiguration.QueryParameters.Select = new string[] { "displayName", "employeeId", "onPremisesSamAccountName", "mail","manager" };
    requestConfiguration.Headers.Add("ConsistencyLevel", "eventual");
});

I can use individual calls for fetching manager data but this will cause the execution delay. Can anyone suggest me what I am missing over here.

Below mentioned step is one possible solution which I want to avoid.

foreach (var user in result.Value)
{
    var manager= await graphServiceClient.Users[user.Mail.ToLower()].Manager.GetAsync();
}

Solution

  • Initially, I registered one Azure AD application and granted User.Read.All permission of Application type as below:

    enter image description here

    To fetch all user list along with their Manager names, I ran below c# code and got response successfully like this:

    using Azure.Identity;
    using Microsoft.Graph;
    using Microsoft.Graph.Models;
    using Microsoft.Graph.Models.ODataErrors;
    
    var scopes = new[] { "https://graph.microsoft.com/.default" };
    
    var clientId = "appId";
    var tenantId = "tenantId";
    var clientSecret = "secret";
    
    var options = new ClientSecretCredentialOptions
    {
        AuthorityHost = AzureAuthorityHosts.AzurePublicCloud,
    };
    
    var clientSecretCredential = new ClientSecretCredential(
        tenantId, clientId, clientSecret, options);
    
    var graphClient = new GraphServiceClient(clientSecretCredential, scopes);
    
    try
    {
        var result = await graphClient.Users.GetAsync((requestConfiguration) =>
        {
            requestConfiguration.QueryParameters.Expand = new string[] { "manager($select=displayName)" };
            requestConfiguration.QueryParameters.Select = new string[] { "displayName", "employeeId", "onPremisesSamAccountName", "mail", "manager" };
        });
    
        foreach (var user in result.Value)
        {
            Console.WriteLine($"Name: {user.DisplayName}");
            Console.WriteLine($"Employee ID: {user.EmployeeId}");
            Console.WriteLine($"OnPremises Sam Account Name: {user.OnPremisesSamAccountName}");
            Console.WriteLine($"Mail: {user.Mail}");
            if (user.Manager != null)
            {
                // Check if the manager object is of type User
                if (user.Manager is User managerUser)
                {
                    Console.WriteLine($"Manager Name: {managerUser.DisplayName}");
                }
                else
                {
                    Console.WriteLine("Manager information not available");
                }
            }
    
            Console.WriteLine();
        }
    }
    catch (ODataError odataError)
    {
        Console.WriteLine(odataError.Error.Code);
        Console.WriteLine(odataError.Error.Message);
    }
    

    Response:

    enter image description here