.NET Graph SDK v5 RetryHandler question

Aurélien N 21 Reputation points Microsoft Employee
2023-07-14T13:28:45.42+00:00
I am working on a .NET app that uses Graph SDK v5 to import custom domains in Azure.
I create the GraphServiceClient object like this:
        appClient = new GraphServiceClient(clientSecretCredential, new[] { https://graph.microsoft.com/.default });
Then I do some graph calls and sometimes I get a timeout exception because the request exceeded the default 100 seconds timeout value of the underlying HttpClient object.
I did a fiddler trace and noticed that I received a 429 response (throttling), but the Retry-After value is 187. 
This is more than the default timeout, which led me to the timeout exception (I was surprised that I did not get this 429 response in my code).

I then instantiated the GraphServiceClient this way, so that I can change the Timeout to a larger value than 187:
        HttpClient httpClient = GraphClientFactory.Create();
        string token = clientSecretCredential.GetToken(new TokenRequestContext(new[] { https://graph.microsoft.com/.default })).Token;
        httpClient.DefaultRequestHeaders.Add("Authorization", $"Bearer {token}");
        httpClient.Timeout = TimeSpan.FromSeconds(220);
        appClient = new GraphServiceClient(httpClient);

Now, I can see that the retry works fine, without timeout exception anymore.

Now I want to display a message to the user, so that he is aware that a retry will happen if throttling occurs.
So I tried to implement it this way:
        RetryHandler retryHandler = new RetryHandler(new RetryHandlerOption()
        {
                ShouldRetry = (int delay, int numberOfRetry, HttpResponseMessage response) =>
                {
                     if (response.StatusCode == System.Net.HttpStatusCode.TooManyRequests)
                     {
                         Console.WriteLine($"Received {response.StatusCode} from Graph API. Will retry in {delay} seconds.");
                         return true;
                     }
                     return false;
                }
        });

        HttpClient httpClient = GraphClientFactory.Create(new List<DelegatingHandler> { retryHandler });
        string token = clientSecretCredential.GetToken(new TokenRequestContext(new[] { https://graph.microsoft.com/.default })).Token;
        httpClient.DefaultRequestHeaders.Add("Authorization", $"Bearer {token}");
        httpClient.Timeout = TimeSpan.FromSeconds(220);
        appClient = new GraphServiceClient(httpClient);

When I now run the app, I go in the ShouldRetry function after each successful request, but never when the response is 429, thus my message is never displayed.
Once again, I notice that I never get the 429 response in my code.
I’m probably doing something wrong, but I cannot figure out what.

.NET
.NET
Microsoft Technologies based on the .NET software framework.
4,108 questions
Microsoft Graph
Microsoft Graph
A Microsoft programmability model that exposes REST APIs and client libraries to access data on Microsoft 365 services.
13,065 questions
0 comments No comments
{count} votes

Accepted answer
  1. Andrew Omondi 256 Reputation points Microsoft Employee
    2023-07-17T16:51:44.05+00:00

    I believe the behavior can be explained by the short circuit operator in the handler below.

    https://github.com/microsoft/kiota-http-dotnet/blob/main/src/Middleware/RetryHandler.cs#L72

    Irrespective of the ShouldRetry parameter, the SDK will have already made the decision to retry the request on 429 requests. Hence, the breakpoint will not be hit as the evaluation is not made.

    To log the requests, I would suggest looking the docs below to add a logging handler and then add conditionals based on the response status.

    https://github.com/microsoftgraph/msgraph-sdk-dotnet-core/blob/dev/docs/logging-requests.md


0 additional answers

Sort by: Most helpful

Your answer

Answers can be marked as Accepted Answers by the question author, which helps users to know the answer solved the author's problem.