Skip to content

Add aspnet-openapi skill (#dotnet-aspnet)#486

Open
raihanmehran wants to merge 9 commits into
dotnet:mainfrom
raihanmehran:feat/aspnet-openapi-skill
Open

Add aspnet-openapi skill (#dotnet-aspnet)#486
raihanmehran wants to merge 9 commits into
dotnet:mainfrom
raihanmehran:feat/aspnet-openapi-skill

Conversation

@raihanmehran

Copy link
Copy Markdown

Summary

Adds a new aspnet-openapi skill to the dotnet-aspnet plugin covering OpenAPI documentation for ASP.NET Core APIs. This is a high-frequency, high-confusion area, .NET 9 replaced Swashbuckle as the default in project templates, leaving developers with contradictory guidance across tutorials, and the technology-selection and migration decisions are non-obvious without prior experience.

What's included

  • SKILL.md — Full workflow covering:
    • Technology selection: Microsoft.AspNetCore.OpenApi (.NET 9+) vs Swashbuckle vs NSwag, with a clear decision table
    • Setup for both the built-in package and Swashbuckle, including the most common Swashbuckle bug (AddEndpointsApiExplorer() omission)
    • Scalar and Swagger UI setup, with the spec path change called out explicitly
    • Minimal API endpoint annotation (Produces<T>, ProducesProblem, ExcludeFromDescription)
    • JWT Bearer security scheme via IOpenApiDocumentTransformer
    • Securing the spec endpoint in production
  • references/transformers.md — Document, operation, and schema transformer patterns; OAuth2 and API key schemes; Swashbuckle IDocumentFilter/IOperationFilter equivalents
  • references/swashbuckle-migration.md — Step-by-step migration guide from Swashbuckle including filter→transformer mapping, behavioral differences table, and common post-migration failures
  • tests/dotnet-aspnet/aspnet-openapi/eval.yaml — 4 eval scenarios covering basic setup, the Swashbuckle empty-spec gotcha, JWT security scheme configuration, and full Swashbuckle migration

Motivation

dotnet-aspnet currently has a single skill (minimal-api-file-upload). OpenAPI is arguably the most universally needed capability for any HTTP API, every team configures it, and the .NET 9 ecosystem shift means existing documentation and tutorials are inconsistent. This is a clear LLM gap: agents routinely suggest the wrong package for the target framework, omit AddEndpointsApiExplorer(), or produce security scheme configuration that doesn't match the built-in package's transformer API.

Copilot AI review requested due to automatic review settings March 31, 2026 14:55
@raihanmehran

Copy link
Copy Markdown
Author

@dotnet-policy-service agree

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

Adds a new aspnet-openapi skill to the dotnet-aspnet plugin to guide ASP.NET Core OpenAPI setup and migration (built-in Microsoft.AspNetCore.OpenApi vs Swashbuckle/NSwag), with supporting reference docs and eval scenarios.

Changes:

  • Added aspnet-openapi skill documentation with end-to-end setup guidance (Scalar/Swagger UI), endpoint annotation patterns, JWT security scheme via transformers, and production-hardening guidance.
  • Added reference docs covering transformer/filter equivalents and a Swashbuckle→built-in migration walkthrough.
  • Added an eval suite with 4 scenarios to validate common OpenAPI setup/migration behaviors and pitfalls.

Reviewed changes

Copilot reviewed 4 out of 4 changed files in this pull request and generated 3 comments.

File Description
tests/dotnet-aspnet/aspnet-openapi/eval.yaml Adds eval scenarios for built-in OpenAPI + Scalar, Swashbuckle empty-spec pitfall, JWT scheme transformer, and migration flow.
plugins/dotnet-aspnet/skills/aspnet-openapi/SKILL.md New primary skill workflow doc for OpenAPI technology selection, setup, UI integration, transformers, and securing spec endpoints.
plugins/dotnet-aspnet/skills/aspnet-openapi/references/transformers.md Reference patterns for document/operation/schema transformers and Swashbuckle filter equivalents.
plugins/dotnet-aspnet/skills/aspnet-openapi/references/swashbuckle-migration.md Step-by-step migration guide including mapping table and post-migration troubleshooting.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread plugins/dotnet-aspnet/skills/aspnet-openapi/SKILL.md Outdated
Comment thread plugins/dotnet-aspnet/skills/aspnet-openapi/SKILL.md Outdated
Comment thread plugins/dotnet-aspnet/skills/aspnet-openapi/references/swashbuckle-migration.md Outdated

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 4 out of 4 changed files in this pull request and generated 2 comments.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread plugins/dotnet-aspnet/skills/aspnet-openapi/SKILL.md Outdated
- Fully-qualify System.Reflection.Assembly in Swashbuckle XML docs snippet
  (Assembly.GetExecutingAssembly is not in default global usings)
- Add 'using Microsoft.OpenApi.Models' to the transformer registration
  snippet in references/transformers.md (OpenApiContact/OpenApiInfo
  are not in default global usings)
@raihanmehran raihanmehran force-pushed the feat/aspnet-openapi-skill branch from b6cf426 to b4520f2 Compare April 1, 2026 06:54
@raihanmehran

Copy link
Copy Markdown
Author

@copilot review this PR

@AbhitejJohn

AbhitejJohn commented May 22, 2026

Copy link
Copy Markdown
Contributor

Tagging @danroth27 for thoughts on this. Please feel free to loop in anyone else on the team who might be able to help as well.

@danroth27

Copy link
Copy Markdown
Member

Adding @mikekistler @Youssef1313 and @javiercn to take a look.

@mikekistler mikekistler left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Thanks for this submission!

I left comments on a number of small issues that need to be addressed.

Comment on lines +18 to +19
- You need features the built-in package does not yet support (advanced polymorphism,
`oneOf`/`anyOf` discriminators, complex `$ref` scenarios)

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Not sure what this is referring to. Built-in OpenAPI generation supports polymorphism, oneOf and anyOf schemas, and most complex $ref scenarios I'm aware of. I think more specific guidance is needed here.


## Migrate or Stay?

Migration is not mandatory. Swashbuckle continues to work on .NET 9+ with version 7.x.

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

The current latest version of Swashbuckle.AspNetCore is 10.1.7, and has many improvements over v7.x. Is this recommending against using packages more recent than 7.x? Maybe this should say "7.x or later"?

<PackageReference Include="Swashbuckle.AspNetCore" Version="7.*" />

<!-- Add -->
<PackageReference Include="Microsoft.AspNetCore.OpenApi" Version="9.*" />

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Is this skill .NET 9 specific? How do we write this in a way that makes it applicable to .NET 9 and later?

<PackageReference Include="Microsoft.AspNetCore.OpenApi" Version="9.*" />

<!-- If you still want Swagger UI instead of Scalar -->
<PackageReference Include="Swashbuckle.AspNetCore.SwaggerUI" Version="7.*" />

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Here too, I think we should recommend the most recent version of washbuckle.AspNetCore.SwaggerUI.

Maybe we should be recommending a dotnet add package command, rather than specific updates to the csproj, so that the right levels are used automatically.

| `context.ApiDescription` (in `IOperationFilter`) | `context.Description` | Same type: `ApiDescription` |

### XML Documentation Note

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

I think metadata from XML doc comments was not added to ASP.NET Core until .NET 10. I think that should be mentioned here.

Comment on lines +72 to +74
For **minimal APIs**, XML comments on the handler delegate are not picked up
automatically — use `.WithSummary()` and `.WithDescription()` on the endpoint
instead (shown in SKILL.md Step 5). For **MVC controller actions**, XML `<summary>`

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Recommend defining the delegate as a local method, as described above.

Comment on lines +196 to +226
By default, enums serialize as integers in the spec. To represent them as string values:

```csharp
using Microsoft.AspNetCore.OpenApi;
using Microsoft.OpenApi.Any;
using Microsoft.OpenApi.Models;

internal sealed class EnumSchemaTransformer : IOpenApiSchemaTransformer
{
public Task TransformAsync(
OpenApiSchema schema,
OpenApiSchemaTransformerContext context,
CancellationToken cancellationToken)
{
if (context.JsonTypeInfo.Type.IsEnum)
{
schema.Type = "string";
schema.Enum = Enum.GetNames(context.JsonTypeInfo.Type)
.Select(name => new OpenApiString(name))
.Cast<IOpenApiAny>()
.ToList();
}

return Task.CompletedTask;
}
}
```

> This transformer only affects the OpenAPI schema. Ensure your `JsonSerializerOptions`
> (or `System.Text.Json` attributes) are also configured to serialize enums as strings at
> runtime — the spec and the actual wire format must agree.

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Replace this whole section with "use JsonStringEnumConverter.


## Stop Signals

- **Need to generate C# or TypeScript API clients?** — Use NSwag or `dotnet-openapi`. This skill covers spec *generation*, not *consumption*.

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

There are plenty of options for generating clients besides NSwag, for example Kiota, that take OpenAPI as input, so I don't think this is necessarily a "stop signal".

Comment on lines +50 to +51
| Need typed client code generation | `NSwag.AspNetCore` | Only mature option with C#/TypeScript codegen; pair with the spec output |
| Complex polymorphism or discriminators | `NSwag.AspNetCore` | More schema control than either alternative |

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Neither of these cases should recommend against using built-in OpenAPI doc generation.

The spec is only as useful as the metadata you put in. Sparse annotations produce a sparse,
useless spec — and waste the entire investment in Step 2–4.

**Minimal APIs:**

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

This section should show an example with XML doc comments as the source of OpenAPI metadata.

@github-actions

github-actions Bot commented Jun 4, 2026

Copy link
Copy Markdown
Contributor

✅ Automated diff scan completed for efa719c — no security concerns flagged.

This is an automated static analysis of the PR diff.

Note

🔒 Integrity filter blocked 5 items

The following items were blocked because they don't meet the GitHub integrity level.

  • #486 pull_request_read: has lower integrity than agent requires. The agent cannot read data with integrity below "approved".
  • #486 search_pull_requests: has lower integrity than agent requires. The agent cannot read data with integrity below "approved".
  • #273 search_pull_requests: has lower integrity than agent requires. The agent cannot read data with integrity below "approved".
  • Add aspnet-openapi skill (#dotnet-aspnet) #486 pull_request_read: has lower integrity than agent requires. The agent cannot read data with integrity below "approved".
  • efa719c list_commits: has lower integrity than agent requires. The agent cannot read data with integrity below "approved".

To allow these resources, lower min-integrity in your GitHub frontmatter:

tools:
  github:
    min-integrity: approved  # merged | approved | unapproved | none

Generated by PR Malicious Code Scan · ● 872.6K ·

@github-actions

github-actions Bot commented Jun 4, 2026

Copy link
Copy Markdown
Contributor

✅ Automated diff scan completed for efa719c — no security concerns flagged.

This is an automated static analysis of the PR diff.

Note

🔒 Integrity filter blocked 47 items

The following items were blocked because they don't meet the GitHub integrity level.

  • #486 pull_request_read: has lower integrity than agent requires. The agent cannot read data with integrity below "approved".
  • #694 list_pull_requests: has lower integrity than agent requires. The agent cannot read data with integrity below "approved".
  • #686 list_pull_requests: has lower integrity than agent requires. The agent cannot read data with integrity below "approved".
  • #682 list_pull_requests: has lower integrity than agent requires. The agent cannot read data with integrity below "approved".
  • #609 list_pull_requests: has lower integrity than agent requires. The agent cannot read data with integrity below "approved".
  • #607 list_pull_requests: has lower integrity than agent requires. The agent cannot read data with integrity below "approved".
  • #601 list_pull_requests: has lower integrity than agent requires. The agent cannot read data with integrity below "approved".
  • #598 list_pull_requests: has lower integrity than agent requires. The agent cannot read data with integrity below "approved".
  • #502 list_pull_requests: has lower integrity than agent requires. The agent cannot read data with integrity below "approved".
  • #486 list_pull_requests: has lower integrity than agent requires. The agent cannot read data with integrity below "approved".
  • #376 list_pull_requests: has lower integrity than agent requires. The agent cannot read data with integrity below "approved".
  • #329 list_pull_requests: has lower integrity than agent requires. The agent cannot read data with integrity below "approved".
  • #303 list_pull_requests: has lower integrity than agent requires. The agent cannot read data with integrity below "approved".
  • #269 list_pull_requests: has lower integrity than agent requires. The agent cannot read data with integrity below "approved".
  • #267 list_pull_requests: has lower integrity than agent requires. The agent cannot read data with integrity below "approved".
  • #266 list_pull_requests: has lower integrity than agent requires. The agent cannot read data with integrity below "approved".
  • ... and 31 more items

To allow these resources, lower min-integrity in your GitHub frontmatter:

tools:
  github:
    min-integrity: approved  # merged | approved | unapproved | none

Generated by PR Malicious Code Scan · ● 1.1M ·

@github-actions

github-actions Bot commented Jun 4, 2026

Copy link
Copy Markdown
Contributor

✅ Automated diff scan completed for efa719c — no security concerns flagged.

This is an automated static analysis of the PR diff.

Note

🔒 Integrity filter blocked 4 items

The following items were blocked because they don't meet the GitHub integrity level.

  • #486 pull_request_read: has lower integrity than agent requires. The agent cannot read data with integrity below "approved".
  • Add aspnet-openapi skill (#dotnet-aspnet) #486 pull_request_read: has lower integrity than agent requires. The agent cannot read data with integrity below "approved".
  • efa719c list_commits: has lower integrity than agent requires. The agent cannot read data with integrity below "approved".
  • efa719c get_commit: has lower integrity than agent requires. The agent cannot read data with integrity below "approved".

To allow these resources, lower min-integrity in your GitHub frontmatter:

tools:
  github:
    min-integrity: approved  # merged | approved | unapproved | none

Generated by PR Malicious Code Scan · ● 1.2M ·

@github-actions

github-actions Bot commented Jun 4, 2026

Copy link
Copy Markdown
Contributor

✅ Automated diff scan completed for efa719c — no security concerns flagged.

This is an automated static analysis of the PR diff.

Note

🔒 Integrity filter blocked 46 items

The following items were blocked because they don't meet the GitHub integrity level.

  • #486 pull_request_read: has lower integrity than agent requires. The agent cannot read data with integrity below "approved".
  • #694 list_pull_requests: has lower integrity than agent requires. The agent cannot read data with integrity below "approved".
  • #686 list_pull_requests: has lower integrity than agent requires. The agent cannot read data with integrity below "approved".
  • #682 list_pull_requests: has lower integrity than agent requires. The agent cannot read data with integrity below "approved".
  • #609 list_pull_requests: has lower integrity than agent requires. The agent cannot read data with integrity below "approved".
  • #607 list_pull_requests: has lower integrity than agent requires. The agent cannot read data with integrity below "approved".
  • #601 list_pull_requests: has lower integrity than agent requires. The agent cannot read data with integrity below "approved".
  • #598 list_pull_requests: has lower integrity than agent requires. The agent cannot read data with integrity below "approved".
  • #502 list_pull_requests: has lower integrity than agent requires. The agent cannot read data with integrity below "approved".
  • #486 list_pull_requests: has lower integrity than agent requires. The agent cannot read data with integrity below "approved".
  • #376 list_pull_requests: has lower integrity than agent requires. The agent cannot read data with integrity below "approved".
  • #329 list_pull_requests: has lower integrity than agent requires. The agent cannot read data with integrity below "approved".
  • #303 list_pull_requests: has lower integrity than agent requires. The agent cannot read data with integrity below "approved".
  • #269 list_pull_requests: has lower integrity than agent requires. The agent cannot read data with integrity below "approved".
  • #267 list_pull_requests: has lower integrity than agent requires. The agent cannot read data with integrity below "approved".
  • #266 list_pull_requests: has lower integrity than agent requires. The agent cannot read data with integrity below "approved".
  • ... and 30 more items

To allow these resources, lower min-integrity in your GitHub frontmatter:

tools:
  github:
    min-integrity: approved  # merged | approved | unapproved | none

Generated by PR Malicious Code Scan · ● 1.5M ·

builder.Services.AddOpenApi("v2");

// Both served at their named paths: /openapi/v1.json and /openapi/v2.json
app.MapOpenApi("/openapi/{documentName}.json");

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

I think this is already the default.

Suggested change
app.MapOpenApi("/openapi/{documentName}.json");
app.MapOpenApi();

Show me the complete setup using the built-in Microsoft.AspNetCore.OpenApi package
and Scalar UI. Include the NuGet packages I need and the Program.cs changes.
assertions:
- type: "output_matches"

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Can we have stronger assertions. At least validate that dotnet build builds.

MapGet or MapPost endpoints appear. My MVC controllers show up fine.
What's wrong and how do I fix it?
assertions:
- type: "output_contains"

@Youssef1313 Youssef1313 Jun 4, 2026

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Same here about stronger assertions. Basically all scenarios

Comment on lines +4 to +7
I've just created a new ASP.NET Core 9 minimal API project with dotnet new webapi
and I want to add an OpenAPI spec endpoint and an interactive API explorer.
Show me the complete setup using the built-in Microsoft.AspNetCore.OpenApi package
and Scalar UI. Include the NuGet packages I need and the Program.cs changes.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

This prompt will be provided to the agent without having the actual project that the agent should try to update. Is the intent for this test scenario to let the agent really create a new project from scratch?

It looks like all existing scenarios are done this way. Do we want to at least have few scenarios where the agent is given an existing project?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

7 participants