Enviar un array (JS) a un controlador MVC5

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<long> 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<long> en lugar de un long[] (eso sí, que se llame “data” igual!).

Saludos!

Deja un comentario

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *