Passar matriz para mvc Action via AJAX

123

Estou tentando passar uma matriz (ou IEnumerable) de ints do AJAX para uma ação MVC e preciso de uma ajudinha.

o javascript é

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

e a ação do controlador é

public ActionResult MyAction(IEnumerable<int> arrayOfValues )

No momento, a solicitação está formatada como

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

Então, estou quase lá. Se tirar os colchetes, recebo a resposta correta. Como devo passar essa matriz para o meu get para que o controlador possa reconhecer o que é?

Muito obrigado pela sua ajuda

Dave

Dave
fonte

Respostas:

149

Defina a propriedade tradicional como true antes de fazer a chamada. ou seja:

jQuery.ajaxSettings.traditional = true

$.get('/controller/MyAction', { vals: arrayOfValues }, function (data) {... 
Chandu
fonte
3
obrigado! você poderia descrever as diferenças entre o ajax tradicional e o não tradicional? gostaria de entender melhor o que estou fazendo no restante do meu aplicativo.
Tom Beech
5
você também pode adicionar a configuração tradicional a uma única chamada. Então ele não vai afetar o resto
Gluip
1
Esta resposta está correta, mas se você preferir definir "tradicional" para uma única chamada, verifique a resposta @RionWilliams. Votação de ambos. Obrigado!
kzfabi
@Tom Beech No jQuery 1.4, o método $ .param () serializa objetos profundos recursivamente para acomodar linguagens e estruturas de script modernas, como PHP e Ruby on Rails. Você pode desativar essa funcionalidade globalmente, definindo jQuery.ajaxSettings.traditional = true;
Alexey Shevelyov 04/11
Nenhuma dessas respostas funcionou para mim (talvez porque meu controlador era um controlador de API?), Mas eu encontrei minha solução na seguinte resposta do SO: stackoverflow.com/a/11100414/1751792
Lopsided
119

Eu tive problemas no passado ao tentar executar um POST (não tenho certeza se é exatamente isso que você está fazendo, mas eu lembro ao passar uma matriz, o tradicional deve ser definido como verdadeiro .

 var arrayOfValues = new Array();

 //Populate arrayOfValues 
 $.ajax({ 
      type: "POST",
      url: "<%= Url.Action("MyAction","Controller")%>",
      traditional: true,
      data: { 'arrayOfValues': arrayOfValues }              
 });
Rion Williams
fonte
4
Isso é muito melhor do que apenas defini-lo cegamente globalmente em um arquivo web.config, como algumas pessoas sugerem. O outro tem seu próprio conjunto de boas ocasiões, mas o seu deve ser a solução padrão.
Panzercrisis
Isso é apenas o envio de dados como parâmetro para o ActionResult; ele invocará o código Inside ActionResult? Por exemplo, se houver algum código para inserir valores de matriz no banco de dados, esse código será executado?
Saurabh
Isso resolveu exatamente o que eu precisava. Meus matrizes continuou voltando como nulo no meu controlador até que eu adicionei este e tenho-os no meu controlador como: IEnumerable <string> array
SeanMC
52

Bastante tarde, mas diferenteResposta das que já estão presentes aqui:

Se, em vez de $.ajaxvocê desejar usar funções abreviadas $.getou $.post, você pode passar matrizes desta maneira:


Shorthand 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
}

POST taquigráfico

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:

  • O parâmetro booleano $.paramé para a traditionalpropriedade, que DEVE ser truepara que isso funcione .
SNag
fonte
2
Obrigado pela dica sobre a propriedade tradicional. Não consegui descobrir por que meu parâmetro C # era nulo. Eu descobri que o tipo "int []" também funcionará no método C # Action.
21714 Dan Danolph
9

Você deve conseguir fazer isso muito bem:

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

Então seu método de ação seria assim:

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

Para você, parece que você só precisa especificar seus valores. O JSONValueProvider no MVC converterá isso novamente em um IEnumerable para você.

Tejs
fonte
Obrigado pela resposta, mas acho que preciso definir o tradicional como verdadeiro. Votou como eu acho que isso iria funcionar também.
Dave
9

A resposta para usar a opção 'tradicional' está correta. Estou apenas fornecendo mais informações básicas para quem deseja aprender mais.

Na documentação do jQuery:

A partir do jQuery 1.8, o método $ .param () não usa mais o jQuery.ajaxSettings.traditional como configuração padrão e o padrão é false.

Você também pode ler mais aqui: http://michaelsync.net/2012/04/05/tips-asp-net-mvc-javascriptserializer-3-questions-and-3-answers e http://haacked.com/archive /2008/10/23/model-binding-to-a-list.aspx

HTH

Tom Gerken
fonte
2

SE TODO O RESTO FALHAR...

Nenhuma das outras respostas aqui resolveu meu problema. Eu estava tentando fazer uma chamada de método GET do JavaScript para um controlador de MVC Web API e enviar uma matriz de números inteiros como um parâmetro dentro dessa solicitação. Eu tentei todas as soluções aqui, mas ainda assim o parâmetro no meu controlador estava chegando NULL (ou Nothing for you VB users).

Acabei encontrando minha solução em um post SO diferente , e era realmente muito simples: basta adicionar a [FromUri]anotação antes do parâmetro array no controlador ( eu também precisei fazer a chamada usando a configuração AJAX "tradicional" para evitar anotações entre colchetes ). Veja abaixo o código real que usei no meu aplicativo.


Assinatura do Controlador:

Assinatura do Controlador NOTA: A anotação em C # seria [FromUri]


JavaScript:

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

Sequência de URL real:

http://randomhostname/api/InventoryApi/GetBalanceField?productIds=42&inventoryFormId=5493&inventoryBalanceType=Beginning
Assimétrico
fonte
2

Um pouco tarde aqui, mas eu poderia usar a solução do SNag ainda mais em $ .ajax (). Aqui está o código se isso ajudaria alguém:

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
fonte
1

Se você estiver migrando para o ASP.NET Core MVC do .Net Framework MVC como eu, as coisas mudaram um pouco. A chamada ajax deve estar no objeto bruto usando stringify, portanto, em vez de transmitir dados { vals: arrayOfValues }, deve ser JSON.stringify(arrayOfValues)o seguinte:

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

A outra alteração feita no ASP.NET Core é impedir a falsificação de solicitações entre sites. Para chamadas para uma ação MVC a partir de um método ajax, o [FromBody]atributo deve ser aplicado ao parâmetro action da seguinte maneira:

public ActionResult MyAction([FromBody] IEnumerable<int> arrayOfValues )
Michael Armitage
fonte
Obrigado, isso foi incrivelmente útil depois que todas as outras permutações de maneiras de enviar os dados falharam!
NibblyPig
0

Se você estiver usando o ASP.NET Core MVC e precisar lidar com colchetes (em vez de usar a opção "tradicional" do jQuery)), a única opção que encontrei é criar manualmente IEnumerableo método no contoller.

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

Eu trabalho com o asp.net core 2.2 e jquery e tenho que enviar um objeto complexo ('classe principal') de uma visão para um controlador com campos de dados simples e algumas matrizes.
Assim que adicionei a matriz na definição de 'classe principal' do c # (veja abaixo) e enviei a matriz (preenchida corretamente) sobre ajax (post), todo o objeto foi nulo no controlador.
Primeiro, pensei, a falta de "tradicional: verdadeiro" na minha chamada ajax foi o motivo, mas esse não é o caso.
No meu caso, o motivo foi a definição na classe principal do c #.
Na 'classe principal', eu tinha:

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

e EreignisTagNeu foi definido como:

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

Eu tive que mudar a definição na 'classe principal' para:

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

Agora funciona.
Então ... para mim, parece que o núcleo do asp.net tem um problema (com a postagem), se a lista de uma matriz não estiver completamente definida na 'classe principal'.
Nota: No meu caso, isso funciona com ou sem "tradicional: true" para a chamada ajax

FredyWenger
fonte
-3

Você precisa converter Array em string:

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

isso funciona mesmo na forma de int, long ou string

public ActionResult MyAction(int[] arrayOfValues )
dr.Crow
fonte
Essa sintaxe nem está correta para enviar uma matriz para o servidor. Você está apenas passando um objeto e assumindo que é uma matriz, que nunca será o caso com o que você forneceu, que é uma STRING.
precisa saber é o seguinte