Chris Gunawardena
Chris Gunawardena

Reputation: 6468

Microsoft graph: Invalid batch payload format

I'm trying to batch update a list of users, using the MS Graph Batch API following the example from the docs but getting the error "Message: Invalid batch payload format."

// batch disable all users
var allUsers = await GraphHelper.client.Users.Request().Select("id").GetAsync();

var batchRequestContent = new BatchRequestContent();
allUsers.Select(user =>
{
  var httpRequest = GraphHelper.client.Users[user.Id].Request().GetHttpRequestMessage();
  httpRequest.Method = HttpMethod.Put;
  httpRequest.Content = GraphHelper.client.HttpProvider.Serializer.SerializeAsJsonContent(new User { AccountEnabled = false });
  return batchRequestContent.AddBatchRequestStep(httpRequest);
});
var userUpdateResult = await GraphHelper.client.Batch.Request().PostAsync(batchRequestContent);

The code below to disable a user already works without batching.

var user = new User { AccountEnabled = false };
var userResult = await GraphHelper.client.Users[id].Request().UpdateAsync(user);

Upvotes: 2

Views: 2923

Answers (5)

Modern Ronin
Modern Ronin

Reputation: 701

Actually, the problem is that the allUsers.Select(...) is never fully iterated.

So, either append .ToArray() or, if you got something like MoreLinq, .ForEach() and it'll work.

Upvotes: 0

Jeff L.
Jeff L.

Reputation: 900

I was running into this same issue and after a bit of trial/error I figured out that the issue is being caused by the .Select method. I noticed that the batchRequestContent has a dictionary in it which contains all of the requests to be processed. When adding the requests from within the .Select the count never increased.

Converting it to use a standard foreach resolved the issue for me and the batchRequestContent successfully showed it's dictionary count increasing as I added new requests to the batch.

var batchRequestContent = new BatchRequestContent();
var batchIds = new List<string>();
foreach(var query in queries)
{
    var id = batchRequestContent.AddBatchRequestStep(query);
    batchIds.Add(id);
}

Upvotes: 1

Omer Shlifka
Omer Shlifka

Reputation: 263

For me, what solved it was to add 'headers' field to the request body, and not only to the headers of the request:

{'requests': [{
                'id': '1',
                'method': 'GET',
                'url': '/...'
            }, {
                'id': '2',
                'method': 'GET',
                'url': '/...'
            }], 'headers': {
                'Content-Type': 'application/json'
            }}

Upvotes: 1

Jeremy Bradshaw
Jeremy Bradshaw

Reputation: 119

@chris-gunawardena and @shiva-msft-identity I'm wondering if you've any idea what could be going wrong for me, as I'm getting "Invalid batch payload format" when submitting POST method requests to create new items on an SPO list. The same requests sent individually work no problem, and it seems like an issue with how I'm supplying the body/content. My issue is over here (and I'm using PowerShell):

MS Graph batching create list item (SPO) Invalid batch payload format

Note I see in the JSON Batching video by Microsoft which is on the Docs page, in Graph Explorer they use "ContentType": "application/json" whereas the example on the docs page says to supply the "Content-Type" header (note the hyphen). I've tried using both ContentType and Content-Type for my header (and with application/json) in either case, but it's "Invalid batch payload format" in either case. If I drop my headers alltogether (the only header in the array of requests is Content-Type (or ContentType)), I then get the error Write request id : 2 does not contain Content-Type header or body.". So it seems like the payload format is at least reasonably close to 'valid'. It's exactly as I see it in the example on Docs (and in the video from MS).

Upvotes: 0

Shiva Keshav Varma
Shiva Keshav Varma

Reputation: 3595

I am also able to get same sort of error if I use the lambda operator rather I changed it to foreach loop and added batch requests as shown below.

static async Task<BatchResponseContent> BulkUpdate()
{
    var allUsers = await GraphHelper.graphClient.Users.Request().Top(10).Select("id").GetAsync();

    var batchRequestContent = new BatchRequestContent();
    foreach(var items in allUsers)
    { 
        var httpRequest = GraphHelper.graphClient.Users[items.Id].Request().GetHttpRequestMessage();
        httpRequest.Method = HttpMethod.Patch;
        httpRequest.Content = GraphHelper.graphClient.HttpProvider.Serializer.SerializeAsJsonContent(new User { AccountEnabled = false });
        batchRequestContent.AddBatchRequestStep(httpRequest);
    }
    var userUpdateResult = await GraphHelper.graphClient.Batch.Request().PostAsync(batchRequestContent);
    return userUpdateResult;
}

This way I am able to add bulk requests to the batchRequestContent variable as you can see in the below picture.

(JSON Data)Body of Batch Request

Note: JSON batch requests are currently limited to 20 individual requests.

Upvotes: 1

Related Questions