2

I have a JavaScript function where I pass 4 arrays, each of these is of the type [1, 2] with only int values inside or [] with no values inside. these are passed into an Url.Action command.

function Filter(locations, machines, severities, messages) {
    var url = '@Url.Action("Filter", "ActiveMessages")?' + $.param({ 
        locations: locations, machines: machines, severities: severities, messages: messages });
    $.ajax({
        url: url,
        method: 'POST',
        traditional: true,
        success: function (data) { }
    });
}

I tried to build the parameters using $.param(). but this doesn't generate the parameters i'm expecting, I get something like this: "/ActiveMessages/Filter?locations%5B%5D=1"

I also tried doing this:

decodeURIComponent($.param({ locations: filterlocations, machines: filtermachines, severities: filterseverities, messages: filtermessages }))

Then I get something like this: "/ActiveMessages/Filter?locations[]=1&locations[]=2"

Are there any other ways to parse such an array into an url?

Receiving happens in the controller:

public async Task<ActionResult> Filter(int[] locations, int[] machines, int[] severities, int[] messages)
{
    //TODO filter
}

This gets called but the parameters are null;

when I started out I used this which works for a single value but needs to be extended to an array.

var url = '@Url.Action("Filter", "ActiveMessages")' + '?locations=' + locations + '&machines=' + machines + '&severities=' + severities + '&messages=' + messages;
Milad Rashidi
  • 1,296
  • 4
  • 22
  • 40
Axel Bouttelgier
  • 173
  • 1
  • 12
  • Why do you want to pass them by URL? – Ivan Franco Feb 23 '17 at 13:58
  • what other way would you recommend? i thought it would be the easiest way since the data isn't private – Axel Bouttelgier Feb 23 '17 at 13:59
  • 2
    I suggest to pass them with an AJAX POST and include all arrays on data property. Something like this http://stackoverflow.com/a/5489534/6157222 – Ivan Franco Feb 23 '17 at 14:02
  • Yes. Just use POST. You should pretty much *always* use POST with an AJAX call involving data. – Chris Pratt Feb 23 '17 at 14:26
  • 1
    If you did want to do this as a query string, then you need to use `$.param({ ..... }, true);` - your missing the 2nd parameter - [refer documentation](http://api.jquery.com/jquery.param/) (and the `traditional: true` option would be pointless since you not sending any data in the body –  Feb 23 '17 at 21:48

3 Answers3

2

best practise for a post action will be to use the body to send parameters for post (Note the [FromBody] annotation of paramters):

[HttpPost]
public async Task<ActionResult> Filter([FromBody] int[] locations, [FromBody] int[] machines, [FromBody] int[] severities, [FromBody] int[] messages)

the parameters needs to be specified in the body of the ajax call:

function Filter(locations, machines, severities, messages) {
     var url = '@Url.Action("Filter", "ActiveMessages")';
     $.ajax({
          url: url,
          method: 'POST',
          data: JSON.stringify({ locations: locations, machines: machines, severities: severities, messages: messages }),
          traditional: true,
          success: function (data) {
     }});
 }
Ionut Ungureanu
  • 1,020
  • 1
  • 13
  • 16
  • 1
    `[FromBody]` is unnecessary here. The method only allows POST, so the data will of course come from the post body. – Chris Pratt Feb 23 '17 at 14:23
  • I've implemented this but i'm still getting null as value in my controller – Axel Bouttelgier Feb 23 '17 at 14:26
  • I've build the data like this : data: { 'locations': locations, 'machines': machines, 'severities': severities, 'messages': messages } as suggested by – Ivan Franco . Now i'm getting the data in my controller – Axel Bouttelgier Feb 23 '17 at 14:30
2
var locations = [1,2];
var machines = [3,4];
var severities = [5,6];
var messages = [7,8];

$.ajax({
     url: @Url.Action("Filter", "ActiveMessages"),
     method: 'POST',
     data: { 
            locations: locations, 
            machines: machines, 
            severities: severities, 
            messages: messages 
     },
     success: function (data) {
     }
});

In this case, no need to stringify :)

Demian Bibiano
  • 347
  • 1
  • 10
2

While what the others say is totally true (body is made for that) sometimes it's still good to have a choice. The Problem with your query was that the keyword machines= (or locations etc.) must be repeated for each array value. Something like this would work:

const machines = [1, 2];
const locations = [3, 4];

function formatParamArray(array, name) {
  return `${name}=` + array.reduce((acc, cur) => `${acc}&${name}=${cur}`);
}

var url = '@Url.Action("Filter", "ActiveMessages")?'+formatParamArray(machines, 'machines')+'&'+formatParamArray(locations, 'locations');
A. Markóczy
  • 673
  • 7
  • 15