CarterCommunity / Carter

Carter is framework that is a thin layer of extension methods and functionality over ASP.NET Core allowing code to be more explicit and most importantly more enjoyable.

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Could not bind an array of query param values with Request.Query.As<int[]>("Id")

Deilan opened this issue · comments

public sealed class AppCarterModule : CarterModule
{
    private static readonly Actor[] Actors = new[]
    {
        new Actor() { Id = 1, Name = "First"},
        new Actor() { Id = 2, Name = "Second"},
        new Actor() { Id = 3, Name = "Third"},
    };
    public AppCarterModule()
    {
        Get("/actors", async ctx =>
        {
            IEnumerable<Actor> result = Actors;
            // ids is always null for "/actors?Id=1&Id=3"
            var ids = ctx.Request.Query.As<int[]>("Id");
            if (ids != null)
            {
                result = result.Where(x => ids.Contains(x.Id));
            }
            await ctx.Response.Negotiate(result);
        });
    }
}

GET /actors?id=1&id=3
returns all 3 records instead of 2 because ctx.Request.Query.As<int[]>("Id") returns null instead of [1,3]

Repository with a failing test
https://github.com/deilan-issues-samples/Carter.Issues

public async Task Test1()
        {
            var client = _factory.CreateClient();
            var result = await client.GetAsync("/actors?Id=1&Id=3");
            var str = await result.Content.ReadAsStringAsync();
            var array = JsonConvert.DeserializeObject<dynamic[]>(str);

            Assert.Equal(2, array.Length);
        }

Hey, sorry for the slow response.

There's no definitive spec on duplicate query strings, so Carter just takes the first instance of it, and ignores the rest, so you're getting null because it's actually an int not a int[].

I'd question the API design around this first, it's a bit odd imo. Comma-separated values in query params is more common these days.

Not sure this is something Carter should be addressing

I cannot provide any reference to a language- or platform-agnostic spec on that topic. But since:

  • Carter is built upon ASP.NET Core infrastructure, and aforementioned way of working with query strings is the default in ASP.NET (Core)
  • main target audience of Carter is ASP.NET (Core) developers (in past or present)

I'd say it should be also the default way in Carter too. Other ways are also would be nice to have, but as an opt-in.

(Some of) ASP.NET Core utils', used to work with query params:

In particular:
https://github.com/dotnet/aspnetcore/blob/4bd244935a88384def10cce77e68bc2c79cba3a0/src/Http/Http.Extensions/test/QueryBuilderTests.cs#L74-L84

https://github.com/dotnet/aspnetcore/blob/4bd244935a88384def10cce77e68bc2c79cba3a0/src/Http/WebUtilities/test/QueryHelpersTests.cs#L32-L39

To get an array you can do var ids = ctx.Request.Query.AsMultiple<int>("id");