5

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.

asked Jul 9, 2020 at 8:11
2
  • There's no convention on passing value arrays in query parameters. Each language and frameworks uses its own conventions. Have you tried [FromUri] int[] stateList ? How do you want to pass those parameters? Commented Jul 9, 2020 at 9:04
  • ASP.NET Core's convention is to allow multiple parameter instances, eg ids=1&ids=2&ids=3 and bind them to a single ids array Commented Jul 9, 2020 at 9:12

3 Answers 3

10

This can help

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

but the query string will change to https://localhost/api/controller/cities?stateids=1&stateids=2&stateids=3

If you required comma separated query string with integer, you can go for Custom model binder

https://learn.microsoft.com/en-us/aspnet/core/mvc/advanced/custom-model-binding?view=aspnetcore-3.1

answered Jul 9, 2020 at 9:00

Comments

5

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

answered Jul 10, 2020 at 8:33

1 Comment

Hi @Yasser Shaikh, can this answer help you solve the problem?
0

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 
answered Jul 9, 2020 at 9:00

3 Comments

I want to pass stateids=1,2,3
@YasserShaikh that's one string parameter named stateids with value 1,2,3. There's no convention on passing value arrays in query parameters
You can take a look at this post : stackoverflow.com/questions/9584573/…

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.