Skip to content

Cannot use array/list to bind multiple query string parameters with Minimal APIs #37133

Closed
@martincostello

Description

@martincostello

Describe the bug

Porting an existing MVC controller to Minimal APIs, I found that attempting to use a string[] or IList<string> to bind multiple query string parameters with the same name does not work, throwing InvalidOperationException on startup.

For example, an MVC controller using this pattern as shown in the repro below would return the following:

Request

/names4?name=alice&name=bob

Response

["alice","bob"]

The equivalent functionality is not available out-of-the-box with Minimal APIs, and instead requires a custom type to bind the parameters.

I've used the bug template here, but it could arguably be a feature request instead.

To Reproduce

To reproduce, run the following application.

using Microsoft.AspNetCore.Mvc;

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddMvc();

var app = builder.Build();

// Either line, whichever is first, will throw InvalidOperationException.
// Comment out both lines to run the MVC equivalent.
app.MapGet("/names", ([FromQuery] string[] name) => name);
app.MapGet("/names2", ([FromQuery] IList<string> name) => name);

app.MapControllers();

app.Run();

public class NamesController : Controller
{
    [HttpGet]
    [Route("/names3")]
    public IActionResult Names3([FromQuery] string[] name) => Json(name);

    [HttpGet]
    [Route("/names4")]
    public IActionResult Names4([FromQuery] IList<string> name) => Json(name);
}

Exceptions

Unhandled exception. System.InvalidOperationException: No public static bool String[].TryParse(string, out String[]) method found for name.
   at Microsoft.AspNetCore.Http.RequestDelegateFactory.BindParameterFromValue(ParameterInfo parameter, Expression valueExpression, FactoryContext factoryContext)
   at Microsoft.AspNetCore.Http.RequestDelegateFactory.CreateArgument(ParameterInfo parameter, FactoryContext factoryContext)
   at Microsoft.AspNetCore.Http.RequestDelegateFactory.CreateArguments(ParameterInfo[] parameters, FactoryContext factoryContext)
   at Microsoft.AspNetCore.Http.RequestDelegateFactory.CreateTargetableRequestDelegate(MethodInfo methodInfo, RequestDelegateFactoryOptions options, FactoryContext factoryContext, Expression targetExpression)
   at Microsoft.AspNetCore.Http.RequestDelegateFactory.Create(Delegate handler, RequestDelegateFactoryOptions options)
   at Microsoft.AspNetCore.Builder.DelegateEndpointRouteBuilderExtensions.Map(IEndpointRouteBuilder endpoints, RoutePattern pattern, Delegate handler)
   at Microsoft.AspNetCore.Builder.DelegateEndpointRouteBuilderExtensions.MapMethods(IEndpointRouteBuilder endpoints, String pattern, IEnumerable`1 httpMethods, Delegate handler)
   at Microsoft.AspNetCore.Builder.DelegateEndpointRouteBuilderExtensions.MapGet(IEndpointRouteBuilder endpoints, String pattern, Delegate handler)
   at Program.<Main>$(String[] args) in C:\Coding\martincostello\_MultiQuery\Repro\Program.cs:line 9

Further technical details

.NET SDK 6.0.100-rc.1.21463.6

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions