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 2ed3406ed73..dda25c1a846 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 @@ -24,6 +24,7 @@ public class RestClientProvider : TypeProvider private const string RepeatabilityRequestIdHeader = "Repeatability-Request-ID"; private const string RepeatabilityFirstSentHeader = "Repeatability-First-Sent"; private const string MaxPageSizeParameterName = "maxpagesize"; + private const string ApiVersionParameterName = "api-version"; private static readonly Dictionary _knownSpecialHeaderParams = new(StringComparer.OrdinalIgnoreCase) { @@ -306,6 +307,17 @@ private Dictionary GetReinjectedParametersMap( } } + // Add API version parameters that need to be preserved across pagination requests + var apiVersionParam = operation.Parameters.FirstOrDefault(p => p.IsApiVersion); + if (apiVersionParam != null && !reinjectedParamsMap.ContainsKey(apiVersionParam.Name)) + { + var createdParam = ScmCodeModelGenerator.Instance.TypeFactory.CreateParameter(apiVersionParam); + if (createdParam != null && paramMap.TryGetValue(createdParam.Name, out var paramInSignature)) + { + reinjectedParamsMap[apiVersionParam.Name] = paramInSignature; + } + } + return reinjectedParamsMap; } @@ -452,7 +464,7 @@ private List AppendQueryParameters(ScopedApi uri, InputOper // Determine if we should update existing parameters or always append bool shouldUpdateExisting = isNextLinkRequest && - ShouldSkipReinjectedParameter(inputQueryParameter.SerializedName) && + ShouldUpdateReinjectedParameter(inputQueryParameter.SerializedName) && paramType?.IsCollection != true; MethodBodyStatement statement = shouldUpdateExisting @@ -843,9 +855,10 @@ private static bool TryGetSpecialHeaderParam(InputParameter inputParameter, [Not return false; } - private static bool ShouldSkipReinjectedParameter(string parameterName) + private static bool ShouldUpdateReinjectedParameter(string parameterName) { - return parameterName.Equals(MaxPageSizeParameterName, StringComparison.OrdinalIgnoreCase); + return parameterName.Equals(MaxPageSizeParameterName, StringComparison.OrdinalIgnoreCase) || + parameterName.Equals(ApiVersionParameterName, StringComparison.OrdinalIgnoreCase); // In the future, we can extend this to check multiple parameters } 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 57185131052..a275577bb79 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 @@ -1374,5 +1374,63 @@ private static IEnumerable ValidateApiVersionPathParameterTestCase ], parameters: [endpointParameter, enumApiVersionParameter])); } + + [Test] + public void TestApiVersionParameterReinjectedInCreateNextRequestMethod() + { + // Create API version parameter marked with IsApiVersion = true + var apiVersionParam = InputFactory.QueryParameter("apiVersion", InputPrimitiveType.String, + isRequired: true, serializedName: "api-version", isApiVersion: true); + var pageSizeParam = InputFactory.QueryParameter("maxpagesize", InputPrimitiveType.Int32, + isRequired: false, serializedName: "maxpagesize"); + + List parameters = + [ + apiVersionParam, + pageSizeParam, + ]; + + List methodParameters = + [ + InputFactory.MethodParameter("apiVersion", InputPrimitiveType.String, isRequired: true, + location: InputRequestLocation.Query, serializedName: "api-version"), + InputFactory.MethodParameter("maxpagesize", InputPrimitiveType.Int32, isRequired: false, + location: InputRequestLocation.Query, serializedName: "maxpagesize"), + ]; + + var inputModel = InputFactory.Model("Item", properties: + [ + InputFactory.Property("id", InputPrimitiveType.String, isRequired: true), + ]); + + var pagingMetadata = InputFactory.NextLinkPagingMetadata(["value"], ["nextLink"], + InputResponseLocation.Body, reinjectedParameters: []); + + var response = InputFactory.OperationResponse( + [200], + InputFactory.Model( + "PagedItems", + properties: [ + InputFactory.Property("value", InputFactory.Array(inputModel)), + InputFactory.Property("nextLink", InputPrimitiveType.Url) + ])); + + var operation = InputFactory.Operation("listItems", responses: [response], parameters: parameters); + var inputServiceMethod = InputFactory.PagingServiceMethod( + "listItems", + operation, + pagingMetadata: pagingMetadata, + parameters: methodParameters); + + var client = InputFactory.Client("TestClient", methods: [inputServiceMethod]); + var clientProvider = new ClientProvider(client); + var restClientProvider = new MockClientProvider(client, clientProvider); + + var writer = new TypeProviderWriter(restClientProvider); + var file = writer.Write(); + + Assert.That(file.Content, Contains.Substring("api-version")); + Assert.That(file.Content, Contains.Substring("maxpagesize")); + } } }