Bagaimana saya bisa memposting array string ke ASP.NET MVC Controller tanpa formulir?

185

Saya membuat aplikasi kecil untuk belajar sendiri ASP.NET MVC dan JQuery, dan salah satu halaman adalah daftar item di mana beberapa dapat dipilih. Kemudian saya ingin menekan tombol dan mengirim Daftar (atau sesuatu yang setara) ke controller saya yang berisi id item yang dipilih, menggunakan fungsi JQuery's Post.

Saya berhasil mendapatkan array dengan id dari elemen yang dipilih, dan sekarang saya ingin mempostingnya. Salah satu cara saya bisa melakukan ini adalah memiliki formulir dummy di halaman saya, dengan nilai tersembunyi, dan kemudian mengatur nilai tersembunyi dengan item yang dipilih, dan memposting formulir itu; ini terlihat crufty.

Apakah ada cara yang lebih bersih untuk mencapai ini, dengan mengirim array langsung ke controller? Saya sudah mencoba beberapa hal berbeda tetapi sepertinya pengontrol tidak dapat memetakan data yang diterimanya. Berikut kodenya sejauh ini:

function generateList(selectedValues) {
   var s = {
      values: selectedValues //selectedValues is an array of string
   };
   $.post("/Home/GenerateList", $.toJSON(s), function() { alert("back") }, "json");
}

Dan Controller saya terlihat seperti ini

public ActionResult GenerateList(List<string> values)
{
    //do something
}

Yang berhasil saya dapatkan adalah "null" di parameter controller ...

Ada tips?

rodbv
sumber
Meskipun, Anda dapat mengakses data yang sama dengan menggunakanRequest["values[]"]
Tocco

Jawaban:

247

Saya mengubah respons saya untuk memasukkan kode untuk aplikasi pengujian yang saya lakukan.

Pembaruan: Saya telah memperbarui jQuery untuk mengatur pengaturan 'tradisional' menjadi true sehingga ini akan berfungsi lagi (per jawaban @DustinDavis ').

Pertama javascript:

function test()
{
    var stringArray = new Array();
    stringArray[0] = "item1";
    stringArray[1] = "item2";
    stringArray[2] = "item3";
    var postData = { values: stringArray };

    $.ajax({
        type: "POST",
        url: "/Home/SaveList",
        data: postData,
        success: function(data){
            alert(data.Result);
        },
        dataType: "json",
        traditional: true
    });
}

Dan ini kode di kelas controller saya:

public JsonResult SaveList(List<String> values)
{
    return Json(new { Result = String.Format("Fist item in list: '{0}'", values[0]) });
}

Ketika saya memanggil fungsi javascript itu, saya mendapatkan peringatan yang mengatakan "Item pertama dalam daftar: 'item1'". Semoga ini membantu!

MrDustpan
sumber
3
Baik saya menemukan jawaban ini, sekarang saya dapat mengirim berbagai Guid's dan Action menerimanya ke Daftar <Guid>. Terima kasih
Tx3
43
Ada dua hal penting yang perlu diperhatikan di sini. 1) dataType: "json" 2.) Tradisional: benar. Tanpa mereka string array tidak akan diteruskan ke metode aksi
Thanigainathan
1
Catatan yang dataType: 'JSON'menyebabkan jQuery mencoba mem-parsing respons sebagai JSON, dan akan kesalahan jika itu bukan JSON yang valid.
sennett
8
@Thanigainathan dataType: 'json'adalah untuk tipe kembali dan tidak perlu mengirim array ke Action. contentType: "application/json; charset=utf-8", adalah satu-satunya, tetapi dalam beberapa kasus seperti ini tidak diperlukan.
Ruchan
1
@emzero usevar postData = { id: 45, [{myClassProp1: 1, myClassProp2: 2}, {}...], anotherParam: "some string" };
Nick M
108

FYI: JQuery mengubah cara mereka membuat serial data pos.

http://forum.jquery.com/topic/nested-param-serialization

Anda harus mengatur pengaturan 'Tradisional' menjadi true, selain bijaksana

{ Values : ["1", "2", "3"] }

akan keluar sebagai

Values[]=1&Values[]=2&Values[]=3

dari pada

Values=1&Values=2&Values=3
Dustin Davis
sumber
8
Ini adalah sesuatu yang membuatku menggosok kepalaku untuk sementara waktu. pengaturan $.ajax({ ..., traditional: true});akan membantu untuk kembali ke serialisasi tradisional.
juhan_h
Saya membutuhkan ini untuk rute ASP.NET MVC untuk mengkonsumsi js array nilai string dengan benar.
BrandonG
Jawaban Anda sangat membantu. Saya memiliki situasi yang sama tetapi dengan ints. Ketika saya gunakan traditional: true, itu berfungsi, jawaban dan tautan Anda menjelaskan alasannya . Ini juga berfungsi ketika saya menggunakan type: "POST", tanpa menggunakan traditional: true. Mengapa demikian? Bisakah Anda jelaskan. FYI Saya menggunakan Asp.Net Mvc.
barnes
Apakah ada cara di ASP.NET untuk mem-parsing array anonim seperti ini tanpa indeks? Nilai [] = 1 & Nilai [] = 2 & Nilai [] = 3
Charles Owen
24

Terima kasih semuanya atas jawabannya. Solusi cepat lainnya adalah menggunakan metode jQuery.param dengan parameter tradisional disetel ke true untuk mengonversi objek JSON menjadi string:

$.post("/your/url", $.param(yourJsonObject,true));
Evgenii
sumber
Bekerja dengan baik dan sangat cocok untuk saya karena saya menggunakan $ .post () bukannya $ .ajax (). Terima kasih !
AFract
9

Jangan memposting data sebagai array. Untuk mengikat ke daftar, pasangan kunci / nilai harus diserahkan dengan nilai yang sama untuk setiap kunci.

Anda seharusnya tidak memerlukan formulir untuk melakukan ini. Anda hanya perlu daftar pasangan kunci / nilai, yang dapat Anda sertakan dalam panggilan ke $ .post.

Craig Stuntz
sumber
3
Terima kasih. Url yang diperbarui adalah: haacked.com/archive/2008/10/23/model-binding-to-a-list.aspx
Wiebe Tijsma
6

Di .NET4.5,MVC 5

Javascript:

objek di JS: masukkan deskripsi gambar di sini

mekanisme yang melakukan posting.

    $('.button-green-large').click(function() {
        $.ajax({
            url: 'Quote',
            type: "POST",
            dataType: "json",
            data: JSON.stringify(document.selectedProduct),
            contentType: 'application/json; charset=utf-8',
        });
    });

C #

Benda:

public class WillsQuoteViewModel
{
    public string Product { get; set; }

    public List<ClaimedFee> ClaimedFees { get; set; }
}

public partial class ClaimedFee //Generated by EF6
{
    public long Id { get; set; }
    public long JourneyId { get; set; }
    public string Title { get; set; }
    public decimal Net { get; set; }
    public decimal Vat { get; set; }
    public string Type { get; set; }

    public virtual Journey Journey { get; set; }
}

Pengendali:

[AcceptVerbs(HttpVerbs.Post)]
public ActionResult Quote(WillsQuoteViewModel data)
{
....
}

Objek yang diterima:

masukkan deskripsi gambar di sini

Semoga ini menghemat waktu Anda.

Matas Vaitkevicius
sumber
4

Implementasi lain yang juga bekerja dengan daftar objek, bukan hanya string:

JS:

var postData = {};
postData[values] = selectedValues ;

$.ajax({
    url: "/Home/SaveList",
    type: "POST",
    data: JSON.stringify(postData),
    dataType: "json",
    contentType: "application/json; charset=utf-8",
    success: function(data){
        alert(data.Result);
    }
});

Dengan asumsi bahwa 'selectedValues' adalah Array of Objects.

Dalam controller parameternya adalah daftar ViewModels yang sesuai.

public JsonResult SaveList(List<ViewModel> values)
{    
    return Json(new { 
          Result = String.Format("Fist item in list: '{0}'", values[0].Name) 
    });
}
dpopov
sumber
1

Seperti yang saya diskusikan di sini ,

Jika Anda ingin meneruskan objek JSON kustom ke aksi MVC maka Anda dapat menggunakan solusi ini, itu berfungsi seperti pesona.

public string GetData() {
  // InputStream contains the JSON object you've sent
  String jsonString = new StreamReader(this.Request.InputStream).ReadToEnd();

  // Deserialize it to a dictionary
  var dic =
    Newtonsoft.Json.JsonConvert.DeserializeObject < Dictionary < String,
    dynamic >> (jsonString);

  string result = "";

  result += dic["firstname"] + dic["lastname"];

  // You can even cast your object to their original type because of 'dynamic' keyword
  result += ", Age: " + (int) dic["age"];

  if ((bool) dic["married"])
    result += ", Married";

  return result;
}

Manfaat nyata dari solusi ini adalah Anda tidak perlu mendefinisikan kelas baru untuk setiap kombinasi argumen dan di samping itu, Anda dapat melemparkan objek Anda ke tipe aslinya dengan mudah.

Anda dapat menggunakan metode pembantu seperti ini untuk memfasilitasi pekerjaan Anda:

public static Dictionary < string, dynamic > GetDic(HttpRequestBase request) {
  String jsonString = new StreamReader(request.InputStream).ReadToEnd();
  return Newtonsoft.Json.JsonConvert.DeserializeObject < Dictionary < string, dynamic >> (jsonString);
}
Mohsen Afshin
sumber
0

Anda dapat mengatur parameter global dengan

jQuery.ajaxSettings.traditional = true;
mr_squall
sumber