I am trying to use GraphAPI v5 in a Blazor .NET 8.0 application, to request a list of all users who have a certain AppRole assigned.
I configure the roles in Entra Admin Centre > Enterprise applications > (my app) > Users and Groups, and assign users to Roles that I defined in the application registration.
I have tried the following code in a Razor page:
@inject GraphServiceClient GSC@inject MicrosoftIdentityConsentAndConditionalAccessHandler ConsentHandler// ...protected async Task AzTest(){ try { var users = await GSC.Users.GetAsync((requestConfiguration) => { requestConfiguration.QueryParameters.Expand = new string[] { "appRoleAssignments" }; }); } catch(Exception ex) { ConsentHandler.HandleException(ex); }}I also found (thanks to commentor) that Directory.Read.All was a required Scope for this call to work.
My question is: how do I filter the result to find just the users with a specific Role? My organization has over 1000 users.
I have tried the following approaches:
Approach 1 - Filter
Guid roleIdGuid = new Guid("5f61fba7-ae07-4438-9f41-4c00b2540463");// ...requestConfiguration.QueryParameters.Filter = $"appRoleAssignments/any(ar: ar/appRoleId eq {roleIdGuid})";(this was suggested by Copilot). This gives a runtime error :
Microsoft.Graph.Models.ODataErrors.ODataError: Property 'appRoleId' does not exist as a declared property or extension property.which Copilot suggests means that the API does not actually support filtering by App Role ID.
Approach 2 - Pagination
Another approach is to retrieve all users via Pagination, and then go through them in C# to check for the role ID. However, the pagination doesn't seem to work. Using the exact code from the V5 documentation:
var usersResponse = await graphServiceClient .Users .GetAsync(requestConfiguration => { requestConfiguration.QueryParameters.Expand = new string[] { "appRoleAssignments" }; requestConfiguration.QueryParameters.Top = 1; });var userList = new List<User>();var pageIterator = PageIterator<User,UserCollectionResponse>.CreatePageIterator(graphServiceClient,usersResponse, (user) => { userList.Add(user); return true; });await pageIterator.IterateAsync();// (omitted the later filtering code for brevity)This ran but I waited for over 90 seconds and it was still making API calls and responses on the await part; I'm not sure if it was stuck in an infinite loop somehow or just taking forever, but at any rate, that sort of delay isn't an acceptable solution.