diff --git a/packages/http-client-csharp/generator/Microsoft.TypeSpec.Generator.ClientModel/src/Providers/RestClientProvider.cs b/packages/http-client-csharp/generator/Microsoft.TypeSpec.Generator.ClientModel/src/Providers/RestClientProvider.cs index 5cee8c429b3..0c442c416bc 100644 --- a/packages/http-client-csharp/generator/Microsoft.TypeSpec.Generator.ClientModel/src/Providers/RestClientProvider.cs +++ b/packages/http-client-csharp/generator/Microsoft.TypeSpec.Generator.ClientModel/src/Providers/RestClientProvider.cs @@ -637,9 +637,9 @@ private static MethodBodyStatement BuildAppendQueryStatement( valueExpression.AsDictionary(paramType), out KeyValuePairExpression item); var convertedItem = paramType.ElementType.IsEnum - ? paramType.ElementType.ToSerial(item) + ? paramType.ElementType.ToSerial(item.Value) : item.Value; - forEachStatement.Add(uri.AppendQuery(item.Key, convertedItem, true).Terminate()); + AddExplodeQueryItem(forEachStatement, uri, item.Key, convertedItem, paramType.ElementType); return forEachStatement; } else @@ -674,11 +674,35 @@ private static MethodBodyStatement BuildAppendQueryStatement( { convertedItem = item; } - forEachStatement.Add(uri.AppendQuery(Literal(inputQueryParameter.SerializedName), convertedItem, true).Terminate()); + AddExplodeQueryItem(forEachStatement, uri, Literal(inputQueryParameter.SerializedName), convertedItem, paramType.ElementType); return forEachStatement; } } + private static bool IsExtensibleStringEnum(CSharpType type) + => type.IsEnum && type.IsStruct && type.UnderlyingEnumType == typeof(string); + + private static void AddExplodeQueryItem( + ForEachStatement forEachStatement, + ScopedApi uri, + ValueExpression key, + ValueExpression convertedItem, + CSharpType elementType) + { + if (IsExtensibleStringEnum(elementType)) + { + forEachStatement.Add(Declare("paramStr", typeof(string), convertedItem, out VariableExpression cachedVar)); + forEachStatement.Add(new IfStatement(cachedVar.As().NotEqual(Null)) + { + uri.AppendQuery(key, cachedVar, true).Terminate() + }); + } + else + { + forEachStatement.Add(uri.AppendQuery(key, convertedItem, true).Terminate()); + } + } + /// /// Builds the statements for a model-typed query parameter that uses form-style `explode`. /// Each (simple) property of the model is emitted as its own query entry using the property's diff --git a/packages/http-client-csharp/generator/Microsoft.TypeSpec.Generator.ClientModel/test/Providers/RestClientProviders/RestClientProviderTests.cs b/packages/http-client-csharp/generator/Microsoft.TypeSpec.Generator.ClientModel/test/Providers/RestClientProviders/RestClientProviderTests.cs index 07de6b5411a..1239e640469 100644 --- a/packages/http-client-csharp/generator/Microsoft.TypeSpec.Generator.ClientModel/test/Providers/RestClientProviders/RestClientProviderTests.cs +++ b/packages/http-client-csharp/generator/Microsoft.TypeSpec.Generator.ClientModel/test/Providers/RestClientProviders/RestClientProviderTests.cs @@ -1054,6 +1054,10 @@ public void TestBuildCreateRequestMethodWithQueryParameters() var inputStringEnum = InputFactory.StringEnum( "foo", stringEnumValues); + var inputExtensibleStringEnum = InputFactory.StringEnum( + "extensibleFoo", + stringEnumValues, + isExtensible: true); var inputIntEnum = InputFactory.Int32Enum( "intFoo", intEnumValues); @@ -1078,6 +1082,10 @@ public void TestBuildCreateRequestMethodWithQueryParameters() InputFactory.QueryParameter("p7Explode", InputFactory.Dictionary(inputIntEnum), isRequired: true, explode: true), InputFactory.QueryParameter("p8Explode", InputFactory.Array(inputFloatEnum), isRequired: true, explode: true), InputFactory.QueryParameter("p9Explode", InputFactory.Array(inputDoubleEnum), isRequired: true, explode: true), + InputFactory.QueryParameter("p10Explode", InputFactory.Array(inputExtensibleStringEnum), isRequired: true, explode: true), + InputFactory.QueryParameter("p11Explode", InputFactory.Dictionary(inputExtensibleStringEnum), isRequired: true, explode: true), + InputFactory.QueryParameter("p12", inputExtensibleStringEnum, isRequired: true), + InputFactory.QueryParameter("p13", new InputNullableType(inputExtensibleStringEnum), isRequired: false), ]; var operation = InputFactory.Operation( "sampleOp", diff --git a/packages/http-client-csharp/generator/Microsoft.TypeSpec.Generator.ClientModel/test/Providers/RestClientProviders/TestData/RestClientProviderTests/TestBuildCreateRequestMethodWithQueryParameters.cs b/packages/http-client-csharp/generator/Microsoft.TypeSpec.Generator.ClientModel/test/Providers/RestClientProviders/TestData/RestClientProviderTests/TestBuildCreateRequestMethodWithQueryParameters.cs index 60b5383a969..ed43cefed82 100644 --- a/packages/http-client-csharp/generator/Microsoft.TypeSpec.Generator.ClientModel/test/Providers/RestClientProviders/TestData/RestClientProviderTests/TestBuildCreateRequestMethodWithQueryParameters.cs +++ b/packages/http-client-csharp/generator/Microsoft.TypeSpec.Generator.ClientModel/test/Providers/RestClientProviders/TestData/RestClientProviderTests/TestBuildCreateRequestMethodWithQueryParameters.cs @@ -10,7 +10,7 @@ namespace Sample { public partial class TestClient { - internal global::System.ClientModel.Primitives.PipelineMessage CreateSampleOpRequest(global::System.Collections.Generic.IEnumerable p1Explode, global::System.Collections.Generic.IEnumerable p1, global::System.Collections.Generic.IEnumerable p2Explode, global::System.Collections.Generic.IEnumerable p2, global::System.Collections.Generic.IDictionary p3Explode, global::System.Collections.Generic.IDictionary p3, global::System.Collections.Generic.IEnumerable p4Explode, global::System.Collections.Generic.IEnumerable p5Explode, global::System.Collections.Generic.IDictionary p6Explode, global::System.Collections.Generic.IDictionary p7Explode, global::System.Collections.Generic.IEnumerable p8Explode, global::System.Collections.Generic.IEnumerable p9Explode, string optionalParam, global::System.ClientModel.Primitives.RequestOptions options) + internal global::System.ClientModel.Primitives.PipelineMessage CreateSampleOpRequest(global::System.Collections.Generic.IEnumerable p1Explode, global::System.Collections.Generic.IEnumerable p1, global::System.Collections.Generic.IEnumerable p2Explode, global::System.Collections.Generic.IEnumerable p2, global::System.Collections.Generic.IDictionary p3Explode, global::System.Collections.Generic.IDictionary p3, global::System.Collections.Generic.IEnumerable p4Explode, global::System.Collections.Generic.IEnumerable p5Explode, global::System.Collections.Generic.IDictionary p6Explode, global::System.Collections.Generic.IDictionary p7Explode, global::System.Collections.Generic.IEnumerable p8Explode, global::System.Collections.Generic.IEnumerable p9Explode, global::System.Collections.Generic.IEnumerable p10Explode, global::System.Collections.Generic.IDictionary p11Explode, string p12, string optionalParam, string p13, global::System.ClientModel.Primitives.RequestOptions options) { global::Sample.ClientUriBuilder uri = new global::Sample.ClientUriBuilder(); uri.Reset(_endpoint); @@ -75,14 +75,14 @@ public partial class TestClient { foreach (var @param in p6Explode) { - uri.AppendQuery(@param.Key, @param.ToSerialString(), true); + uri.AppendQuery(@param.Key, @param.Value.ToSerialString(), true); } } if (((p7Explode != null) && !((p7Explode is global::Sample.ChangeTrackingDictionary changeTrackingDictionary2) && changeTrackingDictionary2.IsUndefined))) { foreach (var @param in p7Explode) { - uri.AppendQuery(@param.Key, ((int)@param), true); + uri.AppendQuery(@param.Key, ((int)@param.Value), true); } } if (((p8Explode != null) && !((p8Explode is global::Sample.ChangeTrackingList changeTrackingList5) && changeTrackingList5.IsUndefined))) @@ -99,6 +99,33 @@ public partial class TestClient uri.AppendQuery("p9Explode", ((double)@param), true); } } + if (((p10Explode != null) && !((p10Explode is global::Sample.ChangeTrackingList changeTrackingList7) && changeTrackingList7.IsUndefined))) + { + foreach (var @param in p10Explode) + { + string paramStr = @param.ToString(); + if ((paramStr != null)) + { + uri.AppendQuery("p10Explode", paramStr, true); + } + } + } + if (((p11Explode != null) && !((p11Explode is global::Sample.ChangeTrackingDictionary changeTrackingDictionary3) && changeTrackingDictionary3.IsUndefined))) + { + foreach (var @param in p11Explode) + { + string paramStr = @param.Value.ToString(); + if ((paramStr != null)) + { + uri.AppendQuery(@param.Key, paramStr, true); + } + } + } + uri.AppendQuery("p12", p12, true); + if ((p13 != null)) + { + uri.AppendQuery("p13", p13, true); + } global::System.ClientModel.Primitives.PipelineMessage message = Pipeline.CreateMessage(uri.ToUri(), "GET", PipelineMessageClassifier200); global::System.ClientModel.Primitives.PipelineRequest request = message.Request; message.Apply(options);