1

This is my C# WebAPI2 controller, which gets hit:

[HttpGet, Route("bycaseidlist/{idArray}")]
public async Task<IHttpActionResult> GetByCaseIdList([FromUri] List<int> idArray)

This is the call:

var idArray = [4,4,2,4];
var url = baseUrl + 'api/cases/bycaseidlist/' + idArray ;

$http.get(url)

The problem is that the API doesn't get the array, it gets ...this:

enter image description here

In other words an array with one value: 0. Why is this happening? How do I fix it? It seems to be in-line with this answer, but it doesn't work. Should I pass it in the body? I feel like I am missing something obvious.

Community
  • 1
  • 1
VSO
  • 11,546
  • 25
  • 99
  • 187
  • Did you try without [FromUri]? – Ammar Hamidou Dec 09 '15 at 16:29
  • Use the dev tools in your browser to see what is the actual URL that is being sent. My guess is that you have to serialize the array. Look at the send request in this answer to see if your url is similar to it: http://stackoverflow.com/questions/9981330/how-to-pass-an-array-of-integers-to-a-asp-net-web-api-rest-service#answer-11100414 – peinearydevelopment Dec 09 '15 at 16:30
  • @AmmarHamidou: I did not, but I was sending the object in the url, so it was necessary. The alternative is from body, which is the default for anything except simple types, or something along those lines. Thanks for the answers guys. – VSO Dec 09 '15 at 16:47
  • The problem looks to be in your javascript. Even with the [FromUri] attribute the format of the url when I try with the syntax above does not serialize correctly. Your querystring neesd to be in the format ?numbers=1&numbers=2&numbers=3 or ?numbers[]=1&numbers[]=2&numbers[]=3 – Bill Dec 10 '15 at 16:28

2 Answers2

1

Get ActionMethods can take objects as arguments. However, the default behavior is to look at the body when the parameter is not a .net primitive. In order to force the action method to use a model binder to read the object data from the request, the parameter can be decorated with the [FromUri] or [ModelBinder] attributes. (Note there are other ways to do this that include doing parameter binding rules but that is probably overkill for what you are trying to accomplish here). Here is an implementation that solves the original problem that you were posing.

 <script type="text/javascript">
    var ajaxCall = function (myArry) {
        var ajaxProperties = {};
        ajaxProperties.url = "/api/Mul/Mutiply";
        ajaxProperties.type = "Get";
        ajaxProperties.data = {};
        ajaxProperties.data.numbers = myArry;
        ajaxProperties.contentType = "application/json";
        console.log(ajaxProperties);
        ajaxProperties.success = function (data) {
            console.log(data);
        }
        ajaxProperties.error = function (jqXHR) {
            console.log(jqXHR);
        };
        $.ajax(ajaxProperties);

    };
    var getData = function (e) {

        var myArry = new Array();
        myArry.push($('input[name=num1').val());
        myArry.push($('input[name=num2').val());

        ajaxCall(myArry);
        return false;
    };
     </script>

Controller

    [HttpGet]
    public IHttpActionResult Multiply([FromUri] int[] numbers)
    {
        int result = 0;
        if(numbers.Length > 0)
        {
            result = 1;
            foreach (int i in numbers)
            {
                result = result * i;
            }
        }
        return Ok(result);
    }
}
Bill
  • 1,241
  • 17
  • 25
  • Ty. I will come back to accept once I test. I still think there is something about sending http request objects in body and specifically get requests that doesn't work, but it might be an angular-only limitation. Will check the details. – VSO Dec 10 '15 at 16:58
  • You are probably correct. jquery got a head nod from microsoft and it looks like the default serialization of the requst in the get does not format correctly in your implementation. However, there are several books, articles, web sites that show serializing the data into an object, list, or array from the query string of the request. – Bill Dec 10 '15 at 17:02
  • Good enough for me for now. I know how to serialize, but it seems more intuitive to just put the complex objects in the body. Anyway, you answered my question. – VSO Dec 10 '15 at 17:04
0

I think my mistake was using Get. I might be remembering incorrectly (someone confirm if you know offhand), but Get might not be able to take objects as arguments. Anyway, I changed the method to POST and then changed the param to be sent in the request body, rather than the url. It now works. Here is the working code:

[HttpPost, Route("bycaseidlist")]
public async Task<IHttpActionResult> PostByCaseIdList([FromBody] int[] sqlCaseIdArray)

and the call itself:

                    function runDbCall(url, sqlCaseIdArray){
                        return $http({
                            method: 'POST',
                            url: url,
                            data: sqlCaseIdArray
                        });
                    }

                    runDbCall(url, sqlCaseIdArray)

I will come back to this when I figure out if the problem was Get not being able to take objects, but I thought it could in url, just not in body...need to clarify. If someone posts an answer just on that part, I will accept, since that's probably the root of the prob.

VSO
  • 11,546
  • 25
  • 99
  • 187