diff --git a/src/Microsoft.OpenApi/Models/OpenApiParameter.cs b/src/Microsoft.OpenApi/Models/OpenApiParameter.cs
index f1300f027..6e4e6028c 100644
--- a/src/Microsoft.OpenApi/Models/OpenApiParameter.cs
+++ b/src/Microsoft.OpenApi/Models/OpenApiParameter.cs
@@ -116,6 +116,20 @@ internal void SerializeInternal(IOpenApiWriter writer, OpenApiSpecVersion versio
{
Utils.CheckArgumentNull(writer);
+ // Check for querystring restrictions
+ if (In == ParameterLocation.QueryString)
+ {
+ if (version < OpenApiSpecVersion.OpenApi3_2)
+ {
+ throw new InvalidOperationException("Parameter location 'querystring' is only supported in OpenAPI 3.2.0 and above.");
+ }
+ // Only throw if forbidden properties are explicitly set (not just default values)
+ if ((_style.HasValue) || (_explode.HasValue && _explode.Value) || AllowReserved || Schema != null)
+ {
+ throw new InvalidOperationException("When 'in' is 'querystring', 'style', 'explode', 'allowReserved', and 'schema' properties MUST NOT be used as per OpenAPI 3.2 specification.");
+ }
+ }
+
writer.WriteStartObject();
// name
@@ -252,6 +266,12 @@ public virtual void SerializeAsV2(IOpenApiWriter writer)
{
Utils.CheckArgumentNull(writer);
+ // Throw if 'querystring' is used in V2
+ if (In == ParameterLocation.QueryString)
+ {
+ throw new InvalidOperationException("Parameter location 'querystring' is not supported in OpenAPI 2.0.");
+ }
+
writer.WriteStartObject();
// in
diff --git a/src/Microsoft.OpenApi/Models/ParameterLocation.cs b/src/Microsoft.OpenApi/Models/ParameterLocation.cs
index 28d282496..4a5683190 100644
--- a/src/Microsoft.OpenApi/Models/ParameterLocation.cs
+++ b/src/Microsoft.OpenApi/Models/ParameterLocation.cs
@@ -27,6 +27,11 @@ public enum ParameterLocation
///
/// Used to pass a specific cookie value to the API.
///
- [Display("cookie")] Cookie
+ [Display("cookie")] Cookie,
+
+ ///
+ /// Parameters that are appended to the URL query string (OpenAPI 3.2+ only).
+ ///
+ [Display("querystring")] QueryString
}
}
diff --git a/test/Microsoft.OpenApi.Tests/Models/OpenApiParameterTests.cs b/test/Microsoft.OpenApi.Tests/Models/OpenApiParameterTests.cs
index 8bd30a7c9..0cd2726dd 100644
--- a/test/Microsoft.OpenApi.Tests/Models/OpenApiParameterTests.cs
+++ b/test/Microsoft.OpenApi.Tests/Models/OpenApiParameterTests.cs
@@ -1,6 +1,7 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT license.
+using System;
using System.Collections.Generic;
using System.Globalization;
using System.IO;
@@ -406,5 +407,52 @@ public async Task SerializeParameterWithFormStyleAndExplodeTrueWorksAsync(bool p
// Assert
await Verifier.Verify(outputStringWriter).UseParameters(produceTerseOutput);
}
+
+ [Fact]
+ public void SerializeQueryStringParameter_BelowV32_Throws()
+ {
+ var parameter = new OpenApiParameter
+ {
+ Name = "foo",
+ In = ParameterLocation.QueryString
+ };
+ var writer = new OpenApiJsonWriter(new StringWriter());
+ // Style, Explode, AllowReserved, and Schema must be unset for this test to throw as expected
+ Assert.Throws(() => parameter.SerializeAsV3(writer));
+ Assert.Throws(() => parameter.SerializeAsV31(writer));
+ Assert.Throws(() => parameter.SerializeAsV2(writer));
+ }
+
+ [Fact]
+ public void SerializeQueryStringParameter_WithForbiddenProperties_Throws()
+ {
+ var parameter = new OpenApiParameter
+ {
+ Name = "foo",
+ In = ParameterLocation.QueryString,
+ Style = ParameterStyle.Form,
+ Explode = true,
+ AllowReserved = true,
+ Schema = new OpenApiSchema { Type = JsonSchemaType.String }
+ };
+ var writer = new OpenApiJsonWriter(new StringWriter());
+ Assert.Throws(() => parameter.SerializeAsV32(writer));
+ }
+
+ [Fact]
+ public async Task SerializeQueryStringParameter_V32_Succeeds()
+ {
+ var parameter = new OpenApiParameter
+ {
+ Name = "foo",
+ In = ParameterLocation.QueryString,
+ Style = null,
+ AllowReserved = false,
+ Schema = null,
+ // Explode must be false (default) and not set
+ };
+ var json = await parameter.SerializeAsJsonAsync(OpenApiSpecVersion.OpenApi3_2);
+ Assert.Contains("querystring", json);
+ }
}
}
diff --git a/test/Microsoft.OpenApi.Tests/PublicApi/PublicApi.approved.txt b/test/Microsoft.OpenApi.Tests/PublicApi/PublicApi.approved.txt
index d2a93e2c8..dafa995e4 100644
--- a/test/Microsoft.OpenApi.Tests/PublicApi/PublicApi.approved.txt
+++ b/test/Microsoft.OpenApi.Tests/PublicApi/PublicApi.approved.txt
@@ -1736,6 +1736,8 @@ namespace Microsoft.OpenApi
Path = 2,
[Microsoft.OpenApi.Display("cookie")]
Cookie = 3,
+ [Microsoft.OpenApi.Display("querystring")]
+ QueryString = 4,
}
public enum ParameterStyle
{