.NET CORE WEB API accept list of integers as an input param in HTTP GET API

Viewed 5840

I am using .net core 3+ web api.

Below is how my action looks like below, it uses HTTP GET and I want to pass few fields and one of the fields is a list of integers.

[HttpGet]
[Route("cities")]
public ActionResult<IEnumerable<City>> GetCities([FromQuery] CityQuery query)
{...}

and here is CityQuery class -

public class CityQuery
{
    [FromQuery(Name = "stateids")]
    [Required(ErrorMessage = "stateid is missing")]
    public string StateIdsStr { get; set; }

    public IEnumerable<int> StateList    
    {
        get
        {
            if (!string.IsNullOrEmpty(StateIdsStr))
            {
                var output = StateIdsStr.Split(',').Select(id =>
                {
                    int.TryParse(id, out var stateId);
                    return stateId;
                }).ToList();
                return output;
            }
            return new List<int>();
        }
    }
}

Is there a generic way I can use to accept list of integers as input and not accept string and then parse it?

Or is there a better way to do this? I tried googling but could not find much. Thanks in advance.

3 Answers

You can use custom model binding, below is a working demo:

Model:

public class CityQuery
{
    public List<int> StateList{ get; set; }
}

CustomModelBinder:

public class CustomModelBinder: IModelBinder
{
    public Task BindModelAsync(ModelBindingContext bindingContext)
    {
        if (bindingContext == null)
        {
            throw new ArgumentNullException(nameof(bindingContext));
        }

        var values = bindingContext.ValueProvider.GetValue("stateids");

        if (values.Length == 0)
        {
            return Task.CompletedTask;
        }

        var splitData = values.FirstValue.Split(',');
        var result = new CityQuery()
        {
            StateList = new List<int>()
        };

        foreach(var id in splitData)
        {
            result.StateList.Add(int.Parse(id));
        }
        bindingContext.Result = ModelBindingResult.Success(result);
        return Task.CompletedTask;
    }
}

Applying ModelBinding Attribute on Action method:

[HttpGet]
[Route("cities")]
public ActionResult GetCities([ModelBinder(BinderType = typeof(CustomModelBinder))] CityQuery query)
{
    return View();
}

when the url like /cities?stateids=1,2,3, the stateids will be filled to StateList

I think you just need to use [FromUri] before int array parameter :

public ActionResult<IEnumerable<City>> GetCities([FromUri] int[] stateList)

And request would be like :

/cities?stateList=1&stateList=2&stateList=3 
Related