Skip to content
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

Added support for arrays of types with TryParse, StringValues and string[] for query strings and headers #39809

Merged
merged 17 commits into from
Jan 29, 2022

Conversation

davidfowl
Copy link
Member

@davidfowl davidfowl commented Jan 27, 2022

  • Added inferred query support for methods where the body inference is disabled.
  • Added a tests.

Fixes #32516
Fixes #36726

- Added inferred query support for methods where the body inference is disabled.
- Added a test
@martincostello
Copy link
Member

Two questions about how supporting this could work when finished.

  1. Say for example that a query string contained values like 1,2,,4 because there's a blank/missing entry. Would it be explicitly ignored because empty (so you'd get new int[] { 1, 2, 4 }), would it fail the binding because the int.TryParse() call would return false, or could the user opt into one behaviour vs. the other?
  2. Would this support query strings in the formats a=1,2,3, a=1&a=2&a=3, or both?

@davidfowl
Copy link
Member Author

Say for example that a query string contained values like 1,2,,4 because there's a blank/missing entry. Would it be explicitly ignored because empty (so you'd get new int[] { 1, 2, 4 }), would it fail the binding because the int.TryParse() call would return false, or could the user opt into one behaviour vs. the other?

This is a good question, currently I think it would fail to bind but I could go either way here (ignoring empty entries).

Would this support query strings in the formats a=1,2,3, a=1&a=2&a=3, or both?

No, it will only support the second, not the first. The one thing I don't want to support multiple formats unless they are common. MVC supports LOTS of formats https://docs.microsoft.com/en-us/aspnet/core/mvc/models/model-binding?view=aspnetcore-6.0#collections, that won't be supported here. I chose the most obvious one (the latter in your above sample).

@martincostello
Copy link
Member

No, it will only support the second, not the first.

That's fair - I figured I'd ask the question about how much of MVC's leniency would come through as I've seen both approaches in the wild.

@davidfowl
Copy link
Member Author

davidfowl commented Jan 27, 2022

That's fair - I figured I'd ask the question about how much of MVC's leniency would come through as I've seen both approaches in the wild.

If this is common, we can support it. I'll let others chime in of course 😄. I'm inclined to support a subset of whatever MVC supports and it doesn't support slapping multiple values into a single query string value.

using Microsoft.AspNetCore.Mvc;

var builder = WebApplication.CreateBuilder(args);
builder.Services.AddControllers();
var app = builder.Build();

app.MapControllers();

app.Run();

public class MyController : ControllerBase
{
    [HttpGet("/")]
    public string Get(int[] values) => string.Join("&", values);
}

Sending this /?values=1,2,3 doesn't print anything.

This is because the collection model binder uses the simple model binder (type converter) to convert values from strings to the target type. This will try to parse the "1,2,3" as an int as it doesn't split things first. Thats probably good because you'd also need to decide what happens when you do; ?a=1,2,3&a=4

@Pilchie Pilchie added the area-web-frameworks *DEPRECATED* This label is deprecated in favor of the area-mvc and area-minimal labels label Jan 27, 2022
@@ -68,6 +69,17 @@ public void OnProvidersExecuted(ApiDescriptionProviderContext context)

private ApiDescription CreateApiDescription(RouteEndpoint routeEndpoint, string httpMethod, MethodInfo methodInfo)
{
static bool ShouldDisableInferredBody(string method)
Copy link
Member Author

Choose a reason for hiding this comment

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

More copied logic between Map and the api description provider 😢

Copy link
Member

Choose a reason for hiding this comment

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

Can we move this to shared source to prevent these from going out of sync? Maybe rename ParameterBindingMethodCache to be more general. If not, I'd say just add a comment to the ShouldDisableInferredBody(string method) in EndpointRouteBuilderExtensions to keep these in sync.

Copy link
Member

Choose a reason for hiding this comment

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

Oh, I just noticed that this should be called against all the methods in IHttpMethodMetadata.HttpMethods, not just the one we're creating the ApiDescription for currently to align with the logic in EndpointRouteBuilderExtensions.

@davidfowl davidfowl marked this pull request as ready for review January 28, 2022 08:12
@davidfowl
Copy link
Member Author

OK this is done and ready for review.

@davidfowl davidfowl changed the title Added support for arrays of types with TryParse Added support for arrays of types with TryParse, StringValues and string[] for query strings and headers Jan 28, 2022
@davidfowl davidfowl merged commit 25488c5 into main Jan 29, 2022
@davidfowl davidfowl deleted the davidfowl/query-arrays branch January 29, 2022 03:17
@ghost ghost added this to the 7.0-preview1 milestone Jan 29, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
area-web-frameworks *DEPRECATED* This label is deprecated in favor of the area-mvc and area-minimal labels
Projects
None yet
5 participants