msgraph-sdk-dotnet-core icon indicating copy to clipboard operation
msgraph-sdk-dotnet-core copied to clipboard

Add access to Headers in BatchRequestContentCollection

Open Dethras opened this issue 1 year ago • 5 comments

Is your feature request related to a problem? Please describe the problem.

I have a specific case where I need to pass something through a Header to be accessed in a DelegatingHandler, with the addition of BatchRequestContentCollection, BatchRequestContent has become obsolete, and there is no way to access the Headers via BatchRequestContentCollection or via graphClient.Batch.PostAsync(BatchRequestContentCollection)

Describe the solution you'd like.

BatchRequestContentCollection or graphClient.Batch.PostAsync(BatchRequestContentCollection) should accept RequestHeaders/RequestInformation, and they should be added with every batch call made with the graphClient.Batch.PostAsync(BatchRequestContentCollection).

Additional context?

No response

Dethras avatar Aug 05 '24 15:08 Dethras

Thanks for raising this @Dethras

To clarify,

  • is this header for each individual request? Or for the entire batch request message?
  • is this scenario possible with BatchRequestContent but not with BatchRequestContentCollection?

andrueastman avatar Aug 06 '24 07:08 andrueastman

Hi @andrueastman

  1. This is for the entire batch request (For the https://graph.microsoft.com/v1.0/$batch call) [Note: For each individual request it is already supported through BatchRequestStep]
  2. It is possible through BatchRequestContent since I can use graphClient.Batch.ToPostRequestInformationAsync and then access the RequestHeaders through the RequestInformation

Dethras avatar Aug 06 '24 10:08 Dethras

Thanks for the extra information here @Dethras

In my head, BatchRequestContentCollection still ends up splitting the requests into BatchRequestContent instances as the API only accepts 20 items at a time. So, this may still be possible.

Any chance you can also share a code example of how you send the request once you get the RequestInformation object?

andrueastman avatar Aug 07 '24 10:08 andrueastman

@andrueastman Apologies for the late reply.

Here is how I am currently doing it using the BatchRequestContent and it's ToPostRequestInformationAsync

var batchToProcess = new BatchRequestContent(graphClient, <Insert max 20 BatchRequest Steps Here>)
var requestInfo = await graphClient.Batch.ToPostRequestInformationAsync(batchToProcess);

requestInfo.Headers.Add(<Header Name>,<Header Value>);

var locationResponseHandler = new NativeResponseHandler();

requestInfo.SetResponseHandler(locationResponseHandler);

await graphClient.RequestAdapter.SendNoContentAsync(requestInfo, cancellationToken: cancellationToken);

var batchResponse = new BatchResponseContent(locationResponseHandler.Value as HttpResponseMessage);
var responses = await batchResponse.GetResponsesStatusCodesAsync();

Dethras avatar Aug 09 '24 12:08 Dethras

I agree with this request for another reason. What I hate about BatchRequestContentCollection is that you have no control over steps you might want to add in between your batches.

A simple example would be to log "Sending batch with X request" each time a batch is sent. Previously when I had my own code to split a list of requests into multiple BatchRequestContent objects, I was the one iterating over my "batches" so I could log whatever I wanted to, retry throttled requests inside a batch of 20 right after its execution etc...

Now we have no control over any of this, so let's say you created a BatchRequestContentCollection with 60 000 requests, after you use Batch.PostAsync() your code is stuck waiting with no feedback in between internally created batches. I managed to handle the retries but now instead of being able to retry between each small batch I have to wait until the 3000 internally created batches are completed in order to be able to create a retry batch.

The only solution I found for the logging now was also to create a DelegatingHandler that interceps $batch calls and logs the amount of requests being executed, that way I can at least keep track of the progress for my 60000 requests...However I can only keep track of all $batch calls for my application, if I wanted to track individual executions of BatchRequestContentCollection, I would need to be able to specify some kind of "operation-id" header that was my handler could store progress by operation.

To me it would still not be ideal because having to create a delegating handler which has to read every single $batch request is still overkill just to be able to log things in-between batches. To me a better solution would be to make accessible the BatchRequestContent objects within a BatchRequestContentCollection, that way I can use BatchRequestContentCollection to make batches splitting for me, but still have control on how I want to execute each BatchRequestContent, but right now I see it's getting depricated...Another solution would be to offer some kind of delegate that the caller can provide, to run before or after an internal batch is executed.

spplante avatar Aug 27 '25 15:08 spplante