Pase la matriz a la acción mvc a través de AJAX

123

Estoy tratando de pasar una matriz (o IEnumerable) de entradas desde AJAX a una acción MVC y necesito un poco de ayuda.

el javascript es

$.get('/controller/MyAction', { vals: arrayOfValues }, function (data) {...

y la acción del controlador es

public ActionResult MyAction(IEnumerable<int> arrayOfValues )

Por el momento, la solicitud está formateada como

controller/MyAction?_=1301503418429&arrayOfValues[]=491&arrayOfValues[]=368&arrayOfValues[]=235&arrayOfValues[]=437

Así que ya casi estoy allí, si quito los corchetes obtengo la respuesta correcta. ¿Cómo debería pasar esa matriz a mi get para que el controlador pueda reconocer lo que es?

Muchas gracias por su ayuda

Dave

Dave
fuente

Respuestas:

149

Establezca la propiedad tradicional en verdadero antes de realizar la llamada. es decir:

jQuery.ajaxSettings.traditional = true

$.get('/controller/MyAction', { vals: arrayOfValues }, function (data) {... 
Chandu
fuente
3
¡gracias! ¿podría describir las diferencias entre ajax tradicional y no tradicional? Me gustaría entender mejor lo que estoy haciendo al resto de mi aplicación.
Tom Beech
55
También puede agregar la configuración tradicional a una sola llamada. Entonces no afectará al resto
Gluip
1
Esta respuesta es correcta, pero si prefiere configurar "tradicional" para una sola llamada, marque la respuesta @RionWilliams. Votando por los dos. ¡Gracias!
kzfabi
@ Tom Beech A partir de jQuery 1.4, el método $ .param () serializa objetos profundos de forma recursiva para acomodar los lenguajes y marcos modernos de scripting como PHP y Ruby on Rails. Puede deshabilitar esta funcionalidad globalmente estableciendo jQuery.ajaxSettings.traditional = true;
Alexey Shevelyov
Ninguna de estas respuestas funcionó para mí (¿quizás porque mi controlador era un controlador API?), Pero encontré mi solución en la siguiente respuesta SO: stackoverflow.com/a/11100414/1751792
Lopsided
119

He tenido problemas en el pasado al intentar realizar una POST (no estoy seguro de si eso es exactamente lo que está haciendo, pero recuerdo que al pasar una matriz, tradicional debe establecerse en verdadero .

 var arrayOfValues = new Array();

 //Populate arrayOfValues 
 $.ajax({ 
      type: "POST",
      url: "<%= Url.Action("MyAction","Controller")%>",
      traditional: true,
      data: { 'arrayOfValues': arrayOfValues }              
 });
Rion Williams
fuente
44
Esto es mucho mejor que simplemente configurarlo a ciegas globalmente en un archivo web.config, como sugieren algunas personas. El otro tiene su propio conjunto de buenas ocasiones, pero la suya debería ser la solución predeterminada.
Panzercrisis
Esto es solo enviar datos como parámetro a ActionResult, ¿invocará el código Inside ActionResult? Por ejemplo, si hay algún código para insertar valores de matriz en la base de datos, ¿se ejecutará ese código?
Saurabh
Esto resolvió exactamente lo que necesitaba. Mis matrices seguían volviendo nulas en mi controlador hasta que agregué esto y las obtuve en mi controlador como: IEnumerable <string> array
SeanMC
52

Una respuesta bastante tardía pero diferente a las ya presentes aquí:

Si, en lugar de $.ajaxutilizar las funciones abreviadas $.geto $.postdesea, puede pasar matrices de esta manera:


Taquigrafía GET

var array = [1, 2, 3, 4, 5];
$.get('/controller/MyAction', $.param({ data: array }, true), function(data) {});


// Action Method
public void MyAction(List<int> data)
{
    // do stuff here
}

Taquigrafía POST

var array = [1, 2, 3, 4, 5];
$.post('/controller/MyAction', $.param({ data: array }, true), function(data) {});


// Action Method
[HttpPost]
public void MyAction(List<int> data)
{
    // do stuff here
}


Notas:

  • El parámetro booleano en $.parames para la traditionalpropiedad, que DEBE ser truepara que esto funcione .
Engancharse
fuente
2
Gracias por el consejo sobre la propiedad tradicional. No pude entender por qué mi parámetro C # era nulo. Descubrí que el tipo "int []" también funcionará en el método de acción C #.
Dan Randolph
9

Deberías poder hacer esto bien:

$.ajax({
   url: 'controller/myaction',
   data: JSON.stringify({
      myKey: myArray
   }),
   success: function(data) { /* Whatever */ }
});

Entonces su método de acción sería así:

public ActionResult(List<int> myKey)
{
    // Do Stuff
}

Para usted, parece que solo necesita clasificar en cadena sus valores. El JSONValueProvider en MVC lo convertirá de nuevo en un IEnumerable para usted.

Tejs
fuente
Gracias por la respuesta, pero creo que parece que necesito establecer tradicional en verdadero. He votado porque creo que esto también funcionaría.
Dave
9

La respuesta para usar la opción 'tradicional' es correcta. Solo proporciono más información de fondo para esto que desea obtener más información.

De la documentación de jQuery:

A partir de jQuery 1.8, el método $ .param () ya no usa jQuery.ajaxSettings.traditional como su configuración predeterminada y por defecto será falso.

También puede leer más aquí: http://michaelsync.net/2012/04/04/tips-asp-net-mvc-javascriptserializer-3-questions-and-3-answers y http://haacked.com/archive /2008/10/23/model-binding-to-a-list.aspx

HTH

Tom Gerken
fuente
2

SI TODO LO DEMÁS FALLA...

Ninguna de las otras respuestas aquí resolvió mi problema. Intenté hacer una llamada al método GET desde JavaScript a un controlador MVC Web API, y enviar una matriz de enteros como parámetro dentro de esa solicitud. Intenté todas las soluciones aquí, pero el parámetro en mi controlador seguía siendo NULL (o Nothing para ustedes, usuarios de VB).

Finalmente encontré mi solución en una publicación SO diferente , y en realidad fue muy simple: solo agregue la [FromUri]anotación antes del parámetro de matriz en el controlador ( también tuve que hacer la llamada usando la configuración AJAX "tradicional" para evitar anotaciones entre paréntesis ). Vea a continuación el código real que utilicé en mi aplicación.


Firma del controlador:

Firma del controlador NOTA: La anotación en C # sería [FromUri]


JavaScript:

$.get('/api/InventoryApi/GetBalanceField', $.param({productIds: [42], inventoryFormId: 5493, inventoryBalanceType: 'Beginning'},true)).done(function(data) {console.log(data);});

Cadena de URL real:

http://randomhostname/api/InventoryApi/GetBalanceField?productIds=42&inventoryFormId=5493&inventoryBalanceType=Beginning
Desequilibrado
fuente
2

Un poco tarde aquí, pero podría usar la solución de SNag más en $ .ajax (). Aquí está el código si ayudaría a alguien:

var array = [1, 2, 3, 4, 5];

$.ajax({
    type: "GET",
    url: '/controller/MyAction',
    data: $.param({ data: array}, true),
    contentType: 'application/json; charset=utf-8',
    success: function (data) {
    },
    error: function (x, y, z) {
    }
});

// Action Method
public void MyAction(List<int> data)
{
    // do stuff here
}
Saket
fuente
1

Si está migrando a ASP.NET Core MVC desde .Net Framework MVC como yo, las cosas han cambiado ligeramente. La llamada ajax debe estar en el objeto sin formato utilizando stringify, por lo que en lugar de pasar datos del { vals: arrayOfValues }mismo debe ser el JSON.stringify(arrayOfValues)siguiente:

$.ajax({
   url: 'controller/myaction',
   data: JSON.stringify(arrayOfValues),
   success: function(data) { /* Whatever */ }
});

El otro cambio que se ha realizado en ASP.NET Core es evitar la falsificación de solicitudes entre sitios, por lo que para las llamadas a una acción MVC desde un método ajax, el [FromBody]atributo debe aplicarse al parámetro de acción de la siguiente manera:

public ActionResult MyAction([FromBody] IEnumerable<int> arrayOfValues )
Michael Armitage
fuente
¡Gracias, esto fue increíblemente útil después de que cualquier otra permutación de formas de enviar los datos fallara!
NibblyPig
0

Si está utilizando ASP.NET Core MVC y necesita manejar los corchetes (en lugar de usar la opción "tradicional" jQuery), la única opción que he encontrado es compilar manualmente IEnumerableen el método de control.

string arrayKey = "p[]=";
var pArray = HttpContext.Request.QueryString.Value
    .Split('&')
    .Where(s => s.Contains(arrayKey))
    .Select(s => s.Substring(arrayKey.Length));
x5657
fuente
0

Trabajo con asp.net core 2.2 y jquery y tengo que enviar un objeto complejo ('clase principal') desde una vista a un controlador con campos de datos simples y algunos arreglos.
Tan pronto como agregué la matriz en la definición de 'clase principal' de c # (ver más abajo) y envié la matriz (llena correctamente) sobre ajax (post), todo el objeto era nulo en el controlador.
Primero, pensé, el "tradicional: verdadero" que faltaba en mi llamada ajax fue la razón, pero este no es el caso.
En mi caso, la razón fue la definición en la clase principal de c #.
En la 'clase principal', tuve:

public List<EreignisTagNeu> oEreignistageNeu { get; set; }

y EreignisTagNeu se definió como:

public class EreignisTagNeu
{
 public int iHME_Key { get; set; } 
}

Tuve que cambiar la definición en la 'clase principal' a:

 public List<int> oEreignistageNeu { get; set; }

Ahora funciona.
Entonces ... para mí parece que asp.net core tiene un problema (con post), si la lista de una matriz no está completamente definida en la 'clase principal'.
Nota: en mi caso, esto funciona con o sin "tradicional: verdadero" para la llamada ajax

FredyWenger
fuente
-3

Necesita convertir Array en cadena:

//arrayOfValues = [1, 2, 3];  
$.get('/controller/MyAction', { arrayOfValues: "1, 2, 3" }, function (data) {...

esto funciona incluso en forma de int, long o string

public ActionResult MyAction(int[] arrayOfValues )
dr.Crow
fuente
Esto ni siquiera es la sintaxis correcta para enviar una matriz al servidor. Simplemente está pasando un objeto y suponiendo que es una matriz, que nunca será el caso con lo que ha proporcionado, que es un STRING.
Twister1002