I'm using the Microsoft Graph SDK for C# to read data from Microsoft Graph. I also utilize the Microsoft Developer Proxy to simulate responses with an HTTP 429 status (TooManyRequests) for testing purposes.
However, upon encountering a 429 status, the SDK's default behavior is to retry the request up to three times. If it still gets a 429 response after the third retry, it throws a System.InvalidOperationException with the message "Too many retries performed." This behavior is evident from the proxy's output.
Here's the relevant code:
var authenticationProvider = new BaseBearerTokenAuthenticationProvider(new TokenProvider(_token));
var graphServiceClient = new GraphServiceClient(authenticationProvider);
var myTeams = await graphServiceClient
.Me
.JoinedTeams
.GetAsync(requestConfiguration => requestConfiguration.QueryParameters.Select = new string[] { "Id" });
And the proxy's output:
request GET https://graph.microsoft.com/v1.0/me/joinedTeams?$select=Id
chaos ╭ 429 TooManyRequests
╰ GET https://graph.microsoft.com/v1.0/me/joinedTeams?$select=Id
...
My question is: How can I override the default behavior of the Microsoft Graph SDK for C# to handle the 429 status code myself? Ideally, I'd like to either adjust the request rate or implement other custom handling when this happens.
You can either pass per-request options to the default http middleware
var retryHandlerOption = new RetryHandlerOption
{
MaxRetry = 7,
ShouldRetry = (delay,attempt,message) => true
};
var myTeams = await graphServiceClient
.Me
.JoinedTeams
.GetAsync(requestConfiguration =>
{
requestConfiguration.QueryParameters.Select = new string[] { "Id" };
requestConfiguration.QueryParameters.Options.Add(retryHandlerOption);
});
Or replace the default RetryHandler with custom implementation
public class CustomRetryHandler : DelegatingHandler
{
protected override Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
{
// your code
}
}
Creating GraphServiceClient
with replaced default RetryHandler
var authenticationProvider = new BaseBearerTokenAuthenticationProvider(new TokenProvider(_token));
var handlers = GraphClientFactory.CreateDefaultHandlers();
// dummy replacement
var retryHandler = handlers.FirstOrDefault(x => x is RetryHandler);
var index = handlers.IndexOf(retryHandler);
handlers[index] = new CustomRetryHandler();
var httpClient = GraphClientFactory.Create(handlers);
var graphServiceClient = new GraphServiceClient(httpClient, authenticationProvider);