0

Usings Net 6 Minimal API I have the following route:

builder.MapGet("posts", async ([FromQuery] IEnumerable<Int32> postsIds) => {
});

The parameters postsIds contains the ids of posts to be loaded, e.g., "1, 3, 5".

I get the following error when running the application:

Exception thrown: 'System.InvalidOperationException' in Microsoft.AspNetCore.Http.Extensions.dll: 'No public static bool IEnumerable.TryParse(string, out IEnumerable) method found for postsIds.

So I created the following:

public class CommaSeparatedValues<T> {

  public IEnumerable<T> Values { get; set; } = new List<T>();

  public static Boolean TryParse(String? value, IFormatProvider? provider, out CommaSeparatedValues<T>? commaSeparatedValues) {

    IEnumerable<T>? values = value?.Split(',', StringSplitOptions.RemoveEmptyEntries | StringSplitOptions.TrimEntries).Cast<T>();

    if (values is null) {
      commaSeparatedValues = null;
      return false;
    }

    commaSeparatedValues = new CommaSeparatedValues<T> { Values = values };
    return true;

  } 

And changed the endpoint to:

builder.MapGet("posts", async ([FromQuery] CommaSeparatedValues<Int32> postsIds) => {
});

Does this make sense? Can I improve / simplify this approach? Or this is the way?

Crowcoder
  • 11,250
  • 3
  • 36
  • 45
Miguel Moura
  • 36,732
  • 85
  • 259
  • 481
  • 1
    I don't know if you like this method, but if you repeat query parameters they will come into the controller as an array: `?id=1&id=3&id=5` – Crowcoder Dec 08 '21 at 16:57
  • Was not able to reproduce. Also `.Cast()` will not work cause you can't cast `string` to `int`. – Guru Stron Dec 08 '21 at 16:58
  • @Crowcoder I know. But what would be type of the parameter in my endpoint method? Array of int? – Miguel Moura Dec 08 '21 at 17:30
  • why not send all comma separated values in one parameter and use custom model binder to fill a list? – abdul qayyum Dec 09 '21 at 08:03
  • Does this answer your question? [Model binding comma separated query string parameter](https://stackoverflow.com/questions/9584573/model-binding-comma-separated-query-string-parameter) Answer https://stackoverflow.com/a/49910078/2343086 – abdul qayyum Dec 09 '21 at 08:09

1 Answers1

0

According to this section, so I test your code in my side:

Pls note this line var trimmedValue = value?.TrimStart('(').TrimEnd(')'); and CommaSeparatedValues<string> postsIds. Per my test I found when using CommaSeparatedValues<Int32> postsIds it will appear error message below because it can't execute .Cast<T>() successfully.

enter image description here

app.MapGet("posts", (CommaSeparatedValues<string> postsIds) => {
    return postsIds;
});

public class CommaSeparatedValues<T>
{
    public IEnumerable<T> Values { get; set; } = new List<T>();

    public static Boolean TryParse(String? value, IFormatProvider? provider, out CommaSeparatedValues<T>? commaSeparatedValues)
    {
        {
            // Format is "(12.3,10.1)"
            var trimmedValue = value?.TrimStart('(').TrimEnd(')');
            IEnumerable<T>? values = trimmedValue?.Split(',', StringSplitOptions.RemoveEmptyEntries | StringSplitOptions.TrimEntries).Cast<T>();

            if (values is null)
            {
                commaSeparatedValues = null;
                return false;
            }

            commaSeparatedValues = new CommaSeparatedValues<T> { Values = values };
            return true;
        }
    }
}

enter image description here

By the way if you can accept to use this instead?

app.MapGet("posts", async ([FromQuery(Name = "postsIds")] string postsIds) =>
{
    List<string> list = postsIds.Split(",").ToList(); 
    return postsIds;
});
Tiny Wang
  • 10,423
  • 1
  • 11
  • 29