diff --git a/Swashbuckle.AspNetCore.slnx b/Swashbuckle.AspNetCore.slnx
index a6e0f06356..5bfe87b48d 100644
--- a/Swashbuckle.AspNetCore.slnx
+++ b/Swashbuckle.AspNetCore.slnx
@@ -58,6 +58,7 @@
+
diff --git a/src/Swashbuckle.AspNetCore.Cli/CommandRunner.cs b/src/Swashbuckle.AspNetCore.Cli/CommandRunner.cs
index 0e874c0178..89dbb3c403 100644
--- a/src/Swashbuckle.AspNetCore.Cli/CommandRunner.cs
+++ b/src/Swashbuckle.AspNetCore.Cli/CommandRunner.cs
@@ -4,7 +4,7 @@ internal class CommandRunner(string commandName, string commandDescription, Text
{
private readonly Dictionary _argumentDescriptors = [];
private readonly Dictionary _optionDescriptors = [];
- private Func, int> _runFunc = (_) => 1;
+ private Func, Task> _runFunc = (_) => Task.FromResult(1);
private readonly List _subRunners = [];
private readonly TextWriter _output = output;
@@ -27,7 +27,7 @@ public void Option(string name, string description, bool isFlag = false)
_optionDescriptors.Add(name, new OptionDescriptor { Description = description, IsFlag = isFlag });
}
- public void OnRun(Func, int> runFunc)
+ public void OnRun(Func, Task> runFunc)
{
_runFunc = runFunc;
}
@@ -39,12 +39,12 @@ public void SubCommand(string name, string description, Action co
_subRunners.Add(runner);
}
- public int Run(IEnumerable args)
+ public async Task RunAsync(IEnumerable args)
{
if (args.Any())
{
var subRunner = _subRunners.FirstOrDefault(r => r.CommandName.Split(' ').Last() == args.First());
- if (subRunner != null) return subRunner.Run(args.Skip(1));
+ if (subRunner != null) return await subRunner.RunAsync(args.Skip(1));
}
if (_subRunners.Count != 0 || !TryParseArgs(args, out IDictionary namedArgs))
@@ -53,7 +53,7 @@ public int Run(IEnumerable args)
return 1;
}
- return _runFunc(namedArgs);
+ return await _runFunc(namedArgs);
}
private bool TryParseArgs(IEnumerable args, out IDictionary namedArgs)
diff --git a/src/Swashbuckle.AspNetCore.Cli/Program.cs b/src/Swashbuckle.AspNetCore.Cli/Program.cs
index 14d65ac17a..449526146b 100644
--- a/src/Swashbuckle.AspNetCore.Cli/Program.cs
+++ b/src/Swashbuckle.AspNetCore.Cli/Program.cs
@@ -16,7 +16,7 @@ internal class Program
{
private const string OpenApiVersionOption = "--openapiversion";
- public static int Main(string[] args)
+ public static async Task Main(string[] args)
{
// Helper to simplify command line parsing etc.
var runner = new CommandRunner("dotnet swagger", "Swashbuckle (Swagger) Command Line Tools", Console.Out);
@@ -45,7 +45,7 @@ public static int Main(string[] args)
using var child = Process.Start("dotnet", subProcessCommandLine);
child.WaitForExit();
- return child.ExitCode;
+ return Task.FromResult(child.ExitCode);
});
});
@@ -60,14 +60,16 @@ public static int Main(string[] args)
c.Option(OpenApiVersionOption, "");
c.Option("--yaml", "", true);
- c.OnRun((namedArgs) =>
+ c.OnRun(async (namedArgs) =>
{
- SetupAndRetrieveSwaggerProviderAndOptions(namedArgs, out var swaggerProvider, out var swaggerOptions);
+ SetupAndRetrieveSwaggerProviderAndOptions(namedArgs, out var asyncSwaggerProvider, out var swaggerProvider, out var swaggerOptions);
var swaggerDocumentSerializer = swaggerOptions?.Value?.CustomDocumentSerializer;
- var swagger = swaggerProvider.GetSwagger(
- namedArgs["swaggerdoc"],
- namedArgs.TryGetValue("--host", out var arg) ? arg : null,
- namedArgs.TryGetValue("--basepath", out var namedArg) ? namedArg : null);
+
+ var host = namedArgs.TryGetValue("--host", out var arg) ? arg : null;
+ var basePath = namedArgs.TryGetValue("--basepath", out var namedArg) ? namedArg : null;
+ var swagger = asyncSwaggerProvider != null
+ ? await asyncSwaggerProvider.GetSwaggerAsync(namedArgs["swaggerdoc"], host, basePath)
+ : swaggerProvider.GetSwagger(namedArgs["swaggerdoc"], host, basePath);
// 4) Serialize to specified output location or stdout
var outputPath = namedArgs.TryGetValue("--output", out var arg1)
@@ -139,7 +141,7 @@ public static int Main(string[] args)
using var child = Process.Start("dotnet", subProcessCommandLine);
child.WaitForExit();
- return child.ExitCode;
+ return Task.FromResult(child.ExitCode);
});
});
@@ -150,7 +152,7 @@ public static int Main(string[] args)
c.Option("--output", "");
c.OnRun((namedArgs) =>
{
- SetupAndRetrieveSwaggerProviderAndOptions(namedArgs, out var swaggerProvider, out var swaggerOptions);
+ SetupAndRetrieveSwaggerProviderAndOptions(namedArgs, out _, out var swaggerProvider, out var swaggerOptions);
IList docNames = [];
string outputPath = namedArgs.TryGetValue("--output", out var arg1)
@@ -172,7 +174,7 @@ public static int Main(string[] args)
if (swaggerProvider is not ISwaggerDocumentMetadataProvider docMetaProvider)
{
writer.WriteLine($"The registered {nameof(ISwaggerProvider)} instance does not implement {nameof(ISwaggerDocumentMetadataProvider)}; unable to list the Swagger document names.");
- return -1;
+ return Task.FromResult(-1);
}
docNames = docMetaProvider.GetDocumentNames();
@@ -182,14 +184,14 @@ public static int Main(string[] args)
writer.WriteLine($"\"{name}\"");
}
- return 0;
+ return Task.FromResult(0);
});
});
- return runner.Run(args);
+ return await runner.RunAsync(args);
}
- private static void SetupAndRetrieveSwaggerProviderAndOptions(IDictionary namedArgs, out ISwaggerProvider swaggerProvider, out IOptions swaggerOptions)
+ private static void SetupAndRetrieveSwaggerProviderAndOptions(IDictionary namedArgs, out IAsyncSwaggerProvider asyncSwaggerProvider, out ISwaggerProvider swaggerProvider, out IOptions swaggerOptions)
{
// 1) Configure host with provided startupassembly
var startupAssembly = AssemblyLoadContext.Default.LoadFromAssemblyPath(
@@ -199,6 +201,7 @@ private static void SetupAndRetrieveSwaggerProviderAndOptions(IDictionary();
swaggerProvider = serviceProvider.GetRequiredService();
swaggerOptions = serviceProvider.GetService>();
}
diff --git a/test/Swashbuckle.AspNetCore.Cli.Test/CommandRunnerTests.cs b/test/Swashbuckle.AspNetCore.Cli.Test/CommandRunnerTests.cs
index 774223f9b4..feaf29ec0d 100644
--- a/test/Swashbuckle.AspNetCore.Cli.Test/CommandRunnerTests.cs
+++ b/test/Swashbuckle.AspNetCore.Cli.Test/CommandRunnerTests.cs
@@ -5,7 +5,7 @@ namespace Swashbuckle.AspNetCore.Cli.Test;
public static class CommandRunnerTests
{
[Fact]
- public static void Run_ParsesArgumentsAndExecutesCommands_AccordingToConfiguredMetadata()
+ public static async Task Run_ParsesArgumentsAndExecutesCommands_AccordingToConfiguredMetadata()
{
var receivedValues = new List();
var subject = new CommandRunner("test", "a test", new StringWriter());
@@ -18,7 +18,7 @@ public static void Run_ParsesArgumentsAndExecutesCommands_AccordingToConfiguredM
receivedValues.Add(namedArgs["--opt1"]);
receivedValues.Add(namedArgs["--opt2"]);
receivedValues.Add(namedArgs["arg1"]);
- return 2;
+ return Task.FromResult(2);
});
});
subject.SubCommand("cmd2", "", c => {
@@ -30,12 +30,12 @@ public static void Run_ParsesArgumentsAndExecutesCommands_AccordingToConfiguredM
receivedValues.Add(namedArgs["--opt1"]);
receivedValues.Add(namedArgs["--opt2"]);
receivedValues.Add(namedArgs["arg1"]);
- return 3;
+ return Task.FromResult(3);
});
});
- var cmd1ExitCode = subject.Run(["cmd1", "--opt1", "foo", "--opt2", "bar"]);
- var cmd2ExitCode = subject.Run(["cmd2", "--opt1", "blah", "--opt2", "dblah"]);
+ var cmd1ExitCode = await subject.RunAsync(["cmd1", "--opt1", "foo", "--opt2", "bar"]);
+ var cmd2ExitCode = await subject.RunAsync(["cmd2", "--opt1", "blah", "--opt2", "dblah"]);
Assert.Equal(2, cmd1ExitCode);
Assert.Equal(3, cmd2ExitCode);
@@ -43,14 +43,14 @@ public static void Run_ParsesArgumentsAndExecutesCommands_AccordingToConfiguredM
}
[Fact]
- public static void Run_PrintsAvailableCommands_WhenUnexpectedCommandIsProvided()
+ public static async Task Run_PrintsAvailableCommands_WhenUnexpectedCommandIsProvided()
{
var output = new StringWriter();
var subject = new CommandRunner("test", "a test", output);
subject.SubCommand("cmd", "does something", c => {
});
- var exitCode = subject.Run(["foo"]);
+ var exitCode = await subject.RunAsync(["foo"]);
Assert.StartsWith("a test", output.ToString());
Assert.Contains("Commands:", output.ToString());
@@ -58,14 +58,14 @@ public static void Run_PrintsAvailableCommands_WhenUnexpectedCommandIsProvided()
}
[Fact]
- public static void Run_PrintsAvailableCommands_WhenHelpOptionIsProvided()
+ public static async Task Run_PrintsAvailableCommands_WhenHelpOptionIsProvided()
{
var output = new StringWriter();
var subject = new CommandRunner("test", "a test", output);
subject.SubCommand("cmd", "does something", c => {
});
- var exitCode = subject.Run(["--help"]);
+ var exitCode = await subject.RunAsync(["--help"]);
Assert.StartsWith("a test", output.ToString());
Assert.Contains("Commands:", output.ToString());
@@ -81,7 +81,7 @@ public static void Run_PrintsAvailableCommands_WhenHelpOptionIsProvided()
[InlineData(new string[0], new[] { "arg1" }, new[] { "cmd", "--opt1" }, true)]
[InlineData(new string[0], new[] { "arg1" }, new[] { "cmd", "foo", "bar" }, true)]
[InlineData(new string[0], new[] { "arg1" }, new[] { "cmd", "foo" }, false)]
- public static void Run_PrintsCommandUsage_WhenUnexpectedArgumentsAreProvided(
+ public static async Task Run_PrintsCommandUsage_WhenUnexpectedArgumentsAreProvided(
string[] optionNames,
string[] argNames,
string[] providedArgs,
@@ -97,7 +97,7 @@ public static void Run_PrintsCommandUsage_WhenUnexpectedArgumentsAreProvided(
c.Argument(name, "");
});
- subject.Run(providedArgs);
+ await subject.RunAsync(providedArgs);
if (shouldPrintUsage)
Assert.StartsWith("Usage: test cmd", output.ToString());
diff --git a/test/Swashbuckle.AspNetCore.Cli.Test/Swashbuckle.AspNetCore.Cli.Test.csproj b/test/Swashbuckle.AspNetCore.Cli.Test/Swashbuckle.AspNetCore.Cli.Test.csproj
index dc0d77941a..285c4179dd 100644
--- a/test/Swashbuckle.AspNetCore.Cli.Test/Swashbuckle.AspNetCore.Cli.Test.csproj
+++ b/test/Swashbuckle.AspNetCore.Cli.Test/Swashbuckle.AspNetCore.Cli.Test.csproj
@@ -7,6 +7,7 @@
+
diff --git a/test/Swashbuckle.AspNetCore.Cli.Test/ToolTests.cs b/test/Swashbuckle.AspNetCore.Cli.Test/ToolTests.cs
index facefaddc3..9c47543f54 100644
--- a/test/Swashbuckle.AspNetCore.Cli.Test/ToolTests.cs
+++ b/test/Swashbuckle.AspNetCore.Cli.Test/ToolTests.cs
@@ -8,9 +8,9 @@ namespace Swashbuckle.AspNetCore.Cli.Test;
public static class ToolTests
{
[Fact]
- public static void Can_Output_Swagger_Document_Names()
+ public static async Task Can_Output_Swagger_Document_Names()
{
- var result = RunToStringCommand((outputPath) =>
+ var result = await RunToStringCommandAsync((outputPath) =>
[
"list",
"--output",
@@ -22,17 +22,17 @@ public static void Can_Output_Swagger_Document_Names()
}
[Fact]
- public static void Throws_When_Startup_Assembly_Does_Not_Exist()
+ public static async Task Throws_When_Startup_Assembly_Does_Not_Exist()
{
string[] args = ["tofile", "--output", "swagger.json", "--openapiversion", "2.0", "./does_not_exist.dll", "v1"];
- Assert.Throws(() => Program.Main(args));
+ await Assert.ThrowsAsync(() => Program.Main(args));
}
[Theory]
[InlineData("a")]
[InlineData("1.9")]
[InlineData("3.2")]
- public static void Error_When_OpenApiVersion_Is_Not_Supported(string version)
+ public static async Task Error_When_OpenApiVersion_Is_Not_Supported(string version)
{
string[] args =
[
@@ -44,13 +44,13 @@ public static void Error_When_OpenApiVersion_Is_Not_Supported(string version)
Path.Combine(Directory.GetCurrentDirectory(), "Basic.dll"),
"v1"
];
- Assert.NotEqual(0, Program.Main(args));
+ Assert.NotEqual(0, await Program.Main(args));
}
[Fact]
- public static void Can_Generate_Swagger_Json_v2_OpenApiVersion()
+ public static async Task Can_Generate_Swagger_Json_v2_OpenApiVersion()
{
- using var document = RunToJsonCommand((outputPath) =>
+ using var document = await RunToJsonCommandAsync((outputPath) =>
[
"tofile",
"--output",
@@ -70,9 +70,9 @@ public static void Can_Generate_Swagger_Json_v2_OpenApiVersion()
}
[Fact]
- public static void Can_Generate_Swagger_Json_v3()
+ public static async Task Can_Generate_Swagger_Json_v3()
{
- using var document = RunToJsonCommand((outputPath) =>
+ using var document = await RunToJsonCommandAsync((outputPath) =>
[
"tofile",
"--output",
@@ -90,9 +90,9 @@ public static void Can_Generate_Swagger_Json_v3()
}
[Fact]
- public static void Can_Generate_Swagger_Json_v3_1()
+ public static async Task Can_Generate_Swagger_Json_v3_1()
{
- using var document = RunToJsonCommand((outputPath) =>
+ using var document = await RunToJsonCommandAsync((outputPath) =>
[
"tofile",
"--output",
@@ -112,9 +112,9 @@ public static void Can_Generate_Swagger_Json_v3_1()
}
[Fact]
- public static void Can_Generate_Swagger_Json_v3_OpenApiVersion()
+ public static async Task Can_Generate_Swagger_Json_v3_OpenApiVersion()
{
- using var document = RunToJsonCommand((outputPath) =>
+ using var document = await RunToJsonCommandAsync((outputPath) =>
[
"tofile",
"--output",
@@ -134,9 +134,35 @@ public static void Can_Generate_Swagger_Json_v3_OpenApiVersion()
}
[Fact]
- public static void Overwrites_Existing_File()
+ public static async Task Can_Generate_Swagger_Json_With_Async_Operation_Filters()
{
- using var document = RunToJsonCommand((outputPath) =>
+ using var document = await RunToJsonCommandAsync((outputPath) =>
+ [
+ "tofile",
+ "--output",
+ outputPath,
+ Path.Combine(Directory.GetCurrentDirectory(), "Authorization.dll"),
+ "v1"
+ ]);
+
+ var paths = document.RootElement.GetProperty("paths");
+ var resourcesPath = paths.GetProperty("/resources/{id}");
+ var getOp = resourcesPath.GetProperty("get");
+
+ // verify that the async operation filter resolved authorization policies and added security requirements
+ Assert.True(getOp.TryGetProperty("security", out var security));
+ Assert.True(security.GetArrayLength() > 0);
+
+ // verify that 401/403 responses were added by the async filter
+ var responses = getOp.GetProperty("responses");
+ Assert.True(responses.TryGetProperty("401", out _));
+ Assert.True(responses.TryGetProperty("403", out _));
+ }
+
+ [Fact]
+ public static async Task Overwrites_Existing_File()
+ {
+ using var document = await RunToJsonCommandAsync((outputPath) =>
{
File.WriteAllText(outputPath, new string('x', 100_000));
@@ -159,9 +185,9 @@ public static void Overwrites_Existing_File()
}
[Fact]
- public static void CustomDocumentSerializer_Writes_Custom_V2_Document()
+ public static async Task CustomDocumentSerializer_Writes_Custom_V2_Document()
{
- using var document = RunToJsonCommand((outputPath) =>
+ using var document = await RunToJsonCommandAsync((outputPath) =>
[
"tofile",
"--output",
@@ -178,9 +204,9 @@ public static void CustomDocumentSerializer_Writes_Custom_V2_Document()
}
[Fact]
- public static void CustomDocumentSerializer_Writes_Custom_V3_Document()
+ public static async Task CustomDocumentSerializer_Writes_Custom_V3_Document()
{
- using var document = RunToJsonCommand((outputPath) =>
+ using var document = await RunToJsonCommandAsync((outputPath) =>
[
"tofile",
"--output",
@@ -196,9 +222,9 @@ public static void CustomDocumentSerializer_Writes_Custom_V3_Document()
}
[Fact]
- public static void CustomDocumentSerializer_Writes_Custom_V3_1_Document()
+ public static async Task CustomDocumentSerializer_Writes_Custom_V3_1_Document()
{
- using var document = RunToJsonCommand((outputPath) =>
+ using var document = await RunToJsonCommandAsync((outputPath) =>
[
"tofile",
"--output",
@@ -216,9 +242,9 @@ public static void CustomDocumentSerializer_Writes_Custom_V3_1_Document()
}
[Fact]
- public static void Can_Generate_Swagger_Json_ForTopLevelApp()
+ public static async Task Can_Generate_Swagger_Json_ForTopLevelApp()
{
- using var document = RunToJsonCommand((outputPath) =>
+ using var document = await RunToJsonCommandAsync((outputPath) =>
[
"tofile",
"--output",
@@ -236,9 +262,9 @@ public static void Can_Generate_Swagger_Json_ForTopLevelApp()
}
[Fact]
- public static void Does_Not_Run_Crashing_HostedService()
+ public static async Task Does_Not_Run_Crashing_HostedService()
{
- using var document = RunToJsonCommand((outputPath) =>
+ using var document = await RunToJsonCommandAsync((outputPath) =>
[
"tofile",
"--output",
@@ -254,9 +280,9 @@ public static void Does_Not_Run_Crashing_HostedService()
}
[Fact]
- public static void Creates_New_Folder_Path()
+ public static async Task Creates_New_Folder_Path()
{
- using var document = RunToJsonCommand(outputPath =>
+ using var document = await RunToJsonCommandAsync(outputPath =>
[
"tofile",
"--output",
@@ -273,7 +299,7 @@ public static void Creates_New_Folder_Path()
Assert.True(productsPath.TryGetProperty("post", out _));
}
- private static string RunToStringCommand(Func setup, string subOutputPath = default)
+ private static async Task RunToStringCommandAsync(Func setup, string subOutputPath = default)
{
using var temporaryDirectory = new TemporaryDirectory();
@@ -283,14 +309,14 @@ private static string RunToStringCommand(Func setup, string su
string[] args = setup(outputPath);
- Assert.Equal(0, Program.Main(args));
+ Assert.Equal(0, await Program.Main(args));
return File.ReadAllText(outputPath);
}
- private static JsonDocument RunToJsonCommand(Func setup, string subOutputPath = default)
+ private static async Task RunToJsonCommandAsync(Func setup, string subOutputPath = default)
{
- string json = RunToStringCommand(setup, subOutputPath);
+ string json = await RunToStringCommandAsync(setup, subOutputPath);
return JsonDocument.Parse(json);
}
diff --git a/test/Swashbuckle.AspNetCore.IntegrationTests/SwaggerIntegrationTests.cs b/test/Swashbuckle.AspNetCore.IntegrationTests/SwaggerIntegrationTests.cs
index 5d01813839..c1575667f0 100644
--- a/test/Swashbuckle.AspNetCore.IntegrationTests/SwaggerIntegrationTests.cs
+++ b/test/Swashbuckle.AspNetCore.IntegrationTests/SwaggerIntegrationTests.cs
@@ -137,6 +137,7 @@ public async Task SwaggerMiddleware_CanBeConfiguredMultipleTimes(
[InlineData(typeof(TopLevelSwaggerDoc.Program), "/swagger/v1.json")]
[InlineData(typeof(WebApi.Program), "/swagger/v1/swagger.json")]
[InlineData(typeof(WebApi.Aot.Program), "/swagger/v1/swagger.json")]
+ [InlineData(typeof(Authorization.Program), "/swagger/v1/swagger.json")]
public async Task SwaggerEndpoint_ReturnsValidSwaggerJson_Without_Startup(
Type entryPointType,
string swaggerRequestUri)
diff --git a/test/Swashbuckle.AspNetCore.IntegrationTests/VerifyTests.cs b/test/Swashbuckle.AspNetCore.IntegrationTests/VerifyTests.cs
index 862b9ac97a..b2d1042e8e 100644
--- a/test/Swashbuckle.AspNetCore.IntegrationTests/VerifyTests.cs
+++ b/test/Swashbuckle.AspNetCore.IntegrationTests/VerifyTests.cs
@@ -66,6 +66,7 @@ await Verify(swagger)
[InlineData(typeof(WebApi.Program), "/swagger/v1/swagger.json")]
[InlineData(typeof(WebApi.Aot.Program), "/swagger/v1/swagger.json")]
[InlineData(typeof(WebApi.Map.Program), "/swagger/v1/swagger.json")]
+ [InlineData(typeof(Authorization.Program), "/swagger/v1/swagger.json")]
public async Task Swagger_IsValidJson_No_Startup(
Type entryPointType,
string swaggerRequestUri)
diff --git a/test/Swashbuckle.AspNetCore.IntegrationTests/snapshots/10_0/VerifyTests.Swagger_IsValidJson_No_Startup_entryPointType=Authorization.Program_swaggerRequestUri=v1.verified.txt b/test/Swashbuckle.AspNetCore.IntegrationTests/snapshots/10_0/VerifyTests.Swagger_IsValidJson_No_Startup_entryPointType=Authorization.Program_swaggerRequestUri=v1.verified.txt
new file mode 100644
index 0000000000..1fb3df8769
--- /dev/null
+++ b/test/Swashbuckle.AspNetCore.IntegrationTests/snapshots/10_0/VerifyTests.Swagger_IsValidJson_No_Startup_entryPointType=Authorization.Program_swaggerRequestUri=v1.verified.txt
@@ -0,0 +1,224 @@
+{
+ "openapi": "3.0.4",
+ "info": {
+ "title": "Authorization API",
+ "version": "v1"
+ },
+ "paths": {
+ "/resources": {
+ "get": {
+ "tags": [
+ "Resources"
+ ],
+ "responses": {
+ "200": {
+ "description": "OK",
+ "content": {
+ "text/plain": {
+ "schema": {
+ "type": "array",
+ "items": {
+ "$ref": "#/components/schemas/Resource"
+ }
+ }
+ },
+ "application/json": {
+ "schema": {
+ "type": "array",
+ "items": {
+ "$ref": "#/components/schemas/Resource"
+ }
+ }
+ },
+ "text/json": {
+ "schema": {
+ "type": "array",
+ "items": {
+ "$ref": "#/components/schemas/Resource"
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "post": {
+ "tags": [
+ "Resources"
+ ],
+ "requestBody": {
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/Resource"
+ }
+ },
+ "text/json": {
+ "schema": {
+ "$ref": "#/components/schemas/Resource"
+ }
+ },
+ "application/*+json": {
+ "schema": {
+ "$ref": "#/components/schemas/Resource"
+ }
+ }
+ }
+ },
+ "responses": {
+ "200": {
+ "description": "OK",
+ "content": {
+ "text/plain": {
+ "schema": {
+ "$ref": "#/components/schemas/Resource"
+ }
+ },
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/Resource"
+ }
+ },
+ "text/json": {
+ "schema": {
+ "$ref": "#/components/schemas/Resource"
+ }
+ }
+ }
+ },
+ "401": {
+ "description": "Unauthorized"
+ },
+ "403": {
+ "description": "Forbidden"
+ }
+ },
+ "security": [
+ {
+ "bearer": [
+ "Administrator"
+ ]
+ }
+ ]
+ }
+ },
+ "/resources/{id}": {
+ "get": {
+ "tags": [
+ "Resources"
+ ],
+ "parameters": [
+ {
+ "name": "id",
+ "in": "path",
+ "required": true,
+ "schema": {
+ "type": "integer",
+ "format": "int32"
+ }
+ }
+ ],
+ "responses": {
+ "200": {
+ "description": "OK",
+ "content": {
+ "text/plain": {
+ "schema": {
+ "$ref": "#/components/schemas/Resource"
+ }
+ },
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/Resource"
+ }
+ },
+ "text/json": {
+ "schema": {
+ "$ref": "#/components/schemas/Resource"
+ }
+ }
+ }
+ },
+ "401": {
+ "description": "Unauthorized"
+ },
+ "403": {
+ "description": "Forbidden"
+ }
+ },
+ "security": [
+ {
+ "bearer": [
+ "Reader",
+ "Administrator"
+ ]
+ }
+ ]
+ },
+ "delete": {
+ "tags": [
+ "Resources"
+ ],
+ "parameters": [
+ {
+ "name": "id",
+ "in": "path",
+ "required": true,
+ "schema": {
+ "type": "integer",
+ "format": "int32"
+ }
+ }
+ ],
+ "responses": {
+ "200": {
+ "description": "OK"
+ },
+ "401": {
+ "description": "Unauthorized"
+ },
+ "403": {
+ "description": "Forbidden"
+ }
+ },
+ "security": [
+ {
+ "bearer": [
+ "Administrator"
+ ]
+ }
+ ]
+ }
+ }
+ },
+ "components": {
+ "schemas": {
+ "Resource": {
+ "type": "object",
+ "properties": {
+ "id": {
+ "type": "integer",
+ "format": "int32"
+ },
+ "name": {
+ "type": "string",
+ "nullable": true
+ }
+ },
+ "additionalProperties": false
+ }
+ },
+ "securitySchemes": {
+ "bearer": {
+ "type": "http",
+ "scheme": "bearer",
+ "bearerFormat": "JWT"
+ }
+ }
+ },
+ "tags": [
+ {
+ "name": "Resources"
+ }
+ ]
+}
\ No newline at end of file
diff --git a/test/Swashbuckle.AspNetCore.IntegrationTests/snapshots/8_0/VerifyTests.Swagger_IsValidJson_No_Startup_entryPointType=Authorization.Program_swaggerRequestUri=v1.verified.txt b/test/Swashbuckle.AspNetCore.IntegrationTests/snapshots/8_0/VerifyTests.Swagger_IsValidJson_No_Startup_entryPointType=Authorization.Program_swaggerRequestUri=v1.verified.txt
new file mode 100644
index 0000000000..1fb3df8769
--- /dev/null
+++ b/test/Swashbuckle.AspNetCore.IntegrationTests/snapshots/8_0/VerifyTests.Swagger_IsValidJson_No_Startup_entryPointType=Authorization.Program_swaggerRequestUri=v1.verified.txt
@@ -0,0 +1,224 @@
+{
+ "openapi": "3.0.4",
+ "info": {
+ "title": "Authorization API",
+ "version": "v1"
+ },
+ "paths": {
+ "/resources": {
+ "get": {
+ "tags": [
+ "Resources"
+ ],
+ "responses": {
+ "200": {
+ "description": "OK",
+ "content": {
+ "text/plain": {
+ "schema": {
+ "type": "array",
+ "items": {
+ "$ref": "#/components/schemas/Resource"
+ }
+ }
+ },
+ "application/json": {
+ "schema": {
+ "type": "array",
+ "items": {
+ "$ref": "#/components/schemas/Resource"
+ }
+ }
+ },
+ "text/json": {
+ "schema": {
+ "type": "array",
+ "items": {
+ "$ref": "#/components/schemas/Resource"
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "post": {
+ "tags": [
+ "Resources"
+ ],
+ "requestBody": {
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/Resource"
+ }
+ },
+ "text/json": {
+ "schema": {
+ "$ref": "#/components/schemas/Resource"
+ }
+ },
+ "application/*+json": {
+ "schema": {
+ "$ref": "#/components/schemas/Resource"
+ }
+ }
+ }
+ },
+ "responses": {
+ "200": {
+ "description": "OK",
+ "content": {
+ "text/plain": {
+ "schema": {
+ "$ref": "#/components/schemas/Resource"
+ }
+ },
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/Resource"
+ }
+ },
+ "text/json": {
+ "schema": {
+ "$ref": "#/components/schemas/Resource"
+ }
+ }
+ }
+ },
+ "401": {
+ "description": "Unauthorized"
+ },
+ "403": {
+ "description": "Forbidden"
+ }
+ },
+ "security": [
+ {
+ "bearer": [
+ "Administrator"
+ ]
+ }
+ ]
+ }
+ },
+ "/resources/{id}": {
+ "get": {
+ "tags": [
+ "Resources"
+ ],
+ "parameters": [
+ {
+ "name": "id",
+ "in": "path",
+ "required": true,
+ "schema": {
+ "type": "integer",
+ "format": "int32"
+ }
+ }
+ ],
+ "responses": {
+ "200": {
+ "description": "OK",
+ "content": {
+ "text/plain": {
+ "schema": {
+ "$ref": "#/components/schemas/Resource"
+ }
+ },
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/Resource"
+ }
+ },
+ "text/json": {
+ "schema": {
+ "$ref": "#/components/schemas/Resource"
+ }
+ }
+ }
+ },
+ "401": {
+ "description": "Unauthorized"
+ },
+ "403": {
+ "description": "Forbidden"
+ }
+ },
+ "security": [
+ {
+ "bearer": [
+ "Reader",
+ "Administrator"
+ ]
+ }
+ ]
+ },
+ "delete": {
+ "tags": [
+ "Resources"
+ ],
+ "parameters": [
+ {
+ "name": "id",
+ "in": "path",
+ "required": true,
+ "schema": {
+ "type": "integer",
+ "format": "int32"
+ }
+ }
+ ],
+ "responses": {
+ "200": {
+ "description": "OK"
+ },
+ "401": {
+ "description": "Unauthorized"
+ },
+ "403": {
+ "description": "Forbidden"
+ }
+ },
+ "security": [
+ {
+ "bearer": [
+ "Administrator"
+ ]
+ }
+ ]
+ }
+ }
+ },
+ "components": {
+ "schemas": {
+ "Resource": {
+ "type": "object",
+ "properties": {
+ "id": {
+ "type": "integer",
+ "format": "int32"
+ },
+ "name": {
+ "type": "string",
+ "nullable": true
+ }
+ },
+ "additionalProperties": false
+ }
+ },
+ "securitySchemes": {
+ "bearer": {
+ "type": "http",
+ "scheme": "bearer",
+ "bearerFormat": "JWT"
+ }
+ }
+ },
+ "tags": [
+ {
+ "name": "Resources"
+ }
+ ]
+}
\ No newline at end of file
diff --git a/test/Swashbuckle.AspNetCore.IntegrationTests/snapshots/9_0/VerifyTests.Swagger_IsValidJson_No_Startup_entryPointType=Authorization.Program_swaggerRequestUri=v1.verified.txt b/test/Swashbuckle.AspNetCore.IntegrationTests/snapshots/9_0/VerifyTests.Swagger_IsValidJson_No_Startup_entryPointType=Authorization.Program_swaggerRequestUri=v1.verified.txt
new file mode 100644
index 0000000000..1fb3df8769
--- /dev/null
+++ b/test/Swashbuckle.AspNetCore.IntegrationTests/snapshots/9_0/VerifyTests.Swagger_IsValidJson_No_Startup_entryPointType=Authorization.Program_swaggerRequestUri=v1.verified.txt
@@ -0,0 +1,224 @@
+{
+ "openapi": "3.0.4",
+ "info": {
+ "title": "Authorization API",
+ "version": "v1"
+ },
+ "paths": {
+ "/resources": {
+ "get": {
+ "tags": [
+ "Resources"
+ ],
+ "responses": {
+ "200": {
+ "description": "OK",
+ "content": {
+ "text/plain": {
+ "schema": {
+ "type": "array",
+ "items": {
+ "$ref": "#/components/schemas/Resource"
+ }
+ }
+ },
+ "application/json": {
+ "schema": {
+ "type": "array",
+ "items": {
+ "$ref": "#/components/schemas/Resource"
+ }
+ }
+ },
+ "text/json": {
+ "schema": {
+ "type": "array",
+ "items": {
+ "$ref": "#/components/schemas/Resource"
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "post": {
+ "tags": [
+ "Resources"
+ ],
+ "requestBody": {
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/Resource"
+ }
+ },
+ "text/json": {
+ "schema": {
+ "$ref": "#/components/schemas/Resource"
+ }
+ },
+ "application/*+json": {
+ "schema": {
+ "$ref": "#/components/schemas/Resource"
+ }
+ }
+ }
+ },
+ "responses": {
+ "200": {
+ "description": "OK",
+ "content": {
+ "text/plain": {
+ "schema": {
+ "$ref": "#/components/schemas/Resource"
+ }
+ },
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/Resource"
+ }
+ },
+ "text/json": {
+ "schema": {
+ "$ref": "#/components/schemas/Resource"
+ }
+ }
+ }
+ },
+ "401": {
+ "description": "Unauthorized"
+ },
+ "403": {
+ "description": "Forbidden"
+ }
+ },
+ "security": [
+ {
+ "bearer": [
+ "Administrator"
+ ]
+ }
+ ]
+ }
+ },
+ "/resources/{id}": {
+ "get": {
+ "tags": [
+ "Resources"
+ ],
+ "parameters": [
+ {
+ "name": "id",
+ "in": "path",
+ "required": true,
+ "schema": {
+ "type": "integer",
+ "format": "int32"
+ }
+ }
+ ],
+ "responses": {
+ "200": {
+ "description": "OK",
+ "content": {
+ "text/plain": {
+ "schema": {
+ "$ref": "#/components/schemas/Resource"
+ }
+ },
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/Resource"
+ }
+ },
+ "text/json": {
+ "schema": {
+ "$ref": "#/components/schemas/Resource"
+ }
+ }
+ }
+ },
+ "401": {
+ "description": "Unauthorized"
+ },
+ "403": {
+ "description": "Forbidden"
+ }
+ },
+ "security": [
+ {
+ "bearer": [
+ "Reader",
+ "Administrator"
+ ]
+ }
+ ]
+ },
+ "delete": {
+ "tags": [
+ "Resources"
+ ],
+ "parameters": [
+ {
+ "name": "id",
+ "in": "path",
+ "required": true,
+ "schema": {
+ "type": "integer",
+ "format": "int32"
+ }
+ }
+ ],
+ "responses": {
+ "200": {
+ "description": "OK"
+ },
+ "401": {
+ "description": "Unauthorized"
+ },
+ "403": {
+ "description": "Forbidden"
+ }
+ },
+ "security": [
+ {
+ "bearer": [
+ "Administrator"
+ ]
+ }
+ ]
+ }
+ }
+ },
+ "components": {
+ "schemas": {
+ "Resource": {
+ "type": "object",
+ "properties": {
+ "id": {
+ "type": "integer",
+ "format": "int32"
+ },
+ "name": {
+ "type": "string",
+ "nullable": true
+ }
+ },
+ "additionalProperties": false
+ }
+ },
+ "securitySchemes": {
+ "bearer": {
+ "type": "http",
+ "scheme": "bearer",
+ "bearerFormat": "JWT"
+ }
+ }
+ },
+ "tags": [
+ {
+ "name": "Resources"
+ }
+ ]
+}
\ No newline at end of file
diff --git a/test/Swashbuckle.AspNetCore.IntegrationTests/snapshots/code/GeneratesValidClient_1ea4601ed911b960/KiotaOpenApiClient.verified.cs b/test/Swashbuckle.AspNetCore.IntegrationTests/snapshots/code/GeneratesValidClient_1ea4601ed911b960/KiotaOpenApiClient.verified.cs
new file mode 100644
index 0000000000..b51b78d957
--- /dev/null
+++ b/test/Swashbuckle.AspNetCore.IntegrationTests/snapshots/code/GeneratesValidClient_1ea4601ed911b960/KiotaOpenApiClient.verified.cs
@@ -0,0 +1,43 @@
+//
+#pragma warning disable CS0618
+using Microsoft.Kiota.Abstractions.Extensions;
+using Microsoft.Kiota.Abstractions;
+using Microsoft.Kiota.Serialization.Form;
+using Microsoft.Kiota.Serialization.Json;
+using Microsoft.Kiota.Serialization.Multipart;
+using Microsoft.Kiota.Serialization.Text;
+using Swashbuckle.AspNetCore.IntegrationTests.KiotaTests.Resources;
+using System.Collections.Generic;
+using System.IO;
+using System.Threading.Tasks;
+using System;
+namespace Swashbuckle.AspNetCore.IntegrationTests.KiotaTests
+{
+ ///
+ /// The main entry point of the SDK, exposes the configuration and the fluent API.
+ ///
+ [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")]
+ public partial class KiotaOpenApiClient : BaseRequestBuilder
+ {
+ /// The resources property
+ public global::Swashbuckle.AspNetCore.IntegrationTests.KiotaTests.Resources.ResourcesRequestBuilder Resources
+ {
+ get => new global::Swashbuckle.AspNetCore.IntegrationTests.KiotaTests.Resources.ResourcesRequestBuilder(PathParameters, RequestAdapter);
+ }
+ ///
+ /// Instantiates a new and sets the default values.
+ ///
+ /// The request adapter to use to execute the requests.
+ public KiotaOpenApiClient(IRequestAdapter requestAdapter) : base(requestAdapter, "{+baseurl}", new Dictionary())
+ {
+ ApiClientBuilder.RegisterDefaultSerializer();
+ ApiClientBuilder.RegisterDefaultSerializer();
+ ApiClientBuilder.RegisterDefaultSerializer();
+ ApiClientBuilder.RegisterDefaultSerializer();
+ ApiClientBuilder.RegisterDefaultDeserializer();
+ ApiClientBuilder.RegisterDefaultDeserializer();
+ ApiClientBuilder.RegisterDefaultDeserializer();
+ }
+ }
+}
+#pragma warning restore CS0618
diff --git a/test/Swashbuckle.AspNetCore.IntegrationTests/snapshots/code/GeneratesValidClient_1ea4601ed911b960/Models/Resource.verified.cs b/test/Swashbuckle.AspNetCore.IntegrationTests/snapshots/code/GeneratesValidClient_1ea4601ed911b960/Models/Resource.verified.cs
new file mode 100644
index 0000000000..e71661f59e
--- /dev/null
+++ b/test/Swashbuckle.AspNetCore.IntegrationTests/snapshots/code/GeneratesValidClient_1ea4601ed911b960/Models/Resource.verified.cs
@@ -0,0 +1,59 @@
+//
+#pragma warning disable CS0618
+using Microsoft.Kiota.Abstractions.Extensions;
+using Microsoft.Kiota.Abstractions.Serialization;
+using System.Collections.Generic;
+using System.IO;
+using System;
+namespace Swashbuckle.AspNetCore.IntegrationTests.KiotaTests.Models
+{
+ [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")]
+ #pragma warning disable CS1591
+ public partial class Resource : IParsable
+ #pragma warning restore CS1591
+ {
+ /// The id property
+ public int? Id { get; set; }
+ /// The name property
+#if NETSTANDARD2_1_OR_GREATER || NETCOREAPP3_1_OR_GREATER
+#nullable enable
+ public string? Name { get; set; }
+#nullable restore
+#else
+ public string Name { get; set; }
+#endif
+ ///
+ /// Creates a new instance of the appropriate class based on discriminator value
+ ///
+ /// A
+ /// The parse node to use to read the discriminator value and create the object
+ public static global::Swashbuckle.AspNetCore.IntegrationTests.KiotaTests.Models.Resource CreateFromDiscriminatorValue(IParseNode parseNode)
+ {
+ if(ReferenceEquals(parseNode, null)) throw new ArgumentNullException(nameof(parseNode));
+ return new global::Swashbuckle.AspNetCore.IntegrationTests.KiotaTests.Models.Resource();
+ }
+ ///
+ /// The deserialization information for the current model
+ ///
+ /// A IDictionary<string, Action<IParseNode>>
+ public virtual IDictionary> GetFieldDeserializers()
+ {
+ return new Dictionary>
+ {
+ { "id", n => { Id = n.GetIntValue(); } },
+ { "name", n => { Name = n.GetStringValue(); } },
+ };
+ }
+ ///
+ /// Serializes information the current object
+ ///
+ /// Serialization writer to use to serialize this model
+ public virtual void Serialize(ISerializationWriter writer)
+ {
+ if(ReferenceEquals(writer, null)) throw new ArgumentNullException(nameof(writer));
+ writer.WriteIntValue("id", Id);
+ writer.WriteStringValue("name", Name);
+ }
+ }
+}
+#pragma warning restore CS0618
diff --git a/test/Swashbuckle.AspNetCore.IntegrationTests/snapshots/code/GeneratesValidClient_1ea4601ed911b960/Resources/Item/ResourcesItemRequestBuilder.verified.cs b/test/Swashbuckle.AspNetCore.IntegrationTests/snapshots/code/GeneratesValidClient_1ea4601ed911b960/Resources/Item/ResourcesItemRequestBuilder.verified.cs
new file mode 100644
index 0000000000..4724f97fde
--- /dev/null
+++ b/test/Swashbuckle.AspNetCore.IntegrationTests/snapshots/code/GeneratesValidClient_1ea4601ed911b960/Resources/Item/ResourcesItemRequestBuilder.verified.cs
@@ -0,0 +1,124 @@
+//
+#pragma warning disable CS0618
+using Microsoft.Kiota.Abstractions.Extensions;
+using Microsoft.Kiota.Abstractions.Serialization;
+using Microsoft.Kiota.Abstractions;
+using Swashbuckle.AspNetCore.IntegrationTests.KiotaTests.Models;
+using System.Collections.Generic;
+using System.IO;
+using System.Threading.Tasks;
+using System.Threading;
+using System;
+namespace Swashbuckle.AspNetCore.IntegrationTests.KiotaTests.Resources.Item
+{
+ ///
+ /// Builds and executes requests for operations under \resources\{id}
+ ///
+ [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")]
+ public partial class ResourcesItemRequestBuilder : BaseRequestBuilder
+ {
+ ///
+ /// Instantiates a new and sets the default values.
+ ///
+ /// Path parameters for the request
+ /// The request adapter to use to execute the requests.
+ public ResourcesItemRequestBuilder(Dictionary pathParameters, IRequestAdapter requestAdapter) : base(requestAdapter, "{+baseurl}/resources/{id}", pathParameters)
+ {
+ }
+ ///
+ /// Instantiates a new and sets the default values.
+ ///
+ /// The raw URL to use for the request builder.
+ /// The request adapter to use to execute the requests.
+ public ResourcesItemRequestBuilder(string rawUrl, IRequestAdapter requestAdapter) : base(requestAdapter, "{+baseurl}/resources/{id}", rawUrl)
+ {
+ }
+ /// A
+ /// Cancellation token to use when cancelling requests
+ /// Configuration for the request such as headers, query parameters, and middleware options.
+#if NETSTANDARD2_1_OR_GREATER || NETCOREAPP3_1_OR_GREATER
+#nullable enable
+ public async Task DeleteAsync(Action>? requestConfiguration = default, CancellationToken cancellationToken = default)
+ {
+#nullable restore
+#else
+ public async Task DeleteAsync(Action> requestConfiguration = default, CancellationToken cancellationToken = default)
+ {
+#endif
+ var requestInfo = ToDeleteRequestInformation(requestConfiguration);
+ return await RequestAdapter.SendPrimitiveAsync(requestInfo, default, cancellationToken).ConfigureAwait(false);
+ }
+ /// A
+ /// Cancellation token to use when cancelling requests
+ /// Configuration for the request such as headers, query parameters, and middleware options.
+#if NETSTANDARD2_1_OR_GREATER || NETCOREAPP3_1_OR_GREATER
+#nullable enable
+ public async Task GetAsync(Action>? requestConfiguration = default, CancellationToken cancellationToken = default)
+ {
+#nullable restore
+#else
+ public async Task GetAsync(Action> requestConfiguration = default, CancellationToken cancellationToken = default)
+ {
+#endif
+ var requestInfo = ToGetRequestInformation(requestConfiguration);
+ return await RequestAdapter.SendAsync(requestInfo, global::Swashbuckle.AspNetCore.IntegrationTests.KiotaTests.Models.Resource.CreateFromDiscriminatorValue, default, cancellationToken).ConfigureAwait(false);
+ }
+ /// A
+ /// Configuration for the request such as headers, query parameters, and middleware options.
+#if NETSTANDARD2_1_OR_GREATER || NETCOREAPP3_1_OR_GREATER
+#nullable enable
+ public RequestInformation ToDeleteRequestInformation(Action>? requestConfiguration = default)
+ {
+#nullable restore
+#else
+ public RequestInformation ToDeleteRequestInformation(Action> requestConfiguration = default)
+ {
+#endif
+ var requestInfo = new RequestInformation(Method.DELETE, UrlTemplate, PathParameters);
+ requestInfo.Configure(requestConfiguration);
+ return requestInfo;
+ }
+ /// A
+ /// Configuration for the request such as headers, query parameters, and middleware options.
+#if NETSTANDARD2_1_OR_GREATER || NETCOREAPP3_1_OR_GREATER
+#nullable enable
+ public RequestInformation ToGetRequestInformation(Action>? requestConfiguration = default)
+ {
+#nullable restore
+#else
+ public RequestInformation ToGetRequestInformation(Action> requestConfiguration = default)
+ {
+#endif
+ var requestInfo = new RequestInformation(Method.GET, UrlTemplate, PathParameters);
+ requestInfo.Configure(requestConfiguration);
+ requestInfo.Headers.TryAdd("Accept", "application/json, text/plain;q=0.9");
+ return requestInfo;
+ }
+ ///
+ /// Returns a request builder with the provided arbitrary URL. Using this method means any other path or query parameters are ignored.
+ ///
+ /// A
+ /// The raw URL to use for the request builder.
+ public global::Swashbuckle.AspNetCore.IntegrationTests.KiotaTests.Resources.Item.ResourcesItemRequestBuilder WithUrl(string rawUrl)
+ {
+ return new global::Swashbuckle.AspNetCore.IntegrationTests.KiotaTests.Resources.Item.ResourcesItemRequestBuilder(rawUrl, RequestAdapter);
+ }
+ ///
+ /// Configuration for the request such as headers, query parameters, and middleware options.
+ ///
+ [Obsolete("This class is deprecated. Please use the generic RequestConfiguration class generated by the generator.")]
+ [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")]
+ public partial class ResourcesItemRequestBuilderDeleteRequestConfiguration : RequestConfiguration
+ {
+ }
+ ///
+ /// Configuration for the request such as headers, query parameters, and middleware options.
+ ///
+ [Obsolete("This class is deprecated. Please use the generic RequestConfiguration class generated by the generator.")]
+ [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")]
+ public partial class ResourcesItemRequestBuilderGetRequestConfiguration : RequestConfiguration
+ {
+ }
+ }
+}
+#pragma warning restore CS0618
diff --git a/test/Swashbuckle.AspNetCore.IntegrationTests/snapshots/code/GeneratesValidClient_1ea4601ed911b960/Resources/ResourcesRequestBuilder.verified.cs b/test/Swashbuckle.AspNetCore.IntegrationTests/snapshots/code/GeneratesValidClient_1ea4601ed911b960/Resources/ResourcesRequestBuilder.verified.cs
new file mode 100644
index 0000000000..cdd3234b81
--- /dev/null
+++ b/test/Swashbuckle.AspNetCore.IntegrationTests/snapshots/code/GeneratesValidClient_1ea4601ed911b960/Resources/ResourcesRequestBuilder.verified.cs
@@ -0,0 +1,157 @@
+//
+#pragma warning disable CS0618
+using Microsoft.Kiota.Abstractions.Extensions;
+using Microsoft.Kiota.Abstractions.Serialization;
+using Microsoft.Kiota.Abstractions;
+using Swashbuckle.AspNetCore.IntegrationTests.KiotaTests.Models;
+using Swashbuckle.AspNetCore.IntegrationTests.KiotaTests.Resources.Item;
+using System.Collections.Generic;
+using System.IO;
+using System.Threading.Tasks;
+using System.Threading;
+using System;
+namespace Swashbuckle.AspNetCore.IntegrationTests.KiotaTests.Resources
+{
+ ///
+ /// Builds and executes requests for operations under \resources
+ ///
+ [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")]
+ public partial class ResourcesRequestBuilder : BaseRequestBuilder
+ {
+ /// Gets an item from the Swashbuckle.AspNetCore.IntegrationTests.KiotaTests.resources.item collection
+ /// Unique identifier of the item
+ /// A
+ public global::Swashbuckle.AspNetCore.IntegrationTests.KiotaTests.Resources.Item.ResourcesItemRequestBuilder this[int position]
+ {
+ get
+ {
+ var urlTplParams = new Dictionary(PathParameters);
+ urlTplParams.Add("id", position);
+ return new global::Swashbuckle.AspNetCore.IntegrationTests.KiotaTests.Resources.Item.ResourcesItemRequestBuilder(urlTplParams, RequestAdapter);
+ }
+ }
+ /// Gets an item from the Swashbuckle.AspNetCore.IntegrationTests.KiotaTests.resources.item collection
+ /// Unique identifier of the item
+ /// A
+ [Obsolete("This indexer is deprecated and will be removed in the next major version. Use the one with the typed parameter instead.")]
+ public global::Swashbuckle.AspNetCore.IntegrationTests.KiotaTests.Resources.Item.ResourcesItemRequestBuilder this[string position]
+ {
+ get
+ {
+ var urlTplParams = new Dictionary(PathParameters);
+ if (!string.IsNullOrWhiteSpace(position)) urlTplParams.Add("id", position);
+ return new global::Swashbuckle.AspNetCore.IntegrationTests.KiotaTests.Resources.Item.ResourcesItemRequestBuilder(urlTplParams, RequestAdapter);
+ }
+ }
+ ///
+ /// Instantiates a new and sets the default values.
+ ///
+ /// Path parameters for the request
+ /// The request adapter to use to execute the requests.
+ public ResourcesRequestBuilder(Dictionary pathParameters, IRequestAdapter requestAdapter) : base(requestAdapter, "{+baseurl}/resources", pathParameters)
+ {
+ }
+ ///
+ /// Instantiates a new and sets the default values.
+ ///
+ /// The raw URL to use for the request builder.
+ /// The request adapter to use to execute the requests.
+ public ResourcesRequestBuilder(string rawUrl, IRequestAdapter requestAdapter) : base(requestAdapter, "{+baseurl}/resources", rawUrl)
+ {
+ }
+ /// A List<global::Swashbuckle.AspNetCore.IntegrationTests.KiotaTests.Models.Resource>
+ /// Cancellation token to use when cancelling requests
+ /// Configuration for the request such as headers, query parameters, and middleware options.
+#if NETSTANDARD2_1_OR_GREATER || NETCOREAPP3_1_OR_GREATER
+#nullable enable
+ public async Task?> GetAsync(Action>? requestConfiguration = default, CancellationToken cancellationToken = default)
+ {
+#nullable restore
+#else
+ public async Task> GetAsync(Action> requestConfiguration = default, CancellationToken cancellationToken = default)
+ {
+#endif
+ var requestInfo = ToGetRequestInformation(requestConfiguration);
+ var collectionResult = await RequestAdapter.SendCollectionAsync(requestInfo, global::Swashbuckle.AspNetCore.IntegrationTests.KiotaTests.Models.Resource.CreateFromDiscriminatorValue, default, cancellationToken).ConfigureAwait(false);
+ return collectionResult?.AsList();
+ }
+ /// A
+ /// The request body
+ /// Cancellation token to use when cancelling requests
+ /// Configuration for the request such as headers, query parameters, and middleware options.
+#if NETSTANDARD2_1_OR_GREATER || NETCOREAPP3_1_OR_GREATER
+#nullable enable
+ public async Task PostAsync(global::Swashbuckle.AspNetCore.IntegrationTests.KiotaTests.Models.Resource body, Action>? requestConfiguration = default, CancellationToken cancellationToken = default)
+ {
+#nullable restore
+#else
+ public async Task PostAsync(global::Swashbuckle.AspNetCore.IntegrationTests.KiotaTests.Models.Resource body, Action> requestConfiguration = default, CancellationToken cancellationToken = default)
+ {
+#endif
+ if(ReferenceEquals(body, null)) throw new ArgumentNullException(nameof(body));
+ var requestInfo = ToPostRequestInformation(body, requestConfiguration);
+ return await RequestAdapter.SendAsync(requestInfo, global::Swashbuckle.AspNetCore.IntegrationTests.KiotaTests.Models.Resource.CreateFromDiscriminatorValue, default, cancellationToken).ConfigureAwait(false);
+ }
+ /// A
+ /// Configuration for the request such as headers, query parameters, and middleware options.
+#if NETSTANDARD2_1_OR_GREATER || NETCOREAPP3_1_OR_GREATER
+#nullable enable
+ public RequestInformation ToGetRequestInformation(Action>? requestConfiguration = default)
+ {
+#nullable restore
+#else
+ public RequestInformation ToGetRequestInformation(Action> requestConfiguration = default)
+ {
+#endif
+ var requestInfo = new RequestInformation(Method.GET, UrlTemplate, PathParameters);
+ requestInfo.Configure(requestConfiguration);
+ requestInfo.Headers.TryAdd("Accept", "text/plain;q=0.9");
+ return requestInfo;
+ }
+ /// A
+ /// The request body
+ /// Configuration for the request such as headers, query parameters, and middleware options.
+#if NETSTANDARD2_1_OR_GREATER || NETCOREAPP3_1_OR_GREATER
+#nullable enable
+ public RequestInformation ToPostRequestInformation(global::Swashbuckle.AspNetCore.IntegrationTests.KiotaTests.Models.Resource body, Action>? requestConfiguration = default)
+ {
+#nullable restore
+#else
+ public RequestInformation ToPostRequestInformation(global::Swashbuckle.AspNetCore.IntegrationTests.KiotaTests.Models.Resource body, Action> requestConfiguration = default)
+ {
+#endif
+ if(ReferenceEquals(body, null)) throw new ArgumentNullException(nameof(body));
+ var requestInfo = new RequestInformation(Method.POST, UrlTemplate, PathParameters);
+ requestInfo.Configure(requestConfiguration);
+ requestInfo.Headers.TryAdd("Accept", "application/json, text/plain;q=0.9");
+ requestInfo.SetContentFromParsable(RequestAdapter, "application/json", body);
+ return requestInfo;
+ }
+ ///
+ /// Returns a request builder with the provided arbitrary URL. Using this method means any other path or query parameters are ignored.
+ ///
+ /// A
+ /// The raw URL to use for the request builder.
+ public global::Swashbuckle.AspNetCore.IntegrationTests.KiotaTests.Resources.ResourcesRequestBuilder WithUrl(string rawUrl)
+ {
+ return new global::Swashbuckle.AspNetCore.IntegrationTests.KiotaTests.Resources.ResourcesRequestBuilder(rawUrl, RequestAdapter);
+ }
+ ///
+ /// Configuration for the request such as headers, query parameters, and middleware options.
+ ///
+ [Obsolete("This class is deprecated. Please use the generic RequestConfiguration class generated by the generator.")]
+ [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")]
+ public partial class ResourcesRequestBuilderGetRequestConfiguration : RequestConfiguration
+ {
+ }
+ ///
+ /// Configuration for the request such as headers, query parameters, and middleware options.
+ ///
+ [Obsolete("This class is deprecated. Please use the generic RequestConfiguration class generated by the generator.")]
+ [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")]
+ public partial class ResourcesRequestBuilderPostRequestConfiguration : RequestConfiguration
+ {
+ }
+ }
+}
+#pragma warning restore CS0618
diff --git a/test/Swashbuckle.AspNetCore.IntegrationTests/snapshots/code/GeneratesValidClient_b3a89011d8f70304/NSwagOpenApiClient.verified.cs b/test/Swashbuckle.AspNetCore.IntegrationTests/snapshots/code/GeneratesValidClient_b3a89011d8f70304/NSwagOpenApiClient.verified.cs
new file mode 100644
index 0000000000..f4ee7a46d9
--- /dev/null
+++ b/test/Swashbuckle.AspNetCore.IntegrationTests/snapshots/code/GeneratesValidClient_b3a89011d8f70304/NSwagOpenApiClient.verified.cs
@@ -0,0 +1,626 @@
+//----------------------
+//
+// Generated using the NSwag toolchain
+//
+//----------------------
+
+#pragma warning disable 108 // Disable "CS0108 '{derivedDto}.ToJson()' hides inherited member '{dtoBase}.ToJson()'. Use the new keyword if hiding was intended."
+#pragma warning disable 114 // Disable "CS0114 '{derivedDto}.RaisePropertyChanged(String)' hides inherited member 'dtoBase.RaisePropertyChanged(String)'. To make the current member override that implementation, add the override keyword. Otherwise add the new keyword."
+#pragma warning disable 472 // Disable "CS0472 The result of the expression is always 'false' since a value of type 'Int32' is never equal to 'null' of type 'Int32?'
+#pragma warning disable 612 // Disable "CS0612 '...' is obsolete"
+#pragma warning disable 649 // Disable "CS0649 Field is never assigned to, and will always have its default value null"
+#pragma warning disable 1573 // Disable "CS1573 Parameter '...' has no matching param tag in the XML comment for ...
+#pragma warning disable 1591 // Disable "CS1591 Missing XML comment for publicly visible type or member ..."
+#pragma warning disable 8073 // Disable "CS8073 The result of the expression is always 'false' since a value of type 'T' is never equal to 'null' of type 'T?'"
+#pragma warning disable 3016 // Disable "CS3016 Arrays as attribute arguments is not CLS-compliant"
+#pragma warning disable 8600 // Disable "CS8600 Converting null literal or possible null value to non-nullable type"
+#pragma warning disable 8602 // Disable "CS8602 Dereference of a possibly null reference"
+#pragma warning disable 8603 // Disable "CS8603 Possible null reference return"
+#pragma warning disable 8604 // Disable "CS8604 Possible null reference argument for parameter"
+#pragma warning disable 8625 // Disable "CS8625 Cannot convert null literal to non-nullable reference type"
+#pragma warning disable 8765 // Disable "CS8765 Nullability of type of parameter doesn't match overridden member (possibly because of nullability attributes)."
+
+namespace Swashbuckle.AspNetCore.IntegrationTests.NSwagTests
+{
+ using System = global::System;
+
+ [GeneratedCode]
+ public partial class NSwagOpenApiClient
+ {
+ #pragma warning disable 8618
+ private string _baseUrl;
+ #pragma warning restore 8618
+
+ private System.Net.Http.HttpClient _httpClient;
+ private static System.Lazy _settings = new System.Lazy(CreateSerializerSettings, true);
+ private Newtonsoft.Json.JsonSerializerSettings _instanceSettings;
+
+ #pragma warning disable CS8618 // Non-nullable field must contain a non-null value when exiting constructor. Consider declaring as nullable.
+ public NSwagOpenApiClient(string baseUrl, System.Net.Http.HttpClient httpClient)
+ #pragma warning restore CS8618 // Non-nullable field must contain a non-null value when exiting constructor. Consider declaring as nullable.
+ {
+ BaseUrl = baseUrl;
+ _httpClient = httpClient;
+ Initialize();
+ }
+
+ private static Newtonsoft.Json.JsonSerializerSettings CreateSerializerSettings()
+ {
+ var settings = new Newtonsoft.Json.JsonSerializerSettings();
+ UpdateJsonSerializerSettings(settings);
+ return settings;
+ }
+
+ public string BaseUrl
+ {
+ get { return _baseUrl; }
+ set
+ {
+ _baseUrl = value;
+ if (!string.IsNullOrEmpty(_baseUrl) && !_baseUrl.EndsWith("/"))
+ _baseUrl += '/';
+ }
+ }
+
+ protected Newtonsoft.Json.JsonSerializerSettings JsonSerializerSettings { get { return _instanceSettings ?? _settings.Value; } }
+
+ static partial void UpdateJsonSerializerSettings(Newtonsoft.Json.JsonSerializerSettings settings);
+
+ partial void Initialize();
+
+ partial void PrepareRequest(System.Net.Http.HttpClient client, System.Net.Http.HttpRequestMessage request, string url);
+ partial void PrepareRequest(System.Net.Http.HttpClient client, System.Net.Http.HttpRequestMessage request, System.Text.StringBuilder urlBuilder);
+ partial void ProcessResponse(System.Net.Http.HttpClient client, System.Net.Http.HttpResponseMessage response);
+
+ /// OK
+ /// A server side error occurred.
+ public virtual System.Threading.Tasks.Task> ResourcesAllAsync()
+ {
+ return ResourcesAllAsync(System.Threading.CancellationToken.None);
+ }
+
+ /// A cancellation token that can be used by other objects or threads to receive notice of cancellation.
+ /// OK
+ /// A server side error occurred.
+ public virtual async System.Threading.Tasks.Task> ResourcesAllAsync(System.Threading.CancellationToken cancellationToken)
+ {
+ var client_ = _httpClient;
+ var disposeClient_ = false;
+ try
+ {
+ using (var request_ = new System.Net.Http.HttpRequestMessage())
+ {
+ request_.Method = new System.Net.Http.HttpMethod("GET");
+ request_.Headers.Accept.Add(System.Net.Http.Headers.MediaTypeWithQualityHeaderValue.Parse("application/json"));
+
+ var urlBuilder_ = new System.Text.StringBuilder();
+ if (!string.IsNullOrEmpty(_baseUrl)) urlBuilder_.Append(_baseUrl);
+ // Operation Path: "resources"
+ urlBuilder_.Append("resources");
+
+ PrepareRequest(client_, request_, urlBuilder_);
+
+ var url_ = urlBuilder_.ToString();
+ request_.RequestUri = new System.Uri(url_, System.UriKind.RelativeOrAbsolute);
+
+ PrepareRequest(client_, request_, url_);
+
+ var response_ = await client_.SendAsync(request_, System.Net.Http.HttpCompletionOption.ResponseHeadersRead, cancellationToken).ConfigureAwait(false);
+ var disposeResponse_ = true;
+ try
+ {
+ var headers_ = new System.Collections.Generic.Dictionary>();
+ foreach (var item_ in response_.Headers)
+ headers_[item_.Key] = item_.Value;
+ if (response_.Content != null && response_.Content.Headers != null)
+ {
+ foreach (var item_ in response_.Content.Headers)
+ headers_[item_.Key] = item_.Value;
+ }
+
+ ProcessResponse(client_, response_);
+
+ var status_ = (int)response_.StatusCode;
+ if (status_ == 200)
+ {
+ var objectResponse_ = await ReadObjectResponseAsync>(response_, headers_, cancellationToken).ConfigureAwait(false);
+ if (objectResponse_.Object == null)
+ {
+ throw new ApiException("Response was null which was not expected.", status_, objectResponse_.Text, headers_, null);
+ }
+ return objectResponse_.Object;
+ }
+ else
+ {
+ var responseData_ = response_.Content == null ? null : await ReadAsStringAsync(response_.Content, cancellationToken).ConfigureAwait(false);
+ throw new ApiException("The HTTP status code of the response was not expected (" + status_ + ").", status_, responseData_, headers_, null);
+ }
+ }
+ finally
+ {
+ if (disposeResponse_)
+ response_.Dispose();
+ }
+ }
+ }
+ finally
+ {
+ if (disposeClient_)
+ client_.Dispose();
+ }
+ }
+
+ /// OK
+ /// A server side error occurred.
+ public virtual System.Threading.Tasks.Task ResourcesPOSTAsync(Resource body)
+ {
+ return ResourcesPOSTAsync(body, System.Threading.CancellationToken.None);
+ }
+
+ /// A cancellation token that can be used by other objects or threads to receive notice of cancellation.
+ /// OK
+ /// A server side error occurred.
+ public virtual async System.Threading.Tasks.Task ResourcesPOSTAsync(Resource body, System.Threading.CancellationToken cancellationToken)
+ {
+ var client_ = _httpClient;
+ var disposeClient_ = false;
+ try
+ {
+ using (var request_ = new System.Net.Http.HttpRequestMessage())
+ {
+ var json_ = Newtonsoft.Json.JsonConvert.SerializeObject(body, JsonSerializerSettings);
+ var content_ = new System.Net.Http.StringContent(json_);
+ content_.Headers.ContentType = System.Net.Http.Headers.MediaTypeHeaderValue.Parse("application/json");
+ request_.Content = content_;
+ request_.Method = new System.Net.Http.HttpMethod("POST");
+ request_.Headers.Accept.Add(System.Net.Http.Headers.MediaTypeWithQualityHeaderValue.Parse("application/json"));
+
+ var urlBuilder_ = new System.Text.StringBuilder();
+ if (!string.IsNullOrEmpty(_baseUrl)) urlBuilder_.Append(_baseUrl);
+ // Operation Path: "resources"
+ urlBuilder_.Append("resources");
+
+ PrepareRequest(client_, request_, urlBuilder_);
+
+ var url_ = urlBuilder_.ToString();
+ request_.RequestUri = new System.Uri(url_, System.UriKind.RelativeOrAbsolute);
+
+ PrepareRequest(client_, request_, url_);
+
+ var response_ = await client_.SendAsync(request_, System.Net.Http.HttpCompletionOption.ResponseHeadersRead, cancellationToken).ConfigureAwait(false);
+ var disposeResponse_ = true;
+ try
+ {
+ var headers_ = new System.Collections.Generic.Dictionary>();
+ foreach (var item_ in response_.Headers)
+ headers_[item_.Key] = item_.Value;
+ if (response_.Content != null && response_.Content.Headers != null)
+ {
+ foreach (var item_ in response_.Content.Headers)
+ headers_[item_.Key] = item_.Value;
+ }
+
+ ProcessResponse(client_, response_);
+
+ var status_ = (int)response_.StatusCode;
+ if (status_ == 200)
+ {
+ var objectResponse_ = await ReadObjectResponseAsync(response_, headers_, cancellationToken).ConfigureAwait(false);
+ if (objectResponse_.Object == null)
+ {
+ throw new ApiException("Response was null which was not expected.", status_, objectResponse_.Text, headers_, null);
+ }
+ return objectResponse_.Object;
+ }
+ else
+ if (status_ == 401)
+ {
+ string responseText_ = ( response_.Content == null ) ? string.Empty : await ReadAsStringAsync(response_.Content, cancellationToken).ConfigureAwait(false);
+ throw new ApiException("Unauthorized", status_, responseText_, headers_, null);
+ }
+ else
+ if (status_ == 403)
+ {
+ string responseText_ = ( response_.Content == null ) ? string.Empty : await ReadAsStringAsync(response_.Content, cancellationToken).ConfigureAwait(false);
+ throw new ApiException("Forbidden", status_, responseText_, headers_, null);
+ }
+ else
+ {
+ var responseData_ = response_.Content == null ? null : await ReadAsStringAsync(response_.Content, cancellationToken).ConfigureAwait(false);
+ throw new ApiException("The HTTP status code of the response was not expected (" + status_ + ").", status_, responseData_, headers_, null);
+ }
+ }
+ finally
+ {
+ if (disposeResponse_)
+ response_.Dispose();
+ }
+ }
+ }
+ finally
+ {
+ if (disposeClient_)
+ client_.Dispose();
+ }
+ }
+
+ /// OK
+ /// A server side error occurred.
+ public virtual System.Threading.Tasks.Task ResourcesGETAsync(int id)
+ {
+ return ResourcesGETAsync(id, System.Threading.CancellationToken.None);
+ }
+
+ /// A cancellation token that can be used by other objects or threads to receive notice of cancellation.
+ /// OK
+ /// A server side error occurred.
+ public virtual async System.Threading.Tasks.Task ResourcesGETAsync(int id, System.Threading.CancellationToken cancellationToken)
+ {
+ if (id == null)
+ throw new System.ArgumentNullException("id");
+
+ var client_ = _httpClient;
+ var disposeClient_ = false;
+ try
+ {
+ using (var request_ = new System.Net.Http.HttpRequestMessage())
+ {
+ request_.Method = new System.Net.Http.HttpMethod("GET");
+ request_.Headers.Accept.Add(System.Net.Http.Headers.MediaTypeWithQualityHeaderValue.Parse("application/json"));
+
+ var urlBuilder_ = new System.Text.StringBuilder();
+ if (!string.IsNullOrEmpty(_baseUrl)) urlBuilder_.Append(_baseUrl);
+ // Operation Path: "resources/{id}"
+ urlBuilder_.Append("resources/");
+ urlBuilder_.Append(System.Uri.EscapeDataString(ConvertToString(id, System.Globalization.CultureInfo.InvariantCulture)));
+
+ PrepareRequest(client_, request_, urlBuilder_);
+
+ var url_ = urlBuilder_.ToString();
+ request_.RequestUri = new System.Uri(url_, System.UriKind.RelativeOrAbsolute);
+
+ PrepareRequest(client_, request_, url_);
+
+ var response_ = await client_.SendAsync(request_, System.Net.Http.HttpCompletionOption.ResponseHeadersRead, cancellationToken).ConfigureAwait(false);
+ var disposeResponse_ = true;
+ try
+ {
+ var headers_ = new System.Collections.Generic.Dictionary>();
+ foreach (var item_ in response_.Headers)
+ headers_[item_.Key] = item_.Value;
+ if (response_.Content != null && response_.Content.Headers != null)
+ {
+ foreach (var item_ in response_.Content.Headers)
+ headers_[item_.Key] = item_.Value;
+ }
+
+ ProcessResponse(client_, response_);
+
+ var status_ = (int)response_.StatusCode;
+ if (status_ == 200)
+ {
+ var objectResponse_ = await ReadObjectResponseAsync(response_, headers_, cancellationToken).ConfigureAwait(false);
+ if (objectResponse_.Object == null)
+ {
+ throw new ApiException("Response was null which was not expected.", status_, objectResponse_.Text, headers_, null);
+ }
+ return objectResponse_.Object;
+ }
+ else
+ if (status_ == 401)
+ {
+ string responseText_ = ( response_.Content == null ) ? string.Empty : await ReadAsStringAsync(response_.Content, cancellationToken).ConfigureAwait(false);
+ throw new ApiException("Unauthorized", status_, responseText_, headers_, null);
+ }
+ else
+ if (status_ == 403)
+ {
+ string responseText_ = ( response_.Content == null ) ? string.Empty : await ReadAsStringAsync(response_.Content, cancellationToken).ConfigureAwait(false);
+ throw new ApiException("Forbidden", status_, responseText_, headers_, null);
+ }
+ else
+ {
+ var responseData_ = response_.Content == null ? null : await ReadAsStringAsync(response_.Content, cancellationToken).ConfigureAwait(false);
+ throw new ApiException("The HTTP status code of the response was not expected (" + status_ + ").", status_, responseData_, headers_, null);
+ }
+ }
+ finally
+ {
+ if (disposeResponse_)
+ response_.Dispose();
+ }
+ }
+ }
+ finally
+ {
+ if (disposeClient_)
+ client_.Dispose();
+ }
+ }
+
+ /// OK
+ /// A server side error occurred.
+ public virtual System.Threading.Tasks.Task ResourcesDELETEAsync(int id)
+ {
+ return ResourcesDELETEAsync(id, System.Threading.CancellationToken.None);
+ }
+
+ /// A cancellation token that can be used by other objects or threads to receive notice of cancellation.
+ /// OK
+ /// A server side error occurred.
+ public virtual async System.Threading.Tasks.Task ResourcesDELETEAsync(int id, System.Threading.CancellationToken cancellationToken)
+ {
+ if (id == null)
+ throw new System.ArgumentNullException("id");
+
+ var client_ = _httpClient;
+ var disposeClient_ = false;
+ try
+ {
+ using (var request_ = new System.Net.Http.HttpRequestMessage())
+ {
+ request_.Method = new System.Net.Http.HttpMethod("DELETE");
+
+ var urlBuilder_ = new System.Text.StringBuilder();
+ if (!string.IsNullOrEmpty(_baseUrl)) urlBuilder_.Append(_baseUrl);
+ // Operation Path: "resources/{id}"
+ urlBuilder_.Append("resources/");
+ urlBuilder_.Append(System.Uri.EscapeDataString(ConvertToString(id, System.Globalization.CultureInfo.InvariantCulture)));
+
+ PrepareRequest(client_, request_, urlBuilder_);
+
+ var url_ = urlBuilder_.ToString();
+ request_.RequestUri = new System.Uri(url_, System.UriKind.RelativeOrAbsolute);
+
+ PrepareRequest(client_, request_, url_);
+
+ var response_ = await client_.SendAsync(request_, System.Net.Http.HttpCompletionOption.ResponseHeadersRead, cancellationToken).ConfigureAwait(false);
+ var disposeResponse_ = true;
+ try
+ {
+ var headers_ = new System.Collections.Generic.Dictionary>();
+ foreach (var item_ in response_.Headers)
+ headers_[item_.Key] = item_.Value;
+ if (response_.Content != null && response_.Content.Headers != null)
+ {
+ foreach (var item_ in response_.Content.Headers)
+ headers_[item_.Key] = item_.Value;
+ }
+
+ ProcessResponse(client_, response_);
+
+ var status_ = (int)response_.StatusCode;
+ if (status_ == 200)
+ {
+ return;
+ }
+ else
+ if (status_ == 401)
+ {
+ string responseText_ = ( response_.Content == null ) ? string.Empty : await ReadAsStringAsync(response_.Content, cancellationToken).ConfigureAwait(false);
+ throw new ApiException("Unauthorized", status_, responseText_, headers_, null);
+ }
+ else
+ if (status_ == 403)
+ {
+ string responseText_ = ( response_.Content == null ) ? string.Empty : await ReadAsStringAsync(response_.Content, cancellationToken).ConfigureAwait(false);
+ throw new ApiException("Forbidden", status_, responseText_, headers_, null);
+ }
+ else
+ {
+ var responseData_ = response_.Content == null ? null : await ReadAsStringAsync(response_.Content, cancellationToken).ConfigureAwait(false);
+ throw new ApiException("The HTTP status code of the response was not expected (" + status_ + ").", status_, responseData_, headers_, null);
+ }
+ }
+ finally
+ {
+ if (disposeResponse_)
+ response_.Dispose();
+ }
+ }
+ }
+ finally
+ {
+ if (disposeClient_)
+ client_.Dispose();
+ }
+ }
+
+ protected struct ObjectResponseResult
+ {
+ public ObjectResponseResult(T responseObject, string responseText)
+ {
+ this.Object = responseObject;
+ this.Text = responseText;
+ }
+
+ public T Object { get; }
+
+ public string Text { get; }
+ }
+
+ [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)]
+ private static System.Threading.Tasks.Task ReadAsStringAsync(System.Net.Http.HttpContent content, System.Threading.CancellationToken cancellationToken)
+ {
+ #if NET5_0_OR_GREATER
+ return content.ReadAsStringAsync(cancellationToken);
+ #else
+ return content.ReadAsStringAsync();
+ #endif
+ }
+
+ [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)]
+ private static System.Threading.Tasks.Task ReadAsStreamAsync(System.Net.Http.HttpContent content, System.Threading.CancellationToken cancellationToken)
+ {
+ #if NET5_0_OR_GREATER
+ return content.ReadAsStreamAsync(cancellationToken);
+ #else
+ return content.ReadAsStreamAsync();
+ #endif
+ }
+
+ public bool ReadResponseAsString { get; set; }
+
+ protected virtual async System.Threading.Tasks.Task> ReadObjectResponseAsync(System.Net.Http.HttpResponseMessage response, System.Collections.Generic.IReadOnlyDictionary> headers, System.Threading.CancellationToken cancellationToken)
+ {
+ if (response == null || response.Content == null)
+ {
+ return new ObjectResponseResult(default(T), string.Empty);
+ }
+
+ if (ReadResponseAsString)
+ {
+ var responseText = await ReadAsStringAsync(response.Content, cancellationToken).ConfigureAwait(false);
+ try
+ {
+ var typedBody = Newtonsoft.Json.JsonConvert.DeserializeObject(responseText, JsonSerializerSettings);
+ return new ObjectResponseResult(typedBody, responseText);
+ }
+ catch (Newtonsoft.Json.JsonException exception)
+ {
+ var message = "Could not deserialize the response body string as " + typeof(T).FullName + ".";
+ throw new ApiException(message, (int)response.StatusCode, responseText, headers, exception);
+ }
+ }
+ else
+ {
+ try
+ {
+ using (var responseStream = await ReadAsStreamAsync(response.Content, cancellationToken).ConfigureAwait(false))
+ using (var streamReader = new System.IO.StreamReader(responseStream))
+ using (var jsonTextReader = new Newtonsoft.Json.JsonTextReader(streamReader))
+ {
+ var serializer = Newtonsoft.Json.JsonSerializer.Create(JsonSerializerSettings);
+ var typedBody = serializer.Deserialize(jsonTextReader);
+ return new ObjectResponseResult(typedBody, string.Empty);
+ }
+ }
+ catch (Newtonsoft.Json.JsonException exception)
+ {
+ var message = "Could not deserialize the response body stream as " + typeof(T).FullName + ".";
+ throw new ApiException(message, (int)response.StatusCode, string.Empty, headers, exception);
+ }
+ }
+ }
+
+ private string ConvertToString(object value, System.Globalization.CultureInfo cultureInfo)
+ {
+ if (value == null)
+ {
+ return "";
+ }
+
+ if (value is System.Enum)
+ {
+ var name = System.Enum.GetName(value.GetType(), value);
+ if (name != null)
+ {
+ var field_ = System.Reflection.IntrospectionExtensions.GetTypeInfo(value.GetType()).GetDeclaredField(name);
+ if (field_ != null)
+ {
+ var attribute = System.Reflection.CustomAttributeExtensions.GetCustomAttribute(field_, typeof(System.Runtime.Serialization.EnumMemberAttribute))
+ as System.Runtime.Serialization.EnumMemberAttribute;
+ if (attribute != null)
+ {
+ return attribute.Value != null ? attribute.Value : name;
+ }
+ }
+
+ var converted = System.Convert.ToString(System.Convert.ChangeType(value, System.Enum.GetUnderlyingType(value.GetType()), cultureInfo));
+ return converted == null ? string.Empty : converted;
+ }
+ }
+ else if (value is bool)
+ {
+ return System.Convert.ToString((bool)value, cultureInfo).ToLowerInvariant();
+ }
+ else if (value is byte[])
+ {
+ return System.Convert.ToBase64String((byte[]) value);
+ }
+ else if (value is string[])
+ {
+ return string.Join(",", (string[])value);
+ }
+ else if (value.GetType().IsArray)
+ {
+ var valueArray = (System.Array)value;
+ var valueTextArray = new string[valueArray.Length];
+ for (var i = 0; i < valueArray.Length; i++)
+ {
+ valueTextArray[i] = ConvertToString(valueArray.GetValue(i), cultureInfo);
+ }
+ return string.Join(",", valueTextArray);
+ }
+
+ var result = System.Convert.ToString(value, cultureInfo);
+ return result == null ? "" : result;
+ }
+ }
+
+ [GeneratedCode]
+ public partial class Resource
+ {
+
+ [Newtonsoft.Json.JsonProperty("id", Required = Newtonsoft.Json.Required.DisallowNull, NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)]
+ public int Id { get; set; }
+
+ [Newtonsoft.Json.JsonProperty("name", Required = Newtonsoft.Json.Required.Default, NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)]
+ public string Name { get; set; }
+
+ }
+
+
+
+ [GeneratedCode]
+ public partial class ApiException : System.Exception
+ {
+ public int StatusCode { get; private set; }
+
+ public string Response { get; private set; }
+
+ public System.Collections.Generic.IReadOnlyDictionary> Headers { get; private set; }
+
+ public ApiException(string message, int statusCode, string response, System.Collections.Generic.IReadOnlyDictionary> headers, System.Exception innerException)
+ : base(message + "\n\nStatus: " + statusCode + "\nResponse: \n" + ((response == null) ? "(null)" : response.Substring(0, response.Length >= 512 ? 512 : response.Length)), innerException)
+ {
+ StatusCode = statusCode;
+ Response = response;
+ Headers = headers;
+ }
+
+ public override string ToString()
+ {
+ return string.Format("HTTP Response: \n\n{0}\n\n{1}", Response, base.ToString());
+ }
+ }
+
+ [GeneratedCode]
+ public partial class ApiException : ApiException
+ {
+ public TResult Result { get; private set; }
+
+ public ApiException(string message, int statusCode, string response, System.Collections.Generic.IReadOnlyDictionary> headers, TResult result, System.Exception innerException)
+ : base(message, statusCode, response, headers, innerException)
+ {
+ Result = result;
+ }
+ }
+
+}
+
+#pragma warning restore 108
+#pragma warning restore 114
+#pragma warning restore 472
+#pragma warning restore 612
+#pragma warning restore 649
+#pragma warning restore 1573
+#pragma warning restore 1591
+#pragma warning restore 8073
+#pragma warning restore 3016
+#pragma warning restore 8600
+#pragma warning restore 8602
+#pragma warning restore 8603
+#pragma warning restore 8604
+#pragma warning restore 8625
+#pragma warning restore 8765
\ No newline at end of file
diff --git a/test/WebSites/Authorization/Authorization.csproj b/test/WebSites/Authorization/Authorization.csproj
new file mode 100644
index 0000000000..8b44ca1b9d
--- /dev/null
+++ b/test/WebSites/Authorization/Authorization.csproj
@@ -0,0 +1,12 @@
+
+
+
+ $(DefaultTargetFrameworks)
+
+
+
+
+
+
+
+
diff --git a/test/WebSites/Authorization/Controllers/ResourcesController.cs b/test/WebSites/Authorization/Controllers/ResourcesController.cs
new file mode 100644
index 0000000000..cc6460ae36
--- /dev/null
+++ b/test/WebSites/Authorization/Controllers/ResourcesController.cs
@@ -0,0 +1,41 @@
+using Microsoft.AspNetCore.Authorization;
+using Microsoft.AspNetCore.Mvc;
+
+namespace Authorization.Controllers;
+
+[Route("resources")]
+public class ResourcesController : Controller
+{
+ [HttpGet]
+ public IEnumerable GetAll()
+ {
+ return [new Resource { Id = 1, Name = "Public Resource" }];
+ }
+
+ [HttpGet("{id}")]
+ [Authorize(Policy = "readAccess")]
+ public Resource GetById(int id)
+ {
+ return new Resource { Id = id, Name = "Protected Resource" };
+ }
+
+ [HttpPost]
+ [Authorize(Policy = "writeAccess")]
+ public Resource Create([FromBody] Resource resource)
+ {
+ return resource;
+ }
+
+ [HttpDelete("{id}")]
+ [Authorize(Policy = "writeAccess")]
+ public void Delete(int id)
+ {
+ }
+}
+
+public class Resource
+{
+ public int Id { get; set; }
+
+ public string Name { get; set; }
+}
diff --git a/test/WebSites/Authorization/Program.cs b/test/WebSites/Authorization/Program.cs
new file mode 100644
index 0000000000..20168cf387
--- /dev/null
+++ b/test/WebSites/Authorization/Program.cs
@@ -0,0 +1,50 @@
+using System.Security.Claims;
+using Authorization.Swagger;
+using Microsoft.OpenApi;
+
+var builder = WebApplication.CreateBuilder(args);
+
+builder.Services.AddControllers();
+
+builder.Services.AddAuthorization(options =>
+{
+ options.AddPolicy("readAccess", policy =>
+ policy.RequireClaim(ClaimTypes.Role, "Reader", "Administrator"));
+
+ options.AddPolicy("writeAccess", policy =>
+ policy.RequireClaim(ClaimTypes.Role, "Administrator"));
+});
+
+builder.Services.AddSwaggerGen(c =>
+{
+ c.SwaggerDoc("v1", new OpenApiInfo
+ {
+ Title = "Authorization API",
+ Version = "v1"
+ });
+
+ c.AddSecurityDefinition("bearer", new OpenApiSecurityScheme
+ {
+ Type = SecuritySchemeType.Http,
+ Scheme = "bearer",
+ BearerFormat = "JWT"
+ });
+
+ c.OperationAsyncFilter();
+});
+
+var app = builder.Build();
+
+app.UseAuthorization();
+
+app.MapControllers();
+app.MapSwagger("swagger/{documentName}/swagger.json");
+
+app.Run();
+
+namespace Authorization
+{
+ public partial class Program
+ {
+ }
+}
diff --git a/test/WebSites/Authorization/Swagger/SecurityRequirementsAsyncOperationFilter.cs b/test/WebSites/Authorization/Swagger/SecurityRequirementsAsyncOperationFilter.cs
new file mode 100644
index 0000000000..0605e430c8
--- /dev/null
+++ b/test/WebSites/Authorization/Swagger/SecurityRequirementsAsyncOperationFilter.cs
@@ -0,0 +1,65 @@
+using System.Security.Claims;
+using Microsoft.AspNetCore.Authorization;
+using Microsoft.AspNetCore.Authorization.Infrastructure;
+using Microsoft.OpenApi;
+using Swashbuckle.AspNetCore.SwaggerGen;
+
+namespace Authorization.Swagger;
+
+public class SecurityRequirementsAsyncOperationFilter(IAuthorizationPolicyProvider authorizationPolicyProvider) : IOperationAsyncFilter
+{
+ public async Task ApplyAsync(OpenApiOperation operation, OperationFilterContext context, CancellationToken cancellationToken)
+ {
+ var authorizeAttributes = context.MethodInfo
+ .GetCustomAttributes(true)
+ .Concat(context.MethodInfo.DeclaringType.GetCustomAttributes(true))
+ .OfType()
+ .ToList();
+
+ if (authorizeAttributes.Count == 0)
+ {
+ return;
+ }
+
+ var requiredRoles = new List();
+
+ foreach (var attribute in authorizeAttributes)
+ {
+ if (attribute.Policy == null)
+ {
+ continue;
+ }
+
+ var policy = await authorizationPolicyProvider.GetPolicyAsync(attribute.Policy);
+ if (policy == null)
+ {
+ continue;
+ }
+
+ var roleRequirements = policy.Requirements
+ .OfType()
+ .Where(r => r.ClaimType == ClaimTypes.Role)
+ .SelectMany(r => r.AllowedValues);
+
+ requiredRoles.AddRange(roleRequirements);
+ }
+
+ if (requiredRoles.Count == 0)
+ {
+ return;
+ }
+
+ operation.Responses.Add("401", new OpenApiResponse { Description = "Unauthorized" });
+ operation.Responses.Add("403", new OpenApiResponse { Description = "Forbidden" });
+
+ var scheme = new OpenApiSecuritySchemeReference("bearer", context.Document);
+
+ operation.Security =
+ [
+ new OpenApiSecurityRequirement
+ {
+ [scheme] = requiredRoles.Distinct().ToList()
+ }
+ ];
+ }
+}