From 5482d0c82265f479250ee02f578bd1407619ccc1 Mon Sep 17 00:00:00 2001 From: Egor Sidorenko Date: Wed, 26 Aug 2026 15:21:15 +0500 Subject: [PATCH 1/2] feat: add CreateDefaultHandlers overload that forwards request options to Kiota handlers GraphClientFactory.CreateDefaultHandlers called KiotaClientFactory.CreateDefaultHandlers() with no arguments, even though Kiota exposes an overload that takes an array of IRequestOption to configure the default handlers (for example a RetryHandlerOption). Because of that, the only way to change retry behaviour was to find the RetryHandler in the returned list, remove it, and add a replacement. This adds a second CreateDefaultHandlers overload that takes an IRequestOption[] and forwards it into KiotaClientFactory.CreateDefaultHandlers, while keeping the existing telemetry handler behaviour. The old overload now just calls the new one with no options, so it keeps working exactly as before and no existing public signature changes. Issue #1004 asked for this and was closed as by design before the Kiota migration happened, when this option did not exist one layer down yet. --- .../Requests/GraphClientFactory.cs | 17 ++++++++++++- .../Requests/GraphClientFactoryTests.cs | 25 +++++++++++++++++++ 2 files changed, 41 insertions(+), 1 deletion(-) diff --git a/src/Microsoft.Graph.Core/Requests/GraphClientFactory.cs b/src/Microsoft.Graph.Core/Requests/GraphClientFactory.cs index c1445ac52..021d6c85a 100644 --- a/src/Microsoft.Graph.Core/Requests/GraphClientFactory.cs +++ b/src/Microsoft.Graph.Core/Requests/GraphClientFactory.cs @@ -13,6 +13,7 @@ namespace Microsoft.Graph using System.Threading; using Azure.Core; using Microsoft.Graph.Authentication; + using Microsoft.Kiota.Abstractions; using Microsoft.Kiota.Abstractions.Authentication; using Microsoft.Kiota.Http.HttpClientLibrary; using Microsoft.Kiota.Http.HttpClientLibrary.Middleware; @@ -170,7 +171,21 @@ public static HttpClient Create( /// public static IList CreateDefaultHandlers(GraphClientOptions graphClientOptions = null) { - var handlers = KiotaClientFactory.CreateDefaultHandlers(); + return CreateDefaultHandlers(graphClientOptions, null); + } + + /// + /// Create a default set of middleware for calling Microsoft Graph, letting callers configure the + /// underlying Kiota handlers (for example a custom ) + /// without having to remove and reinsert a handler afterwards. + /// + /// The to use with the client + /// The request options to configure the default Kiota handlers with. See + /// for the handlers that read these options. + /// + public static IList CreateDefaultHandlers(GraphClientOptions graphClientOptions, IRequestOption[] optionsForHandlers) + { + var handlers = KiotaClientFactory.CreateDefaultHandlers(optionsForHandlers); handlers.Add(new GraphTelemetryHandler(graphClientOptions));// add the telemetry handler last. return handlers; diff --git a/tests/Microsoft.Graph.DotnetCore.Core.Test/Requests/GraphClientFactoryTests.cs b/tests/Microsoft.Graph.DotnetCore.Core.Test/Requests/GraphClientFactoryTests.cs index d4d9c7f12..254a0cfc1 100644 --- a/tests/Microsoft.Graph.DotnetCore.Core.Test/Requests/GraphClientFactoryTests.cs +++ b/tests/Microsoft.Graph.DotnetCore.Core.Test/Requests/GraphClientFactoryTests.cs @@ -10,9 +10,11 @@ namespace Microsoft.Graph.DotnetCore.Core.Test.Requests using System.Net; using System.Net.Http; using System.Net.Http.Headers; + using System.Reflection; using System.Threading; using System.Threading.Tasks; using Azure.Core; + using Microsoft.Kiota.Abstractions; using Microsoft.Kiota.Abstractions.Authentication; using Microsoft.Kiota.Http.HttpClientLibrary.Middleware; using Microsoft.Kiota.Http.HttpClientLibrary.Middleware.Options; @@ -148,6 +150,29 @@ public void CreatePipeline_Should_Throw_Exception_With_Duplicate_Handlers() Assert.Contains($"{typeof(GraphTelemetryHandler)} has a duplicate handler.", exception.Message); } + [Fact] + public void CreateDefaultHandlers_Should_Forward_RetryHandlerOption_To_RetryHandler() + { + var retryOption = new RetryHandlerOption + { + MaxRetry = 7, + Delay = 3 + }; + + var defaultHandlers = GraphClientFactory.CreateDefaultHandlers(new GraphClientOptions(), new IRequestOption[] { retryOption }); + + var retryHandler = defaultHandlers.OfType().Single(); + + // RetryHandler.RetryOption is internal to the Kiota library, so we reach it with reflection + // to prove the option we passed in is the one the handler ended up with. + var retryOptionProperty = typeof(RetryHandler).GetProperty("RetryOption", BindingFlags.NonPublic | BindingFlags.Instance); + var actualRetryOption = (RetryHandlerOption)retryOptionProperty.GetValue(retryHandler); + + Assert.Same(retryOption, actualRetryOption); + Assert.Equal(7, actualRetryOption.MaxRetry); + Assert.Equal(3, actualRetryOption.Delay); + } + [Fact] public void CreateClient_CustomHttpHandlingBehaviors() { From edbc0d5a82c9d36eac67018e0f5740f9b03782ca Mon Sep 17 00:00:00 2001 From: Egor Sidorenko Date: Wed, 26 Aug 2026 15:28:47 +0500 Subject: [PATCH 2/2] Assert the reflected property was found before reading it --- .../Requests/GraphClientFactoryTests.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/Microsoft.Graph.DotnetCore.Core.Test/Requests/GraphClientFactoryTests.cs b/tests/Microsoft.Graph.DotnetCore.Core.Test/Requests/GraphClientFactoryTests.cs index 254a0cfc1..7fdbf6811 100644 --- a/tests/Microsoft.Graph.DotnetCore.Core.Test/Requests/GraphClientFactoryTests.cs +++ b/tests/Microsoft.Graph.DotnetCore.Core.Test/Requests/GraphClientFactoryTests.cs @@ -166,6 +166,7 @@ public void CreateDefaultHandlers_Should_Forward_RetryHandlerOption_To_RetryHand // RetryHandler.RetryOption is internal to the Kiota library, so we reach it with reflection // to prove the option we passed in is the one the handler ended up with. var retryOptionProperty = typeof(RetryHandler).GetProperty("RetryOption", BindingFlags.NonPublic | BindingFlags.Instance); + Assert.NotNull(retryOptionProperty); var actualRetryOption = (RetryHandlerOption)retryOptionProperty.GetValue(retryHandler); Assert.Same(retryOption, actualRetryOption);