Extend the ability to customize parameter binding for Minimal APIs
- Dominant language
- C#
- Stars
- 38.4k
- Forks
- 10.9k
- Avg merge
- 2d 5h
- Merged PRs (30d)
- 276
Description
This issue is to discuss future updates to extend the ability to customize parameter binding for Minimal APIs, beyond what's available in .NET 6, i.e. static methods `bool TryParse(string input, out T value)` and `ValueTask BindAsync(HttpContext httpContext)` on the target type.
These are some features of parameter binding to consider:
- [ ] bind via target type (sync from request non-body sources, this is `TryParse` in .NET 6)
- [ ] bind via target type (async from request inc. body, this is `BindAsync` in .NET 6)
- [ ] bind via registered type (inc. overwriting built-in binders), e.g. register `IParameterBinder` in DI
- [ ] bind per parameter, e.g. `([Binder(typeof(CustomerBinder))]Customer customer) => { }`
- [ ] register via DI and accept services from DI
- [ ] have access to method/parameter info (i.e. callsite details, access to the parameter is supported by `BindAsync` in .NET 6 now)
- [ ] compose with other binders (e.g. composite binders)
- [ ] emit/mutate endpoint metadata, e.g. for OpenAPI
- [ ] AOT friendliness
### Strawman
``` csharp
public interface IParameterBinderFactory
{
IParameterBinder Create(IServiceProvider provider, ParameterInfo parameter, MethodInfo method);
}
public interface IParameterBinder
{
ValueTask BindAsync(HttpContext httpContext);
}
```
Example usage:
``` csharp
var builder = WebApplication.CreateBuilder();
builder.Services.AddSingleton, CustomerBinder>();
var app = builder.Build();
app.MapPost("/customers", (Cusomter customer) =>
{
return Results.Created(customer);
});
public class CustomerBinder : IParameterBinderFactory, IParameterBinder
{
public CustomerBinder Create(IServiceProvider provider, ParameterInfo parameter, MethodInfo method)
{
// Called at application startup, access to parameter and method here to change behavior based on
// naming, attributes, etc.
return new CustomerBinder();
}
public async ValueTask BindAsync(HttpContext httpContext)
{
// Called per invocation of routing delegate, i.e. per request
// Do whatever custom binding logic desired, including reading from request body, etc.
return await httpContext.Request.ReadAsJsonAsync();
}
}
```
Related issues:
- https://github.com/dotnet/aspnetcore/issues/33955
- https://github.com/dotnet/aspnetcore/issues/35472
- https://github.com/dotnet/aspnetcore/issues/35304
Contributor guide
Assessment
This issue has not been assessed yet.