From ea2b67dd8f9ba3bec641ca16ee25a9a0f7eb124a Mon Sep 17 00:00:00 2001 From: Vincent Biret Date: Tue, 27 Aug 2024 13:29:45 -0400 Subject: [PATCH 1/4] chore: adds task analyzers --- .../Microsoft.Kiota.Abstractions.csproj | 4 ++++ .../Microsoft.Kiota.Authentication.Azure.csproj | 4 ++++ src/bundle/Microsoft.Kiota.Bundle.csproj | 7 +++++++ .../Microsoft.Kiota.Http.HttpClientLibrary.csproj | 13 +++++++++---- .../form/Microsoft.Kiota.Serialization.Form.csproj | 7 +++++++ .../json/Microsoft.Kiota.Serialization.Json.csproj | 10 ++++++++-- .../Microsoft.Kiota.Serialization.Multipart.csproj | 7 +++++++ .../text/Microsoft.Kiota.Serialization.Text.csproj | 7 +++++++ 8 files changed, 53 insertions(+), 6 deletions(-) diff --git a/src/abstractions/Microsoft.Kiota.Abstractions.csproj b/src/abstractions/Microsoft.Kiota.Abstractions.csproj index 5b9ff9cf..b97279d3 100644 --- a/src/abstractions/Microsoft.Kiota.Abstractions.csproj +++ b/src/abstractions/Microsoft.Kiota.Abstractions.csproj @@ -10,6 +10,10 @@ + + runtime; build; native; contentfiles; analyzers; buildtransitive + all + diff --git a/src/authentication/azure/Microsoft.Kiota.Authentication.Azure.csproj b/src/authentication/azure/Microsoft.Kiota.Authentication.Azure.csproj index 5c46956c..dff36a6d 100644 --- a/src/authentication/azure/Microsoft.Kiota.Authentication.Azure.csproj +++ b/src/authentication/azure/Microsoft.Kiota.Authentication.Azure.csproj @@ -11,6 +11,10 @@ + + runtime; build; native; contentfiles; analyzers; buildtransitive + all + diff --git a/src/bundle/Microsoft.Kiota.Bundle.csproj b/src/bundle/Microsoft.Kiota.Bundle.csproj index b5bd3e1c..7d0325df 100644 --- a/src/bundle/Microsoft.Kiota.Bundle.csproj +++ b/src/bundle/Microsoft.Kiota.Bundle.csproj @@ -18,4 +18,11 @@ + + + runtime; build; native; contentfiles; analyzers; buildtransitive + all + + + diff --git a/src/http/httpClient/Microsoft.Kiota.Http.HttpClientLibrary.csproj b/src/http/httpClient/Microsoft.Kiota.Http.HttpClientLibrary.csproj index 9deabe22..acc2db49 100644 --- a/src/http/httpClient/Microsoft.Kiota.Http.HttpClientLibrary.csproj +++ b/src/http/httpClient/Microsoft.Kiota.Http.HttpClientLibrary.csproj @@ -10,8 +10,7 @@ - + - + @@ -23,4 +22,11 @@ + + + + runtime; build; native; contentfiles; analyzers; buildtransitive + all + + \ No newline at end of file diff --git a/src/serialization/multipart/Microsoft.Kiota.Serialization.Multipart.csproj b/src/serialization/multipart/Microsoft.Kiota.Serialization.Multipart.csproj index ebaf50ca..cafe6d74 100644 --- a/src/serialization/multipart/Microsoft.Kiota.Serialization.Multipart.csproj +++ b/src/serialization/multipart/Microsoft.Kiota.Serialization.Multipart.csproj @@ -12,4 +12,11 @@ + + + + runtime; build; native; contentfiles; analyzers; buildtransitive + all + + diff --git a/src/serialization/text/Microsoft.Kiota.Serialization.Text.csproj b/src/serialization/text/Microsoft.Kiota.Serialization.Text.csproj index 1dd40038..4d18c173 100644 --- a/src/serialization/text/Microsoft.Kiota.Serialization.Text.csproj +++ b/src/serialization/text/Microsoft.Kiota.Serialization.Text.csproj @@ -12,4 +12,11 @@ + + + + runtime; build; native; contentfiles; analyzers; buildtransitive + all + + From ebf15e414ec3a9254269fcfbd1e92f3fbac17b7e Mon Sep 17 00:00:00 2001 From: Vincent Biret Date: Tue, 27 Aug 2024 13:30:00 -0400 Subject: [PATCH 2/4] chore: linting of native wrapper --- src/abstractions/NativeResponseWrapper.cs | 41 +++++++++++++++++++++-- 1 file changed, 39 insertions(+), 2 deletions(-) diff --git a/src/abstractions/NativeResponseWrapper.cs b/src/abstractions/NativeResponseWrapper.cs index dd16f455..74e0c579 100644 --- a/src/abstractions/NativeResponseWrapper.cs +++ b/src/abstractions/NativeResponseWrapper.cs @@ -4,6 +4,7 @@ using System; using System.Collections.Generic; +using System.ComponentModel; using System.Threading.Tasks; namespace Microsoft.Kiota.Abstractions @@ -22,7 +23,43 @@ public class NativeResponseWrapper /// The request headers of the request /// Request options /// - public static async Task CallAndGetNativeType( + [Obsolete("Use CallAndGetNativeTypeAsync instead")] + [EditorBrowsable(EditorBrowsableState.Never)] +#pragma warning disable VSTHRD200 // Use "Async" suffix for async methods + public static Task CallAndGetNativeType( + Func?, Action>?, IEnumerable?, IResponseHandler, Task> originalCall, + Action? q = default, + Action>? h = default, + IEnumerable? o = default) where NativeResponseType : class => CallAndGetNativeTypeAsync(originalCall, q, h, o); + + /// + /// Makes a request with the and instances to get a response with + /// a instance and expect an instance of + /// + /// The original request to make + /// The request body of the request + /// The query parameters of the request + /// The request headers of the request + /// Request options + [Obsolete("Use CallAndGetNativeTypeAsync instead")] + [EditorBrowsable(EditorBrowsableState.Never)] + public static Task CallAndGetNativeType( + Func?, Action>?, IEnumerable?, IResponseHandler, Task> originalCall, + RequestBodyType requestBody, + Action? q = default, + Action>? h = default, + IEnumerable? o = default) where NativeResponseType : class => CallAndGetNativeTypeAsync(originalCall, requestBody, q, h, o); +#pragma warning restore VSTHRD200 // Use "Async" suffix for async methods + /// + /// Makes a request with the instance to get a response with + /// a instance and expect an instance of + /// + /// The original request to make + /// The query parameters of the request + /// The request headers of the request + /// Request options + /// + public static async Task CallAndGetNativeTypeAsync( Func?, Action>?, IEnumerable?, IResponseHandler, Task> originalCall, Action? q = default, Action>? h = default, @@ -42,7 +79,7 @@ public class NativeResponseWrapper /// The query parameters of the request /// The request headers of the request /// Request options - public static async Task CallAndGetNativeType( + public static async Task CallAndGetNativeTypeAsync( Func?, Action>?, IEnumerable?, IResponseHandler, Task> originalCall, RequestBodyType requestBody, Action? q = default, From 1b2094de99f4ecc5e0929bcd1ae6cc3c9af416e5 Mon Sep 17 00:00:00 2001 From: Vincent Biret Date: Tue, 27 Aug 2024 13:53:11 -0400 Subject: [PATCH 3/4] fix: dispose async when possible Signed-off-by: Vincent Biret --- .../httpClient/HttpClientRequestAdapter.cs | 79 +++++++++++++------ .../httpClient/Middleware/RetryHandler.cs | 4 +- .../Middleware/RetryHandlerTests.cs | 2 +- 3 files changed, 57 insertions(+), 28 deletions(-) diff --git a/src/http/httpClient/HttpClientRequestAdapter.cs b/src/http/httpClient/HttpClientRequestAdapter.cs index 2932ba29..4ec4906e 100644 --- a/src/http/httpClient/HttpClientRequestAdapter.cs +++ b/src/http/httpClient/HttpClientRequestAdapter.cs @@ -91,16 +91,21 @@ public string? BaseUrl public async Task?> SendCollectionAsync(RequestInformation requestInfo, ParsableFactory factory, Dictionary>? errorMapping = default, CancellationToken cancellationToken = default) where ModelType : IParsable { using var span = startTracingSpan(requestInfo, nameof(SendCollectionAsync)); - var response = await GetHttpResponseMessage(requestInfo, cancellationToken, span).ConfigureAwait(false); + var response = await GetHttpResponseMessageAsync(requestInfo, cancellationToken, span).ConfigureAwait(false); +#if NETSTANDARD2_1_OR_GREATER || NETCOREAPP3_0_OR_GREATER + if (requestInfo.Content is not null) + await requestInfo.Content.DisposeAsync().ConfigureAwait(false); +#else requestInfo.Content?.Dispose(); +#endif var responseHandler = GetResponseHandler(requestInfo); if(responseHandler == null) { try { - await ThrowIfFailedResponse(response, errorMapping, span, cancellationToken).ConfigureAwait(false); + await ThrowIfFailedResponseAsync(response, errorMapping, span, cancellationToken).ConfigureAwait(false); if(shouldReturnNull(response)) return default; - var rootNode = await GetRootParseNode(response, cancellationToken).ConfigureAwait(false); + var rootNode = await GetRootParseNodeAsync(response, cancellationToken).ConfigureAwait(false); using var spanForDeserialization = activitySource?.StartActivity(nameof(IParseNode.GetCollectionOfObjectValues)); var result = rootNode?.GetCollectionOfObjectValues(factory); SetResponseType(result, span); @@ -131,16 +136,21 @@ public string? BaseUrl #endif { using var span = startTracingSpan(requestInfo, nameof(SendPrimitiveCollectionAsync)); - var response = await GetHttpResponseMessage(requestInfo, cancellationToken, span).ConfigureAwait(false); + var response = await GetHttpResponseMessageAsync(requestInfo, cancellationToken, span).ConfigureAwait(false); +#if NETSTANDARD2_1_OR_GREATER || NETCOREAPP3_0_OR_GREATER + if (requestInfo.Content is not null) + await requestInfo.Content.DisposeAsync().ConfigureAwait(false); +#else requestInfo.Content?.Dispose(); +#endif var responseHandler = GetResponseHandler(requestInfo); if(responseHandler == null) { try { - await ThrowIfFailedResponse(response, errorMapping, span, cancellationToken).ConfigureAwait(false); + await ThrowIfFailedResponseAsync(response, errorMapping, span, cancellationToken).ConfigureAwait(false); if(shouldReturnNull(response)) return default; - var rootNode = await GetRootParseNode(response, cancellationToken).ConfigureAwait(false); + var rootNode = await GetRootParseNodeAsync(response, cancellationToken).ConfigureAwait(false); using var spanForDeserialization = activitySource?.StartActivity(nameof(IParseNode.GetCollectionOfPrimitiveValues)); var result = rootNode?.GetCollectionOfPrimitiveValues(); SetResponseType(result, span); @@ -172,16 +182,21 @@ public string? BaseUrl public async Task SendAsync(RequestInformation requestInfo, ParsableFactory factory, Dictionary>? errorMapping = default, CancellationToken cancellationToken = default) where ModelType : IParsable { using var span = startTracingSpan(requestInfo, nameof(SendAsync)); - var response = await GetHttpResponseMessage(requestInfo, cancellationToken, span).ConfigureAwait(false); + var response = await GetHttpResponseMessageAsync(requestInfo, cancellationToken, span).ConfigureAwait(false); +#if NETSTANDARD2_1_OR_GREATER || NETCOREAPP3_0_OR_GREATER + if (requestInfo.Content is not null) + await requestInfo.Content.DisposeAsync().ConfigureAwait(false); +#else requestInfo.Content?.Dispose(); +#endif var responseHandler = GetResponseHandler(requestInfo); if(responseHandler == null) { try { - await ThrowIfFailedResponse(response, errorMapping, span, cancellationToken).ConfigureAwait(false); + await ThrowIfFailedResponseAsync(response, errorMapping, span, cancellationToken).ConfigureAwait(false); if(shouldReturnNull(response)) return default; - var rootNode = await GetRootParseNode(response, cancellationToken).ConfigureAwait(false); + var rootNode = await GetRootParseNodeAsync(response, cancellationToken).ConfigureAwait(false); if(rootNode == null) return default; using var spanForDeserialization = activitySource?.StartActivity(nameof(IParseNode.GetObjectValue)); var result = rootNode.GetObjectValue(factory); @@ -218,14 +233,19 @@ public string? BaseUrl using var span = startTracingSpan(requestInfo, nameof(SendPrimitiveAsync)); var modelType = typeof(ModelType); var isStreamResponse = modelType == typeof(Stream); - var response = await GetHttpResponseMessage(requestInfo, cancellationToken, span, isStreamResponse: isStreamResponse).ConfigureAwait(false); + var response = await GetHttpResponseMessageAsync(requestInfo, cancellationToken, span, isStreamResponse: isStreamResponse).ConfigureAwait(false); +#if NETSTANDARD2_1_OR_GREATER || NETCOREAPP3_0_OR_GREATER + if (requestInfo.Content is not null) + await requestInfo.Content.DisposeAsync().ConfigureAwait(false); +#else requestInfo.Content?.Dispose(); +#endif var responseHandler = GetResponseHandler(requestInfo); if(responseHandler == null) { try { - await ThrowIfFailedResponse(response, errorMapping, span, cancellationToken).ConfigureAwait(false); + await ThrowIfFailedResponseAsync(response, errorMapping, span, cancellationToken).ConfigureAwait(false); if(shouldReturnNull(response)) return default; if(isStreamResponse) { @@ -236,7 +256,11 @@ public string? BaseUrl #endif if(result.CanSeek && result.Length == 0) { +#if NETSTANDARD2_1_OR_GREATER || NETCOREAPP3_0_OR_GREATER + await result.DisposeAsync().ConfigureAwait(false); +#else result.Dispose(); +#endif return default; } SetResponseType(result, span); @@ -244,7 +268,7 @@ public string? BaseUrl } else { - var rootNode = await GetRootParseNode(response, cancellationToken).ConfigureAwait(false); + var rootNode = await GetRootParseNodeAsync(response, cancellationToken).ConfigureAwait(false); object? result; using var spanForDeserialization = activitySource?.StartActivity($"Get{modelType.Name.TrimEnd('?')}Value"); if(rootNode == null) @@ -336,14 +360,19 @@ public string? BaseUrl public async Task SendNoContentAsync(RequestInformation requestInfo, Dictionary>? errorMapping = default, CancellationToken cancellationToken = default) { using var span = startTracingSpan(requestInfo, nameof(SendNoContentAsync)); - var response = await GetHttpResponseMessage(requestInfo, cancellationToken, span).ConfigureAwait(false); + var response = await GetHttpResponseMessageAsync(requestInfo, cancellationToken, span).ConfigureAwait(false); +#if NETSTANDARD2_1_OR_GREATER || NETCOREAPP3_0_OR_GREATER + if (requestInfo.Content is not null) + await requestInfo.Content.DisposeAsync().ConfigureAwait(false); +#else requestInfo.Content?.Dispose(); +#endif var responseHandler = GetResponseHandler(requestInfo); if(responseHandler == null) { try { - await ThrowIfFailedResponse(response, errorMapping, span, cancellationToken).ConfigureAwait(false); + await ThrowIfFailedResponseAsync(response, errorMapping, span, cancellationToken).ConfigureAwait(false); } finally { @@ -392,9 +421,9 @@ private static bool shouldReturnNull(HttpResponseMessage response) /// The attribute name used to indicate whether the error response contained a body. /// public const string ErrorBodyFoundAttributeName = "com.microsoft.kiota.error.body_found"; - private async Task ThrowIfFailedResponse(HttpResponseMessage response, Dictionary>? errorMapping, Activity? activityForAttributes, CancellationToken cancellationToken) + private async Task ThrowIfFailedResponseAsync(HttpResponseMessage response, Dictionary>? errorMapping, Activity? activityForAttributes, CancellationToken cancellationToken) { - using var span = activitySource?.StartActivity(nameof(ThrowIfFailedResponse)); + using var span = activitySource?.StartActivity(nameof(ThrowIfFailedResponseAsync)); if(response.IsSuccessStatusCode) return; activityForAttributes?.SetStatus(ActivityStatusCode.Error, "received_error_response"); @@ -420,7 +449,7 @@ private async Task ThrowIfFailedResponse(HttpResponseMessage response, Dictionar } activityForAttributes?.SetTag(ErrorMappingFoundAttributeName, true); - var rootNode = await GetRootParseNode(response, cancellationToken).ConfigureAwait(false); + var rootNode = await GetRootParseNodeAsync(response, cancellationToken).ConfigureAwait(false); activityForAttributes?.SetTag(ErrorBodyFoundAttributeName, rootNode != null); var spanForDeserialization = activitySource?.StartActivity(nameof(IParseNode.GetObjectValue)); var result = rootNode?.GetObjectValue(errorFactory); @@ -444,9 +473,9 @@ private async Task ThrowIfFailedResponse(HttpResponseMessage response, Dictionar { return requestInfo.GetRequestOption()?.ResponseHandler; } - private async Task GetRootParseNode(HttpResponseMessage response, CancellationToken cancellationToken) + private async Task GetRootParseNodeAsync(HttpResponseMessage response, CancellationToken cancellationToken) { - using var span = activitySource?.StartActivity(nameof(GetRootParseNode)); + using var span = activitySource?.StartActivity(nameof(GetRootParseNodeAsync)); var responseContentType = response.Content?.Headers?.ContentType?.MediaType?.ToLowerInvariant(); if(string.IsNullOrEmpty(responseContentType)) return null; @@ -466,9 +495,9 @@ private async Task ThrowIfFailedResponse(HttpResponseMessage response, Dictionar private const string ClaimsKey = "claims"; private const string BearerAuthenticationScheme = "Bearer"; private static Func filterAuthHeader = static x => x.Scheme.Equals(BearerAuthenticationScheme, StringComparison.OrdinalIgnoreCase); - private async Task GetHttpResponseMessage(RequestInformation requestInfo, CancellationToken cancellationToken, Activity? activityForAttributes, string? claims = default, bool isStreamResponse = false) + private async Task GetHttpResponseMessageAsync(RequestInformation requestInfo, CancellationToken cancellationToken, Activity? activityForAttributes, string? claims = default, bool isStreamResponse = false) { - using var span = activitySource?.StartActivity(nameof(GetHttpResponseMessage)); + using var span = activitySource?.StartActivity(nameof(GetHttpResponseMessageAsync)); if(requestInfo == null) throw new ArgumentNullException(nameof(requestInfo)); @@ -504,7 +533,7 @@ private async Task GetHttpResponseMessage(RequestInformatio activityForAttributes?.SetTag("http.status_code", (int)response.StatusCode); activityForAttributes?.SetTag("http.flavor", $"{response.Version.Major}.{response.Version.Minor}"); - return await RetryCAEResponseIfRequired(response, requestInfo, cancellationToken, claims, activityForAttributes).ConfigureAwait(false); + return await RetryCAEResponseIfRequiredAsync(response, requestInfo, cancellationToken, claims, activityForAttributes).ConfigureAwait(false); } private static readonly Regex caeValueRegex = new("\"([^\"]*)\"", RegexOptions.Compiled, TimeSpan.FromMilliseconds(100)); @@ -515,9 +544,9 @@ private async Task GetHttpResponseMessage(RequestInformatio public const string AuthenticateChallengedEventKey = "com.microsoft.kiota.authenticate_challenge_received"; private static readonly char[] ComaSplitSeparator = [',']; - private async Task RetryCAEResponseIfRequired(HttpResponseMessage response, RequestInformation requestInfo, CancellationToken cancellationToken, string? claims, Activity? activityForAttributes) + private async Task RetryCAEResponseIfRequiredAsync(HttpResponseMessage response, RequestInformation requestInfo, CancellationToken cancellationToken, string? claims, Activity? activityForAttributes) { - using var span = activitySource?.StartActivity(nameof(RetryCAEResponseIfRequired)); + using var span = activitySource?.StartActivity(nameof(RetryCAEResponseIfRequiredAsync)); if(response.StatusCode == HttpStatusCode.Unauthorized && string.IsNullOrEmpty(claims) && // avoid infinite loop, we only retry once (requestInfo.Content?.CanSeek ?? true)) @@ -559,7 +588,7 @@ private async Task RetryCAEResponseIfRequired(HttpResponseM activityForAttributes?.SetTag("http.retry_count", 1); requestInfo.Content?.Seek(0, SeekOrigin.Begin); await DrainAsync(response, cancellationToken).ConfigureAwait(false); - return await GetHttpResponseMessage(requestInfo, cancellationToken, activityForAttributes, responseClaims).ConfigureAwait(false); + return await GetHttpResponseMessageAsync(requestInfo, cancellationToken, activityForAttributes, responseClaims).ConfigureAwait(false); } } } diff --git a/src/http/httpClient/Middleware/RetryHandler.cs b/src/http/httpClient/Middleware/RetryHandler.cs index 47879bc9..4c1d1dac 100644 --- a/src/http/httpClient/Middleware/RetryHandler.cs +++ b/src/http/httpClient/Middleware/RetryHandler.cs @@ -109,7 +109,7 @@ private async Task SendRetryAsync(HttpResponseMessage respo retryActivity?.SetTag("http.status_code", response.StatusCode); // Call Delay method to get delay time from response's Retry-After header or by exponential backoff - Task delay = RetryHandler.Delay(response, retryCount, retryOption.Delay, out double delayInSeconds, cancellationToken); + Task delay = RetryHandler.DelayAsync(response, retryCount, retryOption.Delay, out double delayInSeconds, cancellationToken); // If client specified a retries time limit, let's honor it if(retryOption.RetriesTimeLimit > TimeSpan.Zero) @@ -176,7 +176,7 @@ private static void AddOrUpdateRetryAttempt(HttpRequestMessage request, int retr /// /// The cancellationToken for the Http request /// The for delay operation. - internal static Task Delay(HttpResponseMessage response, int retryCount, int delay, out double delayInSeconds, CancellationToken cancellationToken) + internal static Task DelayAsync(HttpResponseMessage response, int retryCount, int delay, out double delayInSeconds, CancellationToken cancellationToken) { delayInSeconds = delay; if(response.Headers.TryGetValues(RetryAfter, out IEnumerable? values)) diff --git a/tests/http/httpClient/Middleware/RetryHandlerTests.cs b/tests/http/httpClient/Middleware/RetryHandlerTests.cs index 58631349..fd233520 100644 --- a/tests/http/httpClient/Middleware/RetryHandlerTests.cs +++ b/tests/http/httpClient/Middleware/RetryHandlerTests.cs @@ -431,7 +431,7 @@ private async Task DelayTestWithMessage(HttpResponseMessage response, int count, Message = message; await Task.Run(async () => { - await RetryHandler.Delay(response, count, delay, out _, new CancellationToken()); + await RetryHandler.DelayAsync(response, count, delay, out _, new CancellationToken()); Message += " Work " + count; }); } From c7df8014595a01a22a9bab615021a975d6e1b59c Mon Sep 17 00:00:00 2001 From: Vincent Biret Date: Tue, 27 Aug 2024 14:07:34 -0400 Subject: [PATCH 4/4] fix: adds missing cancellation token parameter Signed-off-by: Vincent Biret --- src/abstractions/NativeResponseWrapper.cs | 21 +++++++++++++-------- 1 file changed, 13 insertions(+), 8 deletions(-) diff --git a/src/abstractions/NativeResponseWrapper.cs b/src/abstractions/NativeResponseWrapper.cs index 74e0c579..a090e590 100644 --- a/src/abstractions/NativeResponseWrapper.cs +++ b/src/abstractions/NativeResponseWrapper.cs @@ -5,6 +5,7 @@ using System; using System.Collections.Generic; using System.ComponentModel; +using System.Threading; using System.Threading.Tasks; namespace Microsoft.Kiota.Abstractions @@ -30,7 +31,7 @@ public class NativeResponseWrapper Func?, Action>?, IEnumerable?, IResponseHandler, Task> originalCall, Action? q = default, Action>? h = default, - IEnumerable? o = default) where NativeResponseType : class => CallAndGetNativeTypeAsync(originalCall, q, h, o); + IEnumerable? o = default) where NativeResponseType : class => CallAndGetNativeTypeAsync((_q, _h, _o, _r, _c) => originalCall(_q, _h, _o, _r), q, h, o); /// /// Makes a request with the and instances to get a response with @@ -48,7 +49,7 @@ public class NativeResponseWrapper RequestBodyType requestBody, Action? q = default, Action>? h = default, - IEnumerable? o = default) where NativeResponseType : class => CallAndGetNativeTypeAsync(originalCall, requestBody, q, h, o); + IEnumerable? o = default) where NativeResponseType : class => CallAndGetNativeTypeAsync((_b, _q, _h, _o, _r, _c) => originalCall(_b, _q, _h, _o, _r), requestBody, q, h, o); #pragma warning restore VSTHRD200 // Use "Async" suffix for async methods /// /// Makes a request with the instance to get a response with @@ -58,15 +59,17 @@ public class NativeResponseWrapper /// The query parameters of the request /// The request headers of the request /// Request options + /// The cancellation token /// public static async Task CallAndGetNativeTypeAsync( - Func?, Action>?, IEnumerable?, IResponseHandler, Task> originalCall, + Func?, Action>?, IEnumerable?, IResponseHandler, CancellationToken, Task> originalCall, Action? q = default, Action>? h = default, - IEnumerable? o = default) where NativeResponseType : class + IEnumerable? o = default, + CancellationToken cancellationToken = default) where NativeResponseType : class { var responseHandler = new NativeResponseHandler(); - await originalCall.Invoke(q, h, o, responseHandler); + await originalCall.Invoke(q, h, o, responseHandler, cancellationToken); return responseHandler.Value as NativeResponseType; } @@ -79,15 +82,17 @@ public class NativeResponseWrapper /// The query parameters of the request /// The request headers of the request /// Request options + /// The cancellation token public static async Task CallAndGetNativeTypeAsync( - Func?, Action>?, IEnumerable?, IResponseHandler, Task> originalCall, + Func?, Action>?, IEnumerable?, IResponseHandler, CancellationToken, Task> originalCall, RequestBodyType requestBody, Action? q = default, Action>? h = default, - IEnumerable? o = default) where NativeResponseType : class + IEnumerable? o = default, + CancellationToken cancellationToken = default) where NativeResponseType : class { var responseHandler = new NativeResponseHandler(); - await originalCall.Invoke(requestBody, q, h, o, responseHandler); + await originalCall.Invoke(requestBody, q, h, o, responseHandler, cancellationToken); return responseHandler.Value as NativeResponseType; } }