Search code examples
asp.net-coreauthenticationmicrosoft-graph-apimicrosoft-graph-teamsgraphserviceclient

Error retrieving "UserId" from the members of a Microsoft Teams team


Good morning people,

I'm to get all the teams members of the Microsoft Teams teams in the organization of the user who signing on my web.

The login was made with GraphServiceClient

Once the user login, I save the graphClient instance and in my controller I have this code:

public async Task<IActionResult> Index()
{
    List<UserModel> users = new List<UserModel>();
    var result = await graphClient.Teams.GetAsync();
    foreach (var team in result.Value)
    {
        var members = await graphClient.Teams[team.Id].Members.GetAsync();
        foreach (var member in members.Value)
        {
            var user = await graphClient.Users[member.UserId].GetAsync();
            UserModel userModel = new UserModel(user.Id, user.DisplayName, user.Mail, user.Department, user.JobTitle, user.MobilePhone, user.OfficeLocation, "");
            users.Add(userModel);
        }
    }
    return View(users);
}

The problem is this: enter image description here

But when I run the same query in Microsoft Graph Explorer, I notice the object member must contain a UserId property.

enter image description here

And if that's not enough, debugging the solution, I can notice effectively my object member contain a UserId property.

enter image description here

So where is the problem?


Solution

  • That's because the response value member is type of ConversationMember, and it's the base type of AadUserConversationMember. It's also the base type for the below types. We can see more details here.

    anonymousGuestConversationMember,
    azureCommunicationServicesUserConversationMember,
    microsoftAccountUserConversationMember,
    skypeForBusinessUserConversationMember,
    skypeUserConversationMember,
    

    In your sceenshoot, we could see that your are getting a member which is type of AadUserConversationMember and that's why it has UserId property, but if the member is AnonymousGuestConversationMember, it doesn't contain a UserId property.

    enter image description here

    Generally speaking, the members collection we get might be made up with several types of data, some of them has property UserId but some of them might not, they are all team members, to include them all, we abstract a base type ConversationMember and it only contains Id property instead of UserId which is only available for some of the types.

    If we are trying to get all user type members' profile, we demand to add a validate like code below. But please note, I haven't test it out about the if clause as I don't have the test result, I just show my idea here. We might also add filter when getting the members to only get AadUserConversationMember type of members returned(Maybe with request like this GET https://graph.microsoft.com/v1.0/teams/teamsId/members?$filter=(microsoft.graph.aadUserConversationMember/userId ne null)).

    var result = await _graphServiceClient.Teams.GetAsync();
    foreach (var team in result.Value)
    {
        ConversationMemberCollectionResponse members = await _graphServiceClient.Teams[team.Id].Members.GetAsync();
        foreach (ConversationMember member in members.Value)
        {
            if (member.OdataType == "aadUserConversationMember") {
                AadUserConversationMember user1 = (AadUserConversationMember)member;
                var res = await _graphServiceClient.Users[user1.UserId].GetAsync();
            }
        }
    }