How To Pass An Array As A Parameter While Calling an ASP.NET Web API

Through this blog, I would like to share how to pass an array as a parameter, while calling an ASP.NET Web API.

Thus, let's begin by creating the same. This blog is strictly to comprehend how to pass an array as parameter while calling ASP.NET Web API.

Consider that you want to perform some basic operation like Addition, Multiplication etc. by passing two or more parameters. However, the number of parameters is not specific.

We will create a method, which will accept three parameters. An input is mandatory for performing the operation while another would be an optional array. 
  1. public class BasicOperationPerform : BasicOperationBase    
  2.     {    
  3.            
  4.     
  5.         public override double PerformOperation(string operation, double n1, double n2, params double[] nn)    
  6.         {    
  7.             double result = 0;    
  8.             if (operation == "ADD")    
  9.             {    
  10.                 Addition add = new Addition();    
  11.                 double totaladdition = add.GetAddition(n1, n2, nn);    
  12.                 result = totaladdition;    
  13.             }    
  14.             else if (operation == "SUB")    
  15.             {    
  16.                 Subtraction add = new Subtraction();    
  17.                 double totalsubtraction = add.GetSubtraction(n1, n2, nn);    
  18.                 result = totalsubtraction;    
  19.             }    
  20.             else if (operation == "MUL")    
  21.             {    
  22.                 Multiplication add = new Multiplication();    
  23.                 double totalMultiplication = add.GetMultiplication(n1, n2, nn);    
  24.                 result = totalMultiplication;    
  25.             }    
  26.             else if (operation == "DIV")    
  27.             {    
  28.                 Division add = new Division();    
  29.                 double totaladdition = add.GetDivision(n1, n2, nn);    
  30.                 result = totaladdition;    
  31.             }    
  32.                 
  33.     
  34.             return result;    
  35.         }    

Now, let us create an APIController and observe whether the implemented stuff is sufficient for the requirement or not.

  1. public class BasicOperationController : ApiController    
  2.    {    
  3.        [HttpGet]    
  4.        [Route("api/GetBasicOperationResult/{operation}/{n1}/{n2}/{nn}")]    
  5.        public IHttpActionResult GetBasicOperationResult(string operation, double n1, double n2, [FromUri]double[] nn = null)    
  6.        {    
  7.            BasicOperationPerform bop = new BasicOperationPerform();    
  8.            double result = bop.PerformOperation(operation, n1, n2, nn);    
  9.     
  10.            return Ok(result);    
  11.        }    
  12.    }    

There are two things which need to be implemented in this code block.

  1. The nn parameter is optional. Thus, we need to add ? behind the nn in route as {nn?} to make it optional.

  2. How will we pass an array in the URL and the same would be accepted by the method. The best option to deal with it is create a Custom Action Filter attribute, which will filter the URL by a specific separator, as shown below. 
Thus, we will create an ArrayInputAttribute and override OnActionExecuting method for processing the input URL.
 
  1. public class ArrayInputAttribute : ActionFilterAttribute    
  2.     {    
  3.         private readonly string[] _parameternames;    
  4.            
  5.         public string Separator { getset; }    
  6.     
  7.          
  8.         public ArrayInputAttribute(params string[] parameternames)    
  9.         {    
  10.             _parameternames = parameternames;    
  11.             Separator = "-";   
  12.         }    
  13.           
  14.     
  15.     
  16.         public void ProcessArrayInput(HttpActionContext actionContext, string parametername)    
  17.         {    
  18.             if (actionContext.ActionArguments.ContainsKey(parametername))    
  19.             {    
  20.                 var parameterdescriptor = actionContext.ActionDescriptor.GetParameters().FirstOrDefault(p=>p.ParameterName== parametername);    
  21.     
  22.                 if (parameterdescriptor != null && parameterdescriptor.ParameterType.IsArray)    
  23.                 {    
  24.                     var type = parameterdescriptor.ParameterType.GetElementType();    
  25.                     var parameters = String.Empty;    
  26.                     if (actionContext.ControllerContext.RouteData.Values.ContainsKey(parametername))    
  27.                     {    
  28.                         parameters = (string)actionContext.ControllerContext.RouteData.Values[parametername];    
  29.                     }    
  30.                     else    
  31.                     {    
  32.                         var queryString = actionContext.ControllerContext.Request.RequestUri.ParseQueryString();    
  33.                         if (queryString[parametername] != null)    
  34.                         {    
  35.                             parameters = queryString[parametername];    
  36.                         }    
  37.                     }    
  38.     
  39.                     var values = parameters.Split(new[] { Separator }, StringSplitOptions.RemoveEmptyEntries)    
  40.                         .Select(TypeDescriptor.GetConverter(type).ConvertFromString).ToArray();    
  41.                     var typedValues = Array.CreateInstance(type, values.Length);    
  42.                     values.CopyTo(typedValues, 0);    
  43.                     actionContext.ActionArguments[parametername] = typedValues;    
  44.                 }    
  45.             }    
  46.         }    
  47.     
  48.         public override void OnActionExecuting(HttpActionContext actionContext)    
  49.         {    
  50.                 
  51.             foreach (var parameterName in _parameternames)    
  52.             {    
  53.                 ProcessArrayInput(actionContext, parameterName);    
  54.             }    
  55.         }    
  56.     }    

Note

We have used "-" as a separator.

Now, we are having the filter, which can be applied to the URL input and can transform to an array.

Thus, our method can be updated, as shown.

  1. [HttpGet]    
  2.         [ArrayInput("nn")]    
  3.         [Route("api/GetBasicOperationResult/{operation}/{n1}/{n2}/{nn?}")]    
  4.         public IHttpActionResult GetBasicOperationResult(string operation, double n1, double n2, [FromUri]double[] nn = null)    
  5.         {    
  6.             BasicOperationPerform bop = new BasicOperationPerform();    
  7.             double result = bop.PerformOperation(operation, n1, n2, nn);    
  8.     
  9.             return Ok(result);    
  10.         }    
Note

We have updated the method with the following.
  1. [ArrayInput("nn")]
  2. [Route("api/GetBasicOperationResult/{operation}/{n1}/{n2}/{nn?}")]

Now, we can call the Web API by passing the URL, as shown below.

"/api/GetBasicOperationResult/ADD/10/10/10-10-10".

Finally, there can be some other method also for dealing with it