From 2a79e0236252d6efb103513c74d548a045a3d8e5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ana=C3=AFs=20Betts?= Date: Mon, 17 Apr 2023 16:32:00 +0200 Subject: [PATCH] Revert "Feature: allow developers to inject the MethodInfo as a Property (#1367)" This reverts commit b06ef7c37dab6b003805424d010137ebbef65661. --- README.md | 50 +---------------- Refit.Tests/MultipartTests.cs | 4 +- Refit.Tests/RequestBuilder.cs | 81 ++++----------------------- Refit/HttpRequestMessageProperties.cs | 19 +------ Refit/RefitSettings.cs | 27 +-------- Refit/RequestBuilderImplementation.cs | 17 ++---- 6 files changed, 21 insertions(+), 177 deletions(-) diff --git a/README.md b/README.md index c43bf9867..9befb73b1 100644 --- a/README.md +++ b/README.md @@ -56,7 +56,7 @@ services * [Removing headers](#removing-headers) * [Passing state into DelegatingHandlers](#passing-state-into-delegatinghandlers) * [Support for Polly and Polly.Context](#support-for-polly-and-pollycontext) - * [Target Interface type and method info](#target-interface-type-and-method-info) + * [Target Interface type](#target-interface-type) * [MethodInfo of the method on the Refit client interface that was invoked](#methodinfo-of-the-method-on-the-refit-client-interface-that-was-invoked) * [Multipart uploads](#multipart-uploads) * [Retrieving the response](#retrieving-the-response) @@ -882,54 +882,6 @@ class RequestPropertyHandler : DelegatingHandler Note: in .NET 5 `HttpRequestMessage.Properties` has been marked `Obsolete` and Refit will instead populate the value into the new `HttpRequestMessage.Options`. Refit provides `HttpRequestMessageOptions.InterfaceTypeKey` and `HttpRequestMessageOptions.RestMethodInfoKey` to respectively access the interface type and REST method info from the options. -#### MethodInfo of the method on the Refit client interface that was invoked - -There may be times when you want access to the `MethodInfo` of the method on the Refit client interface that was invoked. An example is where you -want to decorate the method with a custom attribute in order to control some aspect of behavior in a `DelegatingHandler`: - -```csharp -public interface ISomeAPI -{ - [SomeCustomAttribute("SomeValue")] - [Get("/{id}")] - Task> GetById(int id); -} -``` -To make the `MethodInfo` available you need to opt-in via the `RefitSettings` like so: - -```csharp -services.AddRefitClient(provider => new RefitSettings - { - InjectMethodInfoAsProperty = true - }) - .ConfigureHttpClient(c => c.BaseAddress = new Uri("https://api.example.com")); -``` - -You can access the `MethodInfo` for use in a handler and then get the custom attributes: - -```csharp -class RequestPropertyHandler : DelegatingHandler -{ - public RequestPropertyHandler(HttpMessageHandler innerHandler = null) : base(innerHandler ?? new HttpClientHandler()) {} - - protected override async Task SendAsync(HttpRequestMessage request, CancellationToken cancellationToken) - { - // Get the MethodInfo - MethodInfo methodInfo; - request.Options.TryGetValue(HttpRequestMessageOptions.MethodInfoKey, out methodInfo); - - //get the custom attributes - var customAttributes = methodInfo.CustomAttributes; - - //insert your logic here - - return await base.SendAsync(request, cancellationToken).ConfigureAwait(false); - } -} -``` - -Note: for .NET Core 3.1 and lower this will be available via `HttpRequestMessage.Properties[HttpRequestMessageOptions.MethodInfo]`. - ### Multipart uploads Methods decorated with `Multipart` attribute will be submitted with multipart content type. diff --git a/Refit.Tests/MultipartTests.cs b/Refit.Tests/MultipartTests.cs index 9c155e10a..95c87a36d 100644 --- a/Refit.Tests/MultipartTests.cs +++ b/Refit.Tests/MultipartTests.cs @@ -308,12 +308,12 @@ public async Task MultipartUploadShouldWorkWithHeaderAndRequestProperty() Assert.Equal(someHeader, message.Headers.Authorization.ToString()); #if NET6_0_OR_GREATER - Assert.Equal(2, message.Options.Count()); + Assert.Equal(3, message.Options.Count()); Assert.Equal(someProperty, ((IDictionary)message.Options)["SomeProperty"]); #endif #pragma warning disable CS0618 // Type or member is obsolete - Assert.Equal(2, message.Properties.Count); + Assert.Equal(3, message.Properties.Count); Assert.Equal(someProperty, message.Properties["SomeProperty"]); #pragma warning restore CS0618 // Type or member is obsolete }, diff --git a/Refit.Tests/RequestBuilder.cs b/Refit.Tests/RequestBuilder.cs index a61680d2f..f4c743b46 100644 --- a/Refit.Tests/RequestBuilder.cs +++ b/Refit.Tests/RequestBuilder.cs @@ -288,7 +288,6 @@ public class ComplexQueryObject public class RestMethodInfoTests { - [Fact] public void TooManyComplexTypesThrows() { @@ -514,7 +513,7 @@ public void ParameterMappingSmokeTest() Assert.Empty(fixture.QueryParameterMap); Assert.Null(fixture.BodyParameterInfo); } - + [Fact] public void ParameterMappingWithTheSameIdInAFewPlaces() { @@ -2175,12 +2174,6 @@ public void InterfaceTypeShouldBeInProperties() var factory = fixture.BuildRequestFactoryForMethod(nameof(IContainAandB.Ping)); var output = factory(Array.Empty()); -#if NET6_0_OR_GREATER - Assert.NotEmpty(output.Options); - output.Options.TryGetValue(HttpRequestMessageOptions.InterfaceTypeKey, out var interfaceType); - Assert.Equal(typeof(IContainAandB), interfaceType); -#endif - #pragma warning disable CS0618 // Type or member is obsolete Assert.NotEmpty(output.Properties); Assert.Equal(typeof(IContainAandB), output.Properties[HttpRequestMessageOptions.InterfaceType]); @@ -2189,75 +2182,23 @@ public void InterfaceTypeShouldBeInProperties() } [Fact] - public void MethodInfoShouldBeInPropertiesIfInjectMethodInfoAsPropertyTrue() - { - var fixture = new RequestBuilderImplementation(new RefitSettings - { - InjectMethodInfoAsProperty = true - }); - var factory = fixture.BuildRequestFactoryForMethod(nameof(IContainAandB.Ping)); - var output = factory(Array.Empty()); - - RestMethodInfo restMethodInfo; -#if NET6_0_OR_GREATER - Assert.NotEmpty(output.Options); - output.Options.TryGetValue(HttpRequestMessageOptions.RestMethodInfoKey, out restMethodInfo); - Assert.NotNull(restMethodInfo); - Assert.Equal(nameof(IContainAandB.Ping), restMethodInfo.Name); - Assert.Equal(typeof(IAmInterfaceA), restMethodInfo.MethodInfo.DeclaringType); -#endif - -#pragma warning disable CS0618 // Type or member is obsolete - Assert.NotEmpty(output.Properties); - restMethodInfo = (RestMethodInfo)(output.Properties[HttpRequestMessageOptions.RestMethodInfo]); - Assert.NotNull(restMethodInfo); - Assert.Equal(nameof(IContainAandB.Ping), restMethodInfo.Name); - Assert.Equal(typeof(IAmInterfaceA), restMethodInfo.MethodInfo.DeclaringType); -#pragma warning restore CS0618 // Type or member is obsolete - } - - [Fact] - public void MethodInfoShouldNotBeInPropertiesIfInjectMethodInfoAsPropertyFalse() + public void RestMethodInfoShouldBeInProperties() { + var someProperty = new object(); var fixture = new RequestBuilderImplementation(); var factory = fixture.BuildRequestFactoryForMethod(nameof(IContainAandB.Ping)); - var output = factory(Array.Empty()); + var output = factory(new object[] { }); - RestMethodInfo restMethodInfo; #if NET6_0_OR_GREATER Assert.NotEmpty(output.Options); - output.Options.TryGetValue(HttpRequestMessageOptions.RestMethodInfoKey, out restMethodInfo); - Assert.Null(restMethodInfo); -#endif - -#pragma warning disable CS0618 // Type or member is obsolete + Assert.True(output.Options.TryGetValue(new HttpRequestOptionsKey(HttpRequestMessageOptions.RestMethodInfo), out var restMethodInfo)); +#else Assert.NotEmpty(output.Properties); - Assert.False(output.Properties.ContainsKey(HttpRequestMessageOptions.RestMethodInfo)); -#pragma warning restore CS0618 // Type or member is obsolete - } - - [Fact] - public void RestMethodInfoShouldBeInProperties() - { - var fixture = new RequestBuilderImplementation(new() { InjectMethodInfoAsProperty = true }); - var factory = fixture.BuildRequestFactoryForMethod(nameof(IContainAandB.Ping)); - var output = factory(Array.Empty()); - RestMethodInfo restMethodInfo; -#if NET6_0_OR_GREATER - Assert.NotEmpty(output.Options); - output.Options.TryGetValue(HttpRequestMessageOptions.RestMethodInfoKey, out restMethodInfo); - Assert.NotNull(restMethodInfo); - Assert.Equal(nameof(IContainAandB.Ping), restMethodInfo.Name); - Assert.Equal(typeof(IAmInterfaceA), restMethodInfo.MethodInfo.DeclaringType); + Assert.True(output.Properties.TryGetValue(HttpRequestMessageOptions.RestMethodInfo, out var restMethodInfoObj)); + Assert.IsType(restMethodInfoObj); + var restMethodInfo = restMethodInfoObj as RestMethodInfo; #endif - -#pragma warning disable CS0618 // Type or member is obsolete - Assert.NotEmpty(output.Properties); - restMethodInfo = (RestMethodInfo)(output.Properties[HttpRequestMessageOptions.RestMethodInfo]); - Assert.NotNull(restMethodInfo); Assert.Equal(nameof(IContainAandB.Ping), restMethodInfo.Name); - Assert.Equal(typeof(IAmInterfaceA), restMethodInfo.MethodInfo.DeclaringType); -#pragma warning restore CS0618 // Type or member is obsolete } [Fact] @@ -2293,12 +2234,12 @@ public void DynamicRequestPropertiesWithDuplicateKeyShouldOverwritePreviousPrope #if NET6_0_OR_GREATER - Assert.Equal(2, output.Options.Count()); + Assert.Equal(3, output.Options.Count()); Assert.Equal(someOtherProperty, ((IDictionary)output.Options)["SomeProperty"]); #endif #pragma warning disable CS0618 // Type or member is obsolete - Assert.Equal(2, output.Properties.Count); + Assert.Equal(3, output.Properties.Count); Assert.Equal(someOtherProperty, output.Properties["SomeProperty"]); #pragma warning restore CS0618 // Type or member is obsolete } diff --git a/Refit/HttpRequestMessageProperties.cs b/Refit/HttpRequestMessageProperties.cs index 0b7f84c75..0610c4be2 100644 --- a/Refit/HttpRequestMessageProperties.cs +++ b/Refit/HttpRequestMessageProperties.cs @@ -1,5 +1,3 @@ -using System.Reflection; - namespace Refit { /// @@ -12,24 +10,9 @@ public static class HttpRequestMessageOptions /// public static string InterfaceType { get; } = "Refit.InterfaceType"; -#if NET6_0_OR_GREATER - /// - /// A typed key to access the of the top-level interface where the method was called from - /// on the . - /// - public static System.Net.Http.HttpRequestOptionsKey InterfaceTypeKey { get; } = new(InterfaceType); -#endif - /// - /// Returns the of the method that was called + /// Returns the of the top-level interface /// public static string RestMethodInfo { get; } = "Refit.RestMethodInfo"; - -#if NET6_0_OR_GREATER - /// - /// A typed key to access the of the method that was called - /// - public static System.Net.Http.HttpRequestOptionsKey RestMethodInfoKey { get; } = new(RestMethodInfo); -#endif } } diff --git a/Refit/RefitSettings.cs b/Refit/RefitSettings.cs index b904b1e48..79372da47 100644 --- a/Refit/RefitSettings.cs +++ b/Refit/RefitSettings.cs @@ -27,35 +27,21 @@ public RefitSettings() ExceptionFactory = new DefaultApiExceptionFactory(this).CreateAsync; } - -#if NET6_0_OR_GREATER - /// - /// Creates a new instance with the specified parameters - /// - /// The instance to use - /// The instance to use (defaults to ) - /// The instance to use (defaults to ) - /// Controls injecting the of the method on the Refit client interface that was invoked into the HttpRequestMessage.Options (defaults to false) -#else /// /// Creates a new instance with the specified parameters /// /// The instance to use /// The instance to use (defaults to ) /// The instance to use (defaults to ) - /// Controls injecting the of the method on the Refit client interface that was invoked into the HttpRequestMessage.Properties (defaults to false) -#endif public RefitSettings( IHttpContentSerializer contentSerializer, IUrlParameterFormatter? urlParameterFormatter = null, - IFormUrlEncodedParameterFormatter? formUrlEncodedParameterFormatter = null, - bool injectMethodInfoAsProperty = false) + IFormUrlEncodedParameterFormatter? formUrlEncodedParameterFormatter = null) { ContentSerializer = contentSerializer ?? throw new ArgumentNullException(nameof(contentSerializer), "The content serializer can't be null"); UrlParameterFormatter = urlParameterFormatter ?? new DefaultUrlParameterFormatter(); FormUrlEncodedParameterFormatter = formUrlEncodedParameterFormatter ?? new DefaultFormUrlEncodedParameterFormatter(); ExceptionFactory = new DefaultApiExceptionFactory(this).CreateAsync; - InjectMethodInfoAsProperty = injectMethodInfoAsProperty; } /// @@ -103,17 +89,6 @@ public RefitSettings( /// Optional Key-Value pairs, which are displayed in the property or . /// public Dictionary HttpRequestMessageOptions { get; set; } - -#if NET6_0_OR_GREATER - /// - /// Controls injecting the of the method on the Refit client interface that was invoked into the HttpRequestMessage.Options (defaults to false) - /// -#else - /// - /// Controls injecting the of the method on the Refit client interface that was invoked into the HttpRequestMessage.Properties (defaults to false) - /// -#endif - public bool InjectMethodInfoAsProperty { get; set; } } /// diff --git a/Refit/RequestBuilderImplementation.cs b/Refit/RequestBuilderImplementation.cs index b71737c8c..c7baf91cb 100644 --- a/Refit/RequestBuilderImplementation.cs +++ b/Refit/RequestBuilderImplementation.cs @@ -746,21 +746,14 @@ Func BuildRequestFactoryForMethod(RestMethodInfo r #endif } - // Always add the top-level type of the interface to the options/properties and include the MethodInfo if the developer has opted-in to that behavior + // Always add the top-level type of the interface to the properties #if NET6_0_OR_GREATER - ret.Options.Set(HttpRequestMessageOptions.InterfaceTypeKey, TargetType); - if (settings.InjectMethodInfoAsProperty) - { - ret.Options.Set(HttpRequestMessageOptions.RestMethodInfoKey, restMethod); - } + ret.Options.Set(new HttpRequestOptionsKey(HttpRequestMessageOptions.InterfaceType), TargetType); + ret.Options.Set(new HttpRequestOptionsKey(HttpRequestMessageOptions.RestMethodInfo), restMethod); #else ret.Properties[HttpRequestMessageOptions.InterfaceType] = TargetType; - if (settings.InjectMethodInfoAsProperty) - { - ret.Properties[HttpRequestMessageOptions.RestMethodInfo] = restMethod; - } - -#endif + ret.Properties[HttpRequestMessageOptions.RestMethodInfo] = restMethod; +#endif // NB: The URI methods in .NET are dumb. Also, we do this // UriBuilder business so that we preserve any hardcoded query