Skip to content

Use IAsyncSwaggerProvider in CLI tofile command#3910

Open
bt-Knodel wants to merge 1 commit intodomaindrivendev:masterfrom
bt-Knodel:cli-async-swagger-provider
Open

Use IAsyncSwaggerProvider in CLI tofile command#3910
bt-Knodel wants to merge 1 commit intodomaindrivendev:masterfrom
bt-Knodel:cli-async-swagger-provider

Conversation

@bt-Knodel
Copy link
Copy Markdown

@bt-Knodel bt-Knodel commented Apr 17, 2026

Summary

The CLI's tofile command resolves ISwaggerProvider and calls the synchronous GetSwagger(), which internally uses GenerateOperation(). This sync path only invokes IOperationFilter registrations — IOperationAsyncFilter registrations are silently skipped.

This means any project using OperationAsyncFilter<T>() gets correct output from the runtime swagger middleware but missing output from dotnet swagger tofile, leading to inconsistencies in generated clients (e.g., via Orval/NSwag).

Changes

  • Make CommandRunner and Program.Main fully async — no sync-over-async (GetAwaiter().GetResult())
  • The _tofile command prefers IAsyncSwaggerProvider.GetSwaggerAsync() when available, falling back to ISwaggerProvider.GetSwagger() for backward compatibility
  • Add Authorization test WebSite demonstrating real-world async filter: SecurityRequirementsAsyncOperationFilter resolves authorization policies via IAuthorizationPolicyProvider.GetPolicyAsync() and adds security requirements to operations
  • Integration test snapshots and CLI test for the new WebSite

Test plan

  • All existing CLI and integration tests pass
  • New Can_Generate_Swagger_Json_With_Async_Operation_Filters test verifies async filter output via CLI
  • New Authorization WebSite validates real-world use case: async operation filter resolves authorization policies via IAuthorizationPolicyProvider.GetPolicyAsync() and documents security requirements on protected endpoints
  • Backward compatible — falls back to sync provider if async provider is not registered

@bt-Knodel
Copy link
Copy Markdown
Author

The issue #1661 appears to have missed the CLI implementation of Swagger. So async filters registered in the application are not called. Happy to adjust based on feedback, but would love to be able to use async policy filters with swagger cli.

Comment thread src/Swashbuckle.AspNetCore.Cli/Program.cs
var host = namedArgs.TryGetValue("--host", out var arg) ? arg : null;
var basePath = namedArgs.TryGetValue("--basepath", out var namedArg) ? namedArg : null;
var swagger = asyncSwaggerProvider != null
? asyncSwaggerProvider.GetSwaggerAsync(namedArgs["swaggerdoc"], host, basePath).GetAwaiter().GetResult()
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is there a way to refactor this code to avoid needing to do GetAwaiter().GetResult()?

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Happy to do the refactor. As a heads up, this will update quite a few tests since it requires converting Main and CommandRunner to async.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pushed conversion to async

@bt-Knodel bt-Knodel force-pushed the cli-async-swagger-provider branch from 71ba7a1 to 2271ae2 Compare April 19, 2026 12:56
Copy link
Copy Markdown
Collaborator

@martincostello martincostello left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just a few small style nits.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As it's new, could you have this use the Minimal APIs startup style please?

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done! Followed the other websites using the partial class pattern to expose Program to tests.

Comment thread test/WebSites/Authorization/Startup.cs Outdated
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

+1 - the Startup logic moved to Program.cs please.

.ToList();

if (authorizeAttributes.Count == 0)
return;
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please add braces to the return/continue usage.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done!

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@bt-Knodel bt-Knodel force-pushed the cli-async-swagger-provider branch from 2271ae2 to 514c304 Compare April 20, 2026 20:23
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants