Respect IModelNameProvider when matching OpenAPI parameters#64535
Respect IModelNameProvider when matching OpenAPI parameters#64535khellang wants to merge 14 commits into
Conversation
There was a problem hiding this comment.
Pull request overview
This pull request adds support for respecting IModelNameProvider attributes (like FromQuery(Name = "...")) when matching OpenAPI operation parameters with .NET action parameters for XML comment documentation. This ensures that XML documentation comments are correctly applied to parameters that have custom names specified via model binding attributes.
Key Changes:
- Introduces a new
GetOperationParameterhelper method that considers both the parameter's original name and any custom names fromIModelNameProviderattributes - Adds early null check for
parameterInfobefore attempting to match operation parameters - Updates generated code across all snapshot test files to include the new logic
Reviewed changes
Copilot reviewed 11 out of 11 changed files in this pull request and generated 1 comment.
| File | Description |
|---|---|
| src/OpenApi/gen/XmlCommentGenerator.cs | Adds System.Reflection using statement for ParameterInfo type |
| src/OpenApi/gen/XmlCommentGenerator.Emitter.cs | Implements the core logic for parameter matching with IModelNameProvider support; adds GetOperationParameter helper method and includes Microsoft.AspNetCore.Mvc.ModelBinding namespace |
| src/OpenApi/test/.../snapshots/*.verified.cs | Updates all snapshot test files to reflect the generated code changes from the source generator |
68d5b6f to
16a616e
Compare
16a616e to
d6a6aaa
Compare
| var requestBody = operation.RequestBody; | ||
| if (requestBody is not null) | ||
| { | ||
| requestBody.Description = parameterComment.Description; |
There was a problem hiding this comment.
@captainsafia Do you know why this fallback exists? We're seeing the CancellationToken argument being applied to the request body because of this, which is weird 🤔
There was a problem hiding this comment.
Added a check to skip CancellationToken to avoid applying its XML doc to the request body. I can't see a scenario where you'd ever want to include a cancellation token in your OpenAPI docs 😅
There was a problem hiding this comment.
Ideally, instead of checking against typeof(CancellationToken) directly, it should probably check against the binding source to see if it's BindingSource.Body instead of just blindly falling back to setting the request body description.
BrennanConroy
left a comment
There was a problem hiding this comment.
Could you file a follow-up issue to look at other parameter types besides CancellationToken? e.g. HttpContext, [FromServices], ClaimsPrincipal, etc.
Might want to look at the ApiParameterDescription.BindingSource?
|
Thanks @BrennanConroy! Filed #67076. Can probably take a stab at fixing it as well if no one beats me to it. |
ea84636 to
7e1a640
Compare
|
/azp run |
|
Azure Pipelines successfully started running 2 pipeline(s). |
|
The 2 new tests in src/OpenApi/test/Microsoft.AspNetCore.OpenApi.SourceGenerators.Tests/OperationTests.Controllers.cs failed. I think the verified file(s) need to be regenerated. |
…eter is bound to it This avoids applying documentation for parameters that aren't part of the OpenAPI surface, like CancellationToken or [FromServices] parameters, to the request body description.
7e1a640 to
d97acbe
Compare
|
Rebased and updated the stale snapshots. I also included a commit that checks the |
| { | ||
| var parameterInfo = methodInfo.GetParameters().SingleOrDefault(info => info.Name == parameterComment.Name); | ||
| var operationParameter = operation.Parameters?.SingleOrDefault(parameter => parameter.Name == parameterComment.Name); | ||
| var operationParameter = GetOperationParameter(operation, parameterInfo, parameterComment); |
There was a problem hiding this comment.
Not sure we care too much, but if it's easy to fix could we avoid calling GetModelNames multiple times per parameter?
|
|
||
| foreach (var parameterDescription in context.Description.ParameterDescriptions) | ||
| { | ||
| if (parameterDescription.Source == BindingSource.Body |
There was a problem hiding this comment.
This excludes IFormFile (and other form types) from the description. Should those be excluded?
There was a problem hiding this comment.
But those are bound to the body, right?
There was a problem hiding this comment.
Right, so if there is a description on the form param it should end up as the description in openapi?
#67078 calls this out as well.
| if (XmlCommentCache.Cache.TryGetValue(DocumentationCommentIdHelper.NormalizeDocId(propertyInfo.CreateDocumentationId()), out var propertyComment)) | ||
| { | ||
| var parameter = operation.Parameters?.SingleOrDefault(p => p.Name == metadata.Name); | ||
| var parameter = GetOperationParameter(operation, propertyInfo); |
There was a problem hiding this comment.
Do we need to apply IsRequestBodyParameter to this piece of code as well?
Description
This makes sure any attribute implementing
IModelNameProvideris respected when matching OpenAPI operation parameters with .NET action parameters.It also replaces the
CancellationTokenworkaround from the initial review with a proper check againstBindingSource.Body, so documentation for parameters that aren't part of the OpenAPI surface (e.g.CancellationTokenor[FromServices]parameters) is no longer applied to the request body description.Fixes #64534
Fixes #64521
Fixes #67076