Add users to a group in a batch with the Microsoft Graph C# SDK

Introduction

Managing users in large organizations can be a daunting task, especially when it comes to adding multiple users to groups. Thankfully, the Microsoft Graph API and all SDKs offer a powerful solution for batch processing, making this task more efficient and less error-prone.

Batching

Batching allows you to send multiple requests to the Microsoft Graph API in a single HTTP request. This can help you improve the performance of your application by reducing the number of HTTP requests that need to be made.

Batching with the Microsoft Graph C# SDK

The Microsoft Graph C# SDK provides these classes to help you work with batch requests and responses:

  • BatchRequestContentCollection - Represents a collection of all batch requests
  • BatchResponseContentCollection - Represents a collection of all batch responses

As you may know, the Microsoft Graph API has a limit of 20 requests per batch. The BatchRequestContentCollection class automatically splits the requests into multiple batches if the number of requests exceeds this limit of 20 requests.

Add requests to the batch

The SDK uses a builder pattern to easily construct a HTTP request. The request itself contains information about the URL, query parameters and selected HTTP method.

When working with batch requests, you need to create an instance of the RequestInformation for a specific request and add it to the BatchRequestContentCollection via the AddBatchRequestStepAsync method.

The second parameter of the AddBatchRequestStepAsync method is the requestId which can be used to identify the response for a specific request.

// request info to make a GET request to the /me endpoint
var requestInfo = client.Me.ToGetRequestInformation();
await batchCollection.AddBatchRequestStepAsync(requestInfo, requestId: "me");

// request info to make a DELETE request to the /sites/{site-id}/lists/{list-id}/items/{item-id} endpoint
var requestInfo = client.Sites["{site-id}"].Lists["{list-id}"].Items["{item-id}"].ToDeleteRequestInformation();
await batchCollection.AddBatchRequestStepAsync(requestInfo, requestId: "removeListItem");

Once you have added all the requests to the BatchRequestContentCollection object, you can send the batch request(s) to the Microsoft Graph API.

var batchResponse = await client.Batch.PostAsync(batchCollection);

If the batchCollection contains more than 20 requests, the SDK will automatically split the requests into multiple batches, send them to the Microsoft Graph API and collect responses for all batches.

Process the batch response

The BatchResponseContentCollection object contains the responses for all the requests in the batch.

You can access the response for a specific request id by using the GetResponseByIdAsync(requestId) method.

If you want to only check the status codes of all responses, you can use the GetResponsesStatusCodesAsync() method.

Process the error

What if one of the requests in the batch fails? Currently, the SDK does not provide any method to get the error. Just try to read the response and handle the ServiceException exception.

If the ServiceException exception is thrown, you need to deserialize the RawResponseBody to the ODataError object to get the error message.

try
{
    var user = await batchResponse.GetResponseByIdAsync<User>("requestId");
}
catch (ServiceException error)
{
    var odataError = await KiotaJsonSerializer.DeserializeAsync<ODataError>(error.RawResponseBody);
    Console.WriteLine($"Error: {odataError.Message}");
}

If the request inside the batch doesn't return a response body, you need to use a different approach to get the error:

var responseMessage = await batchResponse.GetResponseByIdAsync("requestId");
var stringContent = await responseMessage.Content.ReadAsStringAsync();
var odataError = await KiotaJsonSerializer.DeserializeAsync<ODataError>(stringContent);
Console.WriteLine($"Error: {odataError.Message}");

Add users to a group in a batch

Let's try to create a collection of new users and add them to a group.

Create new users

The first step is to send a batch request to create new users.

// init a collection of batch requests
var batchCollection = new BatchRequestContentCollection(client);

var userIds = new List<string>();

for (int i = 1; i <= 55; i++)
{
    // create a new instance of User model and set the required properties
    var newUser = new User
    {
        AccountEnabled = true,
        DisplayName = $"User {i}",
        MailNickname = $"user{i}",
        UserPrincipalName = $"user{i}@contoso.onmicrosoft.com",
        PasswordProfile = new PasswordProfile
        {
            Password = $"Pa$$w0rd{i}",
            ForceChangePasswordNextSignIn = false
        }
    };

    // create request information about the new user
    var requestInfo = client.Users.ToPostRequestInformation(newUser);

    // add request info with unique request id to the batch collection
    await batchCollection.AddBatchRequestStepAsync(requestInfo, requestId: $"user{i}");
}

// send all batch requests
var batchResponse = await client.Batch.PostAsync(batchCollection);

// read responses status codes
var responsesStatusCodes = await batchResponse.GetResponsesStatusCodesAsync();

foreach (var response in responsesStatusCodes)
{
    Console.WriteLine($"Response {response.Key} with status code {response.Value}");
    try
    {
        var user = await batchResponse.GetResponseByIdAsync<User>(response.Key);
        userIds.Add(user.Id);
    }
    catch (ServiceException error)
    {
        var odataError = await KiotaJsonSerializer.DeserializeAsync<ODataError>(error.RawResponseBody);
        Console.WriteLine($"Error: {odataError.Message}");
    }
}

Add users to a group

The next step is to add the newly created users to a group. The Graph API provides two endpoints to add members to a group:

  • POST https://graph.microsoft.com/v1.0/groups/{group-id}/members/$ref - allows to add a single member
  • PATCH https://graph.microsoft.com/v1.0/groups/{group-id} - allows to add up to 20 members

In our case, we will use the second endpoint which allows us to add up to 20 members in a single request. When using the batch request, you can add up to 400 members in a single batch.

var batchCollection = new BatchRequestContentCollection(client);

for (int i = 0; i < userIds.Count; i += 20)
{
    var selectedUserIds = userIds.Skip(i).Take(20);
    var members = selectedUserIds.Select(id => $"https://graph.microsoft.com/v1.0/directoryObjects/{id}");

    var requestBody = new Group
    {
        AdditionalData = new Dictionary<string, object>
        {
            {
                "members@odata.bind" , members
            }
        }
    };

    var request = client.Groups[groupId].ToPatchRequestInformation(requestBody);

    await batchCollection.AddBatchRequestStepAsync(request, $"batch{i}");
}

var batchResponse = await client.Batch.PostAsync(batchCollection);

var responsesStatusCodes = await batchResponse.GetResponsesStatusCodesAsync();

foreach (var response in responsesStatusCodes)
{
    Console.WriteLine($"Response {response.Key} with status code {response.Value}");
    if (response.Value != System.Net.HttpStatusCode.NoContent)
    {
        try
        {
            var responseMessage = await batchResponse.GetResponseByIdAsync(response.Key);
            var stringContent = await responseMessage.Content.ReadAsStringAsync();
            var odataError = await KiotaJsonSerializer.DeserializeAsync<ODataError>(stringContent);
            Console.WriteLine($"Error: {odataError.Message}");
        }
        catch (Exception ex)
        {
            Console.WriteLine($"Error: {ex.Message}");
        }
    }
}

Now you can check that all users have been created and added to the group.

Conclusion

Batch processing with the Microsoft Graph API can significantly streamline user management tasks.

You can find the complete code sample in the GitHub repository

0
Buy Me a Coffee at ko-fi.com
An error has occurred. This application may no longer respond until reloaded. Reload x