Automatically create OpenApiParameters when using BindAsync in Minimal API
- Dominant language
- C#
- Stars
- 38.4k
- Forks
- 10.9k
- Avg merge
- 2d 10h
- Merged PRs (30d)
- 281
Description
### Is there an existing issue for this?
- [X] I have searched the existing issues
### Is your feature request related to a problem? Please describe the problem.
I'm trying to migrate my controllers-based project to .NET 7 minimal API.
In the old project, I have multiple custom value providers (FromClaim, FromHeaderPart, etc).
In minimal API we can have custom model binding using [BindAsync](https://learn.microsoft.com/en-us/aspnet/core/fundamentals/minimal-apis/parameter-binding?view=aspnetcore-7.0#bindasync), but when using this approach we don't get any params in SwaggerUI.
To display parameters we must add this code:
```C#
.WithOpenApi(operation =>
{
operation.Parameters.Add(new OpenApiParameter
{
Name = "sortBy",
Schema = new OpenApiSchema
{
Type = "string",
Default = new OpenApiString("")
},
Description = "Sort by",
Required = false,
In = ParameterLocation.Query
});
operation.Parameters.Add(new OpenApiParameter
{
Name = "sortDir",
Schema = new OpenApiSchema
{
Type = "string",
Default = new OpenApiString("asc"),
Enum = new List
{
new OpenApiString("asc"),
new OpenApiString("desc")
}
},
Description = "Sort direction",
Required = true,
In = ParameterLocation.Query
});
operation.Parameters.Add(new OpenApiParameter
{
Name = "page",
Schema = new OpenApiSchema
{
Type = "integer",
Default = new OpenApiInteger(1)
},
Description = "Page number",
Required = true,
In = ParameterLocation.Query
});
return operation;
});
```
Ideally, this should be done automatically based on attributes
### Describe the solution you'd like
Ideally, we should be able to annotate properties that are binding from known places with attributes.
So the above `WithOpenApi` could be omitted and a valid list of parameters would be created automatically.
We could use attributes from `Microsoft.AspNetCore.Mvc` or create new ones if needed.
```C#
public class MyCustomParameters
{
[FromQuery]
public string? SortBy { get; init; }
[FromQuery]
[Required]
public SortDirection Sort { get; init; }
[FromQuery]
[Required]
public int CurrentPage { get; init; } = 1;
public static ValueTask BindAsync(HttpContext context, ParameterInfo parameter)
{
const string sortByKey = "sortBy";
const string sortDirectionKey = "sortDir";
const string currentPageKey = "page";
Enum.TryParse(context.Request.Query[sortDirectionKey],ignoreCase: true, out var sortDirection);
int.TryParse(context.Request.Query[currentPageKey], out var page);
page = page == 0 ? 1 : page;
var result = new MyCustomParameters
{
SortBy = context.Request.Query[sortByKey],
Sort = sortDirection,
CurrentPage = page
};
return ValueTask.FromResult(result);
}
public enum SortDirection
{
Asc,
Desc
}
}
```
### Additional context
My main idea is to remove repetitive code that must be added for each endpoint that is using custom binding.
Contributor guide
Research direction
Start by tracing Minimal API BindAsync parameter binding and the WithOpenApi customization shown in the issue. Compare how attributes such as FromQuery and Required could describe generated OpenAPI parameters. Done means BindAsync-bound properties produce the expected query parameters, schemas, defaults, enum values, descriptions, and required flags without per-endpoint WithOpenApi code.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- csharp, openapi
- Domain
- api, backend-api-design
- Issue type
- Feature
- Difficulty
- 5/5
- Estimated time
- Over a week
- Activity status
- Quiet
- Clarity
- Mostly clear
- Newbie friendliness
- 38/100