Enviar un array (JS) a un controlador MVC5

 ·  ☕ 2 min  ·  ✍️ eiximenis

    Nota: Este post ha sido importado de mi blog de geeks.ms. Es posible que algo no se vea del todo "correctamente". En cualquier caso puedes acceder a la versión original aquí

    Buenas!

    En los foros de MSDN aparece la pregunta sobre como enviar un array JS a un controlador de MVC. La verdad es que hay varias maneras de hacerlo… veamos dos de ellas, ambas muy sencillas.

    En todos los casos el controlador tiene el siguiente método:

    1. public ActionResult Index(long[] data)
    2. {
    3.     return View();
    4. }


    Opción 1 – Mandar el array como un JSON

    Esta es la aproximación que se intenta en el post. Basta el siguiente código en el cliente:

    1. var uri = '@Url.Action("Index", "Home")';
    2. var arr = [4,8,15,16,23,42];
    3. $.ajax({
    4.     url: uri,
    5.     data: JSON.stringify(arr),
    6.     type: 'POST',
    7.     contentType: 'application/json'
    8. });

    Y el array se recibe sin problema alguno en el controlador. En el caso que el controlador declarase el parámetro como IEnumerable funcionaría igual.

    Opción 2 – Mandar el array como x-www-form-urlencoded

    Esto, con jQuery es un poco más complejo. El siguiente código:

    1. var arr = [4,8,15,16,23,42];
    2. $.ajax({
    3.     url: uri,
    4.     data: arr,
    5.     type: 'POST',
    6. });

    Genera una petición incorrecta, debido como jQuery serializa los parámetros. Lo que jQuery manda en el cuerpo de la petición es:

    undefined=&undefined=&undefined=&undefined=&undefined=&undefined=

    Si en la llamada a $.ajax colocamos el parámetro processData a false, entonces jQuery nos genera lo siguiente en el cuerpo de la petición:

    4,8,15,16,23,42

    Aunque ahora si que están los datos, MVC5 no es capaz de procesar los datos en este formato, y recibiremos null en el parámetro.

    La solución es bastante sencilla: debemos convertir el array en un objeto, cuya propiedad sea el array:

    1. var arr = [4,8,15,16,23,42];
    2. $.ajax({
    3.     url: uri,
    4.     data: { data: arr },
    5.     type: 'POST'
    6. });

    Ahora bien, es muy importante que el nombre de la propiedad (data) sea el mismo que el nombre del parámetro en el controlador, ya que el model binder de MVC nos enlazará por nombre.

    En este caso lo que se envia en el cuerpo de la petición que se genera es lo siguiente:

    data%5B%5D=4&data%5B%5D=8&data%5B%5D=15&data%5B%5D=16&data%5B%5D=23&data%5B%5D=42

    Parece un poco críptico, pero ten presente que %5B es la codificación del carácter [ y %5D se corresponde al carácter ]. Así que realmente lo que se envía es:

    data[]=4&data[]=8&data[]=15&data[]=16&data[]=23&data[]=42

    El model binder de MVC es capaz de entender esto sin ningún problema. Al igual que antes sigue funcionando si el controlador recibe un IEnumerable en lugar de un long[] (eso sí, que se llame “data” igual!).

    Saludos!

    Si quieres, puedes invitarme a un café xD

    eiximenis
    ESCRITO POR
    eiximenis
    Compulsive Developer