Skip to content

Added support for type based parameter binding (#35496) #35535

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 3 commits into from
Aug 20, 2021

Conversation

davidfowl
Copy link
Member

Customer Impact

We've had several requests to enable MVC style model binding for minimal APIs, for both framework authors and customers who have written basic model binders for various types. We're enabling typed based modeling binding to unlock these scenarios so we can get feedback for .NET 7.0 for the overall design

Testing

Unit testing, lots of it.

Risk

Low

* Added support for type based parameter binding
- Added a convention that allows custom async binding logic to run for parameters that have a static BindAsync method that takes an HttpContext and return a ValueTask of object. This allows customers to write custom binders based solely on type (it's an extension of the existing TryParse pattern).
- There's allocation overhead per request once there's a parameter binder for a delegate. This is because we need to box all of the arguments since we're not using generated code to compute data from the list of binders.
- Changed TryParse tests to BindAsync tests and added more tests.
Copy link
Contributor

@pranavkm pranavkm left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'll trust @halter73 to review the changes to the factory.

var isOptional = parameter.HasDefaultValue || nullability.ReadState == NullabilityState.Nullable;

// Get the BindAsync method
var body = TryParseMethodCache.FindBindAsyncMethod(parameter.ParameterType)!;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Super small nit, but the name is no longer an accurate reflection of what's being cached. BinderMethodCache or something like that?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In .NET 7. This shared source is painful.

@@ -499,6 +499,53 @@ public static bool TryParse(string? value, out MyTryParsableRecord? result)
}
}

private class MyBindAsyncTypeThatThrows
{
public static ValueTask<object?> BindAsync(HttpContext context)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What's the behavior like if the signature does not match? e.g. ValueTask BindAsync(HttpContext context)?

Copy link
Member Author

@davidfowl davidfowl Aug 20, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It won't find it sorta like TryParse today and will fall through to the other things.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I could fail if it found the method but had the wrong return type?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Toss it in the Analyzer pile?

Copy link
Member

@halter73 halter73 Aug 20, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we just look for ValueTask<{type}> in FindBindAsyncMethod? What's the benefit of allowing any object to be returned? I get that we're going to box anyway for structs, but might as well lean on the type-safety checks of the compiler.

We could even throw at startup if a parameter type has a static BindAsync(HttpContext) method with the wrong return type.

@davidfowl davidfowl added feature-minimal-actions Controller-like actions for endpoint routing Servicing-approved Shiproom has approved the issue labels Aug 20, 2021
@davidfowl
Copy link
Member Author

cc @wtgodbe

@BrennanConroy BrennanConroy enabled auto-merge (squash) August 20, 2021 01:58
@BrennanConroy BrennanConroy merged commit 346e9ed into release/6.0-rc1 Aug 20, 2021
@BrennanConroy BrennanConroy deleted the davidfowl/typebased-model-binding-port branch August 20, 2021 04:36
@ghost ghost added this to the 6.0-rc1 milestone Aug 20, 2021
@amcasey amcasey added the area-minimal Includes minimal APIs, endpoint filters, parameter binding, request delegate generator etc label Jun 2, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
area-minimal Includes minimal APIs, endpoint filters, parameter binding, request delegate generator etc feature-minimal-actions Controller-like actions for endpoint routing Servicing-approved Shiproom has approved the issue
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants