1

Working in MVC/ASP.NET, I want to call action methods of a Web API controller (this controller is called "TreinreisController") from my view. For that purpose, I have the following javascript/jQuery function in the view:

function sendAjaxRequest(httpMethod, controller, callback, url, reqData) {
         $.ajax("/api/" + controller + (url ? "/" + url : ""), {
               type: httpMethod,
               contentType: "application/json",
               dataType: "json",
               traditional: true,
               data: JSON.stringify(reqData),
               success: callback,
               error: function (x, y, z) {
                   var err = eval("(" + x.responseText + ")");
                   alert(err.Message);
               },
               data: reqData
         });
}

I call this function whenever I want to make an ajax call to a controller action method using JSON. And this works perfectly if I only place a string (param1) in the data object, like this:

        var param1 = "some_string";
        sendAjaxRequest("POST", "treinreis", function (data) {
                           alert("Succes!");
                        },
        "action_method_name",
        {param1: param1}
        );

But it goes wrong when I add an array of integers as a second parameter (param2), like this:

        var param1 = "some_string";
        var param2 = [8, 17];
        sendAjaxRequest("POST", "treinreis", function (data) {
                               alert("Succes!");
                            },
        "action_method_name",
        {param1: param1, param2: param2}
        );

In the case of 2 parameters, with one being an array, the action method is never reached. Unfortunately, the error message I get from the alert in the error callback-function in function sendAjaxRequest only says: "An error has occurred", which is less than helpful.

I've checked that the array arrives intact in function sendAjaxRequest, and that's in fact the case. So the problem seems to have to do with the JSON serialization, or maybe routing (although the latter seems strange, because the same routing works perfectly with only param1).

The action method in the controller, TreinreisController, goes like this (I'm showing the version with both parameters; the one that only takes param1 should of course be modified accordingly):

[System.Web.Http.HttpPost]   
[System.Web.Http.Route("api/treinreis/action_method_name")]
public void MyActionMethod([FromBody] string param1, 
                           [FromBody] int[] param2) {
    // do calculations, whatever
}

I note that the parameters in the action method have the same names as the ones used in the data-object in the view (i.e., param1 and param2).

What am I doing wrong. Why does work with only param1, but not when I add param2?

Many thanks, and I'll be able to check back in a few hours.

Holland
  • 395
  • 9
  • 22
  • 1
    You are passing Json to controller action you need to pass $('form').serialize(); instead of JSON.stringify(reqData) – Laxman Gite Aug 07 '17 at 06:19
  • Use your browser tools (the Network tab) to inspect the response which will give you the details of the error. –  Aug 07 '17 at 06:27
  • Note also you cannot use `[FromBody]` twice. Refer [Parameter Binding in ASP.NET Web API](https://learn.microsoft.com/en-us/aspnet/web-api/overview/formats-and-model-binding/parameter-binding-in-aspnet-web-api) –  Aug 07 '17 at 06:32
  • 3
    Instead, create a model that contains `int param1` and int[] param2 –  Aug 07 '17 at 06:39
  • data: $('form').serializeArray(), – REDEVI_ Aug 07 '17 at 07:11
  • @LaxmanGite It's not clear to me what's wrong with JSON.stringify? Stringify means serialization, right? And serialization is what I want. I see JSON.stringify used in many examples, for example in the accepted answer here: https://stackoverflow.com/questions/17426199/jquery-ajax-and-json-format, as well as here: https://stackoverflow.com/questions/15687903/ajax-web-api-post-method-how-does-it-work. Also, I do not really have one form that must be passed as a whole... – Holland Aug 07 '17 at 09:30
  • @StephenMuecke Yes, I'm beginning to understand... I must define a server side 'wrapper' class, i.e. model, having param1 and param2 as its properties. And that will be the type of the parameter of the action method. Will try it out a.s.a.p. – Holland Aug 07 '17 at 09:33

1 Answers1

1

You cannot do this! It is by design that at most one parameter is allowed to read from the message body. Hence, this will not work.

The reason for this rule is that the request body might be stored in a non-buffered stream that can only be read once.

https://learn.microsoft.com/en-us/aspnet/web-api/overview/formats-and-model-binding/parameter-binding-in-aspnet-web-api

There a few workarounds that you can use to make this work:

  1. Use both POST and QueryString Parameters in Conjunction
  2. Use a single Object that wraps the two Parameters
  3. Use JObject to parse multiple Property Values out of an Object

https://weblog.west-wind.com/posts/2012/May/08/Passing-multiple-POST-parameters-to-Web-API-Controller-Methods

  • Thanks. Yes, I'm going for Option 2, will try it out as soon as possible, later today. If it works, I'll accept this answer (even though Stepehen Muecke suggested your Option 2 as well in a comment, for which I gave him an upvote). – Holland Aug 07 '17 at 09:37
  • Yes, got everything working now with Option 2. My thanks to you and also to @StephenMuecke. – Holland Aug 08 '17 at 02:50
  • Accidentally not only accepted the answer but also upvoted it. Well, I guess I'm not gonna undo the upvote, in fact I seem to be unable to (due to lack of reputation points). :-) – Holland Aug 08 '17 at 02:52