0

I have a legacy ASP.NET Web API 2 project and want port it to ASP.NET Core 6. I have a problem with http get method which has next argument

public class GetUsersArgs
{
    public List<int> UserIds { get; set; }
}

Client app calls it in next way api/Users/GetUsers?UserIds[]=1&UserIds[]=5&UserIds[]=10 It binds as array with three elements in ASP.NET Web API 2 but it fails when binding in ASP.NET Core 6. I can`t change client code so my question how to achieve same binding on core.

YuriyP
  • 4,210
  • 4
  • 25
  • 35
  • 1
    Try adding a `[FromQuery("UserIds[]")]` attribute to explicitly add the square brackets to the query string parameter. – Martin Costello Jun 17 '22 at 10:39
  • If that fails, you'll probably want to use the rewrite middleware to remote the `[] ` parts. – ProgrammingLlama Jun 17 '22 at 10:45
  • `[FromQuery("UserIds[]")]` breaks other clients which use `api/Users/GetUsers?UserIds[0]=1&UserIds[1]=5&UserIds[2]=10` or `api/Users/GetUsers?UserIds=1&UserIds=5&UserIds=10` formats. Also I need more generic solution because I have many similar api methods. Ideally some custom `IModelBinder` for arrays. – YuriyP Jun 17 '22 at 11:36

1 Answers1

0

I did not found solution which handle my problem on binding level so I created simple middleware which patches legacy queries. Than used LegacyQueryBindingMiddleware before mvc middlewares and it solves my problem.

public class LegacyQueryBindingMiddleware
{
    private readonly RequestDelegate _next;
    
    public LegacyQueryBindingMiddleware(RequestDelegate next)
    {
        _next = next;
    }
    
    public Task Invoke(HttpContext context)
    {
        if (context.Request.Method == "GET")
        {
            var query = context.Request.QueryString.ToString();
            if (query.Contains("[]="))
            {
                var qBuilder = new QueryBuilder();
                foreach (var (key, value) in context.Request.Query)
                {
                    qBuilder.Add(key.Replace("[]", ""), value.ToArray());
                }
                context.Request.QueryString = qBuilder.ToQueryString();
            }
        }
        return _next.Invoke(context);
    }
}
YuriyP
  • 4,210
  • 4
  • 25
  • 35
  • There's no standardized way to send arrays in a URL. Each framework has its own conventions but `UserIds[0]=1` is one of the most unusual. Have you tried `UserIds=1&UserIds=3...` instead? That [works in ASP.NET Web API 2 as well](https://stackoverflow.com/questions/9981330/pass-an-array-of-integers-to-asp-net-web-api) – Panagiotis Kanavos Jul 05 '22 at 09:10
  • I have issue with `UserIds[]=1&UserIds[]=3` format. And I can not change that format. Please read my question where I provided details. – YuriyP Jul 05 '22 at 11:31