diff --git a/Refit.Tests/RequestBuilder.cs b/Refit.Tests/RequestBuilder.cs index f0477c5aa..4c06cb9da 100644 --- a/Refit.Tests/RequestBuilder.cs +++ b/Refit.Tests/RequestBuilder.cs @@ -2044,6 +2044,7 @@ Task QueryWithOptionalParameters( int id, [Query] string text = null, [Query] int? optionalId = null, + [Query(TreatAsString = true)] Foo foo = null, [Query(CollectionFormat = CollectionFormat.Multi)] string[] filters = null ); @@ -3541,12 +3542,12 @@ string expectedQuery } [Theory] - [InlineData("/api/123?text=title&optionalId=999&filters=A&filters=B")] + [InlineData("/api/123?text=title&optionalId=999&foo=foo&filters=A&filters=B")] public void TestNullableQueryStringParams(string expectedQuery) { var fixture = new RequestBuilderImplementation(); var factory = fixture.BuildRequestFactoryForMethod("QueryWithOptionalParameters"); - var output = factory(new object[] { 123, "title", 999, new string[] { "A", "B" } }); + var output = factory(new object[] { 123, "title", 999, new Foo(), new string[] { "A", "B" } }); var uri = new Uri(new Uri("http://api"), output.RequestUri); Assert.Equal(expectedQuery, uri.PathAndQuery); @@ -3558,7 +3559,7 @@ public void TestNullableQueryStringParamsWithANull(string expectedQuery) { var fixture = new RequestBuilderImplementation(); var factory = fixture.BuildRequestFactoryForMethod("QueryWithOptionalParameters"); - var output = factory(new object[] { 123, "title", null, new string[] { "A", "B" } }); + var output = factory(new object[] { 123, "title", null, null, new string[] { "A", "B" } }); var uri = new Uri(new Uri("http://api"), output.RequestUri); Assert.Equal(expectedQuery, uri.PathAndQuery); @@ -3944,6 +3945,14 @@ public void ComplexQueryObjectWithDictionaryAndCustomFormatterProducesCorrectQue } } + public record Foo + { + public override string ToString() + { + return "foo"; + } + } + static class RequestBuilderTestExtensions { public static Func BuildRequestFactoryForMethod( diff --git a/Refit/Attributes.cs b/Refit/Attributes.cs index 5d7d95efb..f7d779e12 100644 --- a/Refit/Attributes.cs +++ b/Refit/Attributes.cs @@ -465,6 +465,12 @@ public QueryAttribute(CollectionFormat collectionFormat) CollectionFormat = collectionFormat; } + /// + /// Used to specify that the value should be treated as a string. + /// Set to true if you want to call ToString() on the object before adding it to the query string. + /// + public bool TreatAsString { get; set; } + /// /// Used to customize the name of either the query parameter pair or of the form field when form encoding. /// diff --git a/Refit/RequestBuilderImplementation.cs b/Refit/RequestBuilderImplementation.cs index eec31a9f9..c342a26dc 100644 --- a/Refit/RequestBuilderImplementation.cs +++ b/Refit/RequestBuilderImplementation.cs @@ -946,7 +946,18 @@ void AddQueryParameters(RestMethodInfoInternal restMethod, QueryAttribute? query List> queryParamsToAdd, int i, RestMethodParameterInfo? parameterInfo) { var attr = queryAttribute ?? DefaultQueryAttribute; - if (DoNotConvertToQueryMap(param)) + if (attr is { TreatAsString: true }) + { + queryParamsToAdd.AddRange( + ParseQueryParameter( + param.ToString(), + restMethod.ParameterInfoArray[i], + restMethod.QueryParameterMap[i], + attr + ) + ); + } + else if (DoNotConvertToQueryMap(param)) { queryParamsToAdd.AddRange( ParseQueryParameter(