Problem
I need to pass an array of integers to an ASP.NET Web API (version 4) REST service.
Here’s how I go about taking action:
public IEnumerable<Category> GetCategories(int[] categoryIds){
// code to retrieve categories from database
}
And this is the URL that I tried:
/Categories?categoryids=1,2,3,4
Asked by Hemanshu Bhojak
Solution #1
You only need to add [FromUri] before the parameter, as shown below:
GetCategories([FromUri] int[] categoryIds)
And send request:
/Categories?categoryids=1&categoryids=2&categoryids=3
Answered by Lavel
Solution #2
As Filip W suggests, you may need to use a custom model binder like this (adjusted to bind to the actual type of parameter):
public IEnumerable<Category> GetCategories([ModelBinder(typeof(CommaDelimitedArrayModelBinder))]long[] categoryIds)
{
// do your thing
}
public class CommaDelimitedArrayModelBinder : IModelBinder
{
public bool BindModel(HttpActionContext actionContext, ModelBindingContext bindingContext)
{
var key = bindingContext.ModelName;
var val = bindingContext.ValueProvider.GetValue(key);
if (val != null)
{
var s = val.AttemptedValue;
if (s != null)
{
var elementType = bindingContext.ModelType.GetElementType();
var converter = TypeDescriptor.GetConverter(elementType);
var values = Array.ConvertAll(s.Split(new[] { ","},StringSplitOptions.RemoveEmptyEntries),
x => { return converter.ConvertFromString(x != null ? x.Trim() : x); });
var typedValues = Array.CreateInstance(elementType, values.Length);
values.CopyTo(typedValues, 0);
bindingContext.Model = typedValues;
}
else
{
// change this line to null if you prefer nulls to empty arrays
bindingContext.Model = Array.CreateInstance(bindingContext.ModelType.GetElementType(), 0);
}
return true;
}
return false;
}
}
Then you can say something like:
ASP.NET Web API will appropriately bind your categoryIds array when you visit /Categories?categoryids=1,2,3,4.
Answered by Mrchief
Solution #3
I recently encountered this requirement and decided to develop an ActionFilter to address it.
public class ArrayInputAttribute : ActionFilterAttribute
{
private readonly string _parameterName;
public ArrayInputAttribute(string parameterName)
{
_parameterName = parameterName;
Separator = ',';
}
public override void OnActionExecuting(HttpActionContext actionContext)
{
if (actionContext.ActionArguments.ContainsKey(_parameterName))
{
string parameters = string.Empty;
if (actionContext.ControllerContext.RouteData.Values.ContainsKey(_parameterName))
parameters = (string) actionContext.ControllerContext.RouteData.Values[_parameterName];
else if (actionContext.ControllerContext.Request.RequestUri.ParseQueryString()[_parameterName] != null)
parameters = actionContext.ControllerContext.Request.RequestUri.ParseQueryString()[_parameterName];
actionContext.ActionArguments[_parameterName] = parameters.Split(Separator).Select(int.Parse).ToArray();
}
}
public char Separator { get; set; }
}
I’m using it like this (notice that I used ‘id’ rather than ‘ids’ because that’s how my route specifies it):
[ArrayInput("id", Separator = ';')]
public IEnumerable<Measure> Get(int[] id)
{
return id.Select(i => GetData(i));
}
And here’s the public url:
/api/Data/1;2;3;4
This may need to be refactored to match your individual requirements.
Answered by Steve Czetty
Solution #4
If someone needs to do the same or comparable operation (like remove) via POST instead of FromUri, use FromBody and format param as $.param(“: categoryids, true) on the client side (JS/jQuery).
c#:
public IHttpActionResult Remove([FromBody] int[] categoryIds)
jQuery:
$.ajax({
type: 'POST',
data: $.param({ '': categoryids }, true),
url: url,
//...
});
The problem with $.param(“: categoryids, true) is that.net expects the post body to have urlencoded values like =1&=2&=3 without the parameter name or brackets.
Answered by Sofija
Solution #5
A simple method for sending array parameters to a web API.
API
public IEnumerable<Category> GetCategories([FromUri]int[] categoryIds){
// code to retrieve categories from database
}
Jquery: as request parameters, send a JSON object
$.get('api/categories/GetCategories',{categoryIds:[1,2,3,4]}).done(function(response){
console.log(response);
//success response
});
It will generate your request URL like ../api/categories/GetCategories?categoryIds=1&categoryIds=2&categoryIds=3&categoryIds=4
Answered by Jignesh Variya
Post is based on https://stackoverflow.com/questions/9981330/pass-an-array-of-integers-to-asp-net-web-api