dotnet / dotnet/aspnetcore

Consider adding an API that enables invoking the default parameter binding logic of RequestDelegateFactory explicitly

Open
#38,003 0 comments 1 reaction 0 assignees View on GitHub
api-proposal api-suggestion area-minimal enhancement feature-minimal-actions Priority:3 triage-focus
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

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.