Consider adding an API that enables invoking the default parameter binding logic of RequestDelegateFactory explicitly
- Dominant language
- C#
- Stars
- 38.4k
- Forks
- 10.9k
- Avg merge
- 2d 10h
- Merged PRs (30d)
- 281
Description
We should consider adding an API that enables the ability to invoke the parameter binding logic inherent in `RequestDelegateFactory` without having to create a `RequestDelegate`. This would be useful in situations where the default logic isn't invoked implicitly, e.g. when a complex parameter implements `BindAsync`, but invoking the behavior in an observable fashion would still add utility.
Such an API [exists in the MinimalApis.Extensions library](https://github.com/DamianEdwards/MinimalApis.Extensions/blob/main/src/MinimalApis.Extensions/Binding/DefaultBinderOfT.cs#L7) and is used by many of the included utility classes ([example](https://github.com/DamianEdwards/MinimalApis.Extensions/blob/main/src/MinimalApis.Extensions/Binding/BindOfT.cs#L42)).
Strawman API proposal:
``` diff
public static class RequestDelegateFactory
{
+ public static BindResult BindParameterAsync(HttpContext httpContext, ParameterInfo parameter);
}
+public class BindResult
+{
+ public TValue? Value { get; }
+ public int? StatusCode { get; }
+ public void Deconstruct(out TValue? value, out int statusCode);
+}
```
Example use:
``` c#
app.MapPost("/widgets", (Param widget, WidgetDb db) =>
{
if (widget.AutoResponseStatusCode != 200)
{
// There was an issue binding, implement custom handling logic here
return Results.Problem(statusCode: widget.AutoResponseStatusCode);
}
var newWidget = db.Insert(widget);
return Results.Created($"/widgets/{newWidget.Id}", newWidget);
});
public class CreateWidget
{
public string? Name { get; set; }
}
public class Param
{
public Param(TValue? value)
{
Value = value;
}
public TValue? Value { get; }
public int AutoResponseStatusCode { get; init; } = 200;
public static async ValueTask> BindAsync(HttpContext context, ParameterInfo parameter)
{
var (defaultValue, statusCode) = await RequestDelegateFactory.BindParameterAsync(context, parameter);
if (statusCode is not 200)
{
// The default logic would have implicitly returned due to an issue
return new Param(null) { AutoResponseStatusCode = statusCode };
}
return new Param(defaultValue);
}
}
```
Contributor guide
Assessment
This issue has not been assessed yet.