Azure AD Graph 客户端库批处理

Azure AD Graph client library batch processing

谁能告诉我是否可以使用批处理来添加群组成员?

如果可以请举个例子

提前致谢

亲切的问候,

斯内加

documentation, Graph API support batch processing. The Microsoft Azure Active Directory Client支持批处理。

您可以在此处找到大量使用 Azure AD Graph API 的示例:

特别是你有一个关于你可以用图表 API 执行的大部分操作的完整示例:

不幸的是,批处理不适用于导航属性,或者至少我没有找到让它工作的方法...

让我们来看看documentation

Graph API support for OData batch requests:

  • A query is a single query or function invocation.
  • A change set is a group of one or more insert, update, or delete operations, action invocations, or service invocations.
  • A batch is a container of operations, including one or more change sets and query operations.

The Graph API supports a subset of the functionality defined by the OData specification:

  • A single batch can contain a maximum of five queries and/or change sets combined.
  • A change set can contain a maximum of one source object modification and up to 20 add-link and delete-link operations combined. All operations in the change set must be on a single source entity.

批量请求语法如下:

https://graph.windows.net/TenantName/$batch?api-version=1.6

使用单个 POST 指令将批处理请求发送到服务器。

有效负载是一个多部分 MIME 消息,其中包含批处理及其组成查询和更改集。负载包括两种类型的 MIME 边界:

  • 批次边界 分隔批次中的每个查询and/or 更改集。
  • 更改集边界 分隔更改集中的各个操作。

更改集中的单个请求与调用该操作本身时发出的请求相同。 (here is a sample request)

您可以在这里找到完整的示例代码:azure-active-directory-batchprocessing 所以基本上,您需要获取身份验证令牌:

var authority = "https://login.microsoftonline.com/mytenantName.onmicrosoft.com";
var resource = "https://graph.windows.net/";
var clientId = "ClientId of the application in the Azure Active Directory";
var clientSecret = "ClientSecret of the application in the Azure Active Directory";

var token = new AuthenticationContext(authority, false).AcquireToken(resource,
        new ClientCredential(clientId, clientSecret)).AccessToken;

在您的问题中,您希望将成员添加到群组 (see Graph API Documentation on groups):

// Get the objectId of the group
var groupId = ...

// Get the member ids you'd like to add to the group
var memberIds = ...

这是将成员添加到群组的代码:

private static async Task AddMemberToGroup(string token, string groupId, IList<string> memberIds)
{
    if (memberIds.Count > 100)
    {
        // A batch can contain up to 5 changesets. Each changeset can contain up to 20 operations.
        throw new InvalidOperationException("Cannot send more than 100 operation in an batch");
    }

    var batch = new BatchRequest("https://graph.windows.net/MyTenantName.onmicrosoft.com");

    // A changeset can contain up to 20 operations
    var takeCount = 20;
    var skipCount = 0;
    var take = memberIds.Skip(skipCount).Take(takeCount).ToList();
    while (take.Count > 0)
    {
        AddChangeset(batch, groupId, take);
        skipCount += takeCount;
        take = memberIds.Skip(skipCount).Take(takeCount).ToList();
    }

    using (var client = new HttpClient())
    {
        client.DefaultRequestHeaders.Add("Authorization", $"Bearer {token}");
        var response = await client.SendAsync(batch.Request);
    }
}

private static void AddChangeset(BatchRequest batch, string groupId, IEnumerable<string> memberIds)
{
    var changeset = batch.AddChangeSet();
    foreach (var memberId in memberIds)
    {
        // Create the HttpRequest to add a member to a group
        var request = AddMemberToGroupRequest(groupId, memberId);

        // Add the operation to the changeset
        changeset.AddOperation(request);
    }
}

private static HttpRequestMessage AddMemberToGroupRequest(string groupId, string memberId)
{
    // Create a request to add a member to a group
    var request = new HttpRequestMessage(HttpMethod.Post,
        $"https://graph.windows.net/MyTenantName.onmicrosoft.com/groups/{groupId}/$links/members?api-version=1.6");

    // Create the body of the request
    var jsonBody =
        JsonConvert.SerializeObject(new DirectoryObject($"https://graph.windows.net/MyTenantName.onmicrosoft.com/directoryObjects/{memberId}"));

    // Set the content
    request.Content = new StringContent(jsonBody, Encoding.UTF8, "application/json");

    // Return the request
    return request;
}

public class BatchRequest
{
    private readonly MultipartContent _batchContent;

    public BatchRequest(string tenantUrl)
    {
        // Create the batch request
        Request = new HttpRequestMessage(HttpMethod.Post,
            $"{tenantUrl}/$batch?api-version=1.6");

        // Initializes the batch content
        _batchContent = new MultipartContent("mixed", "batch_" + Guid.NewGuid());
        Request.Content = _batchContent;
    }

    public HttpRequestMessage Request { get; }

    public ChangeSet AddChangeSet()
    {
        // Create a new changeset
        var changeSet = new ChangeSet();

        // Add the content of the changeset to the batch
        _batchContent.Add(changeSet.Content);

        // return the changeset
        return changeSet;
    }

    public HttpMessageContent CreateOperation(HttpRequestMessage request)
    {
        var content = new HttpMessageContent(request);
        content.Headers.ContentType = new MediaTypeHeaderValue("application/http");
        content.Headers.Add("Content-Transfer-Encoding", "binary");
        return content;
    }
}

public class ChangeSet
{
    public ChangeSet()
    {
        Content = new MultipartContent("mixed", "changeset_" + Guid.NewGuid());
    }

    public MultipartContent Content { get; }

    public void AddOperation(HttpRequestMessage request)
    {
        var operationContent = new HttpMessageContent(request);
        operationContent.Headers.ContentType = new MediaTypeHeaderValue("application/http");
        operationContent.Headers.Add("Content-Transfer-Encoding", "binary");
        Content.Add(operationContent);
    }
}

public class DirectoryObject
{
    public DirectoryObject(string url)
    {
        this.url = url;
    }
        public string url { get; }
}