I have an Admin application written in C# with the Microsoft.Graph.Beta
extension and this uses .Request() to allow users from a B2C to be viewed and searched, I have a separate application that uses the new 5.52.0 Microsoft Graph
and Azure.Identity
that can be used to add and update users in the B2C using the Users.PostAsync
method. With this being the more secure application I need the features of the first one to be migrated over but the new Graph appears to have made .Request() redundant which is the only method I know to get data from the B2C.
Here is the viewing code from the first application -
public static async Task ListUsers(GraphServiceClient graphClient)
{
Console.WriteLine("Getting list of users...");
// Get all users (one page)
var result = await graphClient.Users
.Request()
.Select(e => new
{
e.DisplayName,
e.Id,
e.Identities,
e.BusinessPhones
})
.GetAsync();
// Calculate maximum lengths
int maxDisplayNameLength = result.CurrentPage.Max(u => u.DisplayName.Length);
int maxIdLength = result.CurrentPage.Max(u => u.Id.Length);
int maxEmailLength = result.CurrentPage
.Where(u => u.Identities.Any(i => i.SignInType == "emailAddress")) // Filter users with email addresses
.Select(u => u.Identities.FirstOrDefault(i => i.SignInType == "emailAddress")?.IssuerAssignedId)
.Where(email => email != null)
.Max(email => email.Length);
bool isFirst = true;
foreach (var user in result.CurrentPage)
{
// Get email if available
string email = user.Identities.FirstOrDefault(i => i.SignInType == "emailAddress")?.IssuerAssignedId;
// If user has no email, skip to the next iteration
if (email == null)
continue;
// Get phone numbers
string phoneNumbers = string.Join(", ", user.BusinessPhones);
if (isFirst)
{
Console.WriteLine("------------------------");
isFirst = false;
}
// Format output with alignment based on maximum lengths
Console.WriteLine($"DisplayName: {user.DisplayName.PadRight(maxDisplayNameLength)}");
Console.WriteLine($"Id: {user.Id.PadRight(maxIdLength)}");
Console.WriteLine($"Email: {email?.PadRight(maxEmailLength) ?? string.Empty}");
Console.WriteLine($"Phone Numbers: {phoneNumbers}"); // Display phone numbers
Console.WriteLine("------------------------"); // Add a line separator
}
}
Which works flawlessly in the older Graph version but I need it migrated into the new application for security reasons. Below is an attempt at the same logic in the new application and if ran you would notice it throws errors relating to the .Request() -
`static async Task ListUsers()
{
var scopes = new[] { "https://graph.microsoft.com/.default" };
var tenantId = "...";
var clientId = "...";
var clientSecret = "...";
var clientSecretCredential = new ClientSecretCredential(tenantId, clientId, clientSecret);
var graphClient = new GraphServiceClient(clientSecretCredential, scopes);
try
{
// Retrieve users from Microsoft Graph
var users = await graphClient.Users.Request().GetAsync();
// Display user details
foreach (var user in users)
{
Console.WriteLine($"Display Name: {user.DisplayName}");
Console.WriteLine($"Given Name: {user.GivenName}");
Console.WriteLine($"Surname: {user.Surname}");
Console.WriteLine($"Email Address: {user.Mail}");
Console.WriteLine($"Business Phone Number: {user.BusinessPhones?[0]}");
Console.WriteLine();
}
}
catch (Exception ex)
{
Console.WriteLine($"Error listing users: {ex.Message}");
}
}`
Is there a new method in modern Graph to replace this?
Note that: Request()
is removed from the latest version of Microsoft Graph and hence you need to remove the Request()
from the code to resolve the error. Refer this GitHub Blog.
To resolve the error, modify the code like below:
using Microsoft.Graph;
using Azure.Identity;
class Program
{
static async Task Main()
{
string tenantId = "TenantID";
string clientId = "ClientID";
string clientSecret = "ClientSecret";
var clientSecretCredential = new ClientSecretCredential(tenantId, clientId, clientSecret);
var graphClient = new GraphServiceClient(clientSecretCredential);
try
{
var users = await graphClient.Users.GetAsync((requestConfiguration) =>
{
requestConfiguration.QueryParameters.Select = new string[] { "displayName", "GivenName", "Surname", "Mail" };
});
foreach (var user in users.Value)
{
Console.WriteLine($"Display Name: {user.DisplayName}");
Console.WriteLine($"Given Name: {user.GivenName}");
Console.WriteLine($"Surname: {user.Surname}");
Console.WriteLine($"Street Address: {user.Mail}");
Console.WriteLine(" ");
}
}
catch (Exception ex)
{
Console.WriteLine($"Error listing users: {ex.Message}");
}
}
}