Cara yang tepat untuk menggunakan AJAX Post di jquery untuk meneruskan model dari tampilan MVC3 yang diketik dengan kuat

100

Saya seorang programmer web pemula jadi mohon maafkan saya jika beberapa "jargon" saya tidak benar. Saya punya proyek menggunakan ASP.NET menggunakan kerangka MVC3.

Saya sedang mengerjakan tampilan admin di mana admin akan mengubah daftar peralatan. Salah satu fungsinya adalah tombol "update" yang ingin saya gunakan jquery untuk mengedit entri pada halaman web secara dinamis setelah mengirim posting ke pengontrol MVC.

Saya menganggap pendekatan ini "aman" dalam pengaturan admin tunggal di mana ada sedikit kekhawatiran tentang halaman web yang tidak sinkron dengan database.

Saya telah membuat tampilan yang sangat diketik dan berharap untuk meneruskan data model ke kontrol MVC menggunakan posting AJAX.

Di posting berikut, saya menemukan sesuatu yang mirip dengan apa yang saya ingin lakukan: JQuery Ajax dan ASP.NET MVC3 menyebabkan parameter null

Saya akan menggunakan contoh kode dari posting di atas.

Model:

public class AddressInfo 
{
    public string Address1 { get; set; }
    public string Address2 { get; set; }
    public string City { get; set; }
    public string State { get; set; }
    public string ZipCode { get; set; }
    public string Country { get; set; }
}

Pengontrol:

public class HomeController : Controller
{
    public ActionResult Index()
    {
        return View();
    }

    [HttpPost]
    public ActionResult Check(AddressInfo addressInfo)
    {
        return Json(new { success = true });
    }
}

skrip dalam Tampilan:

<script type="text/javascript">
var ai = {
    Address1: "423 Judy Road",
    Address2: "1001",
    City: "New York",
    State: "NY",
    ZipCode: "10301",
    Country: "USA"
};

$.ajax({
    url: '/home/check',
    type: 'POST',
    data: JSON.stringify(ai),
    contentType: 'application/json; charset=utf-8',
    success: function (data.success) {
        alert(data);
    },
    error: function () {
        alert("error");
    }
});
</script>

Saya belum sempat menggunakan cara di atas. Tapi saya bertanya-tanya apakah ini adalah metode "terbaik" untuk meneruskan data model kembali ke kontrol MVC menggunakan AJAX?

Haruskah saya khawatir tentang pengungkapan informasi model?

John Stone
sumber

Jawaban:

72

Anda bisa melewati deklarasi var dan stringify. Jika tidak, itu akan bekerja dengan baik.

$.ajax({
    url: '/home/check',
    type: 'POST',
    data: {
        Address1: "423 Judy Road",
        Address2: "1001",
        City: "New York",
        State: "NY",
        ZipCode: "10301",
        Country: "USA"
    },
    contentType: 'application/json; charset=utf-8',
    success: function (data) {
        alert(data.success);
    },
    error: function () {
        alert("error");
    }
});
Craig M
sumber
Terima kasih telah menunjukkan sedikit penyesuaian. Apakah ada kekhawatiran dengan mengekspos struktur model dari sudut pandang keamanan?
John Stone
Tidak ada hal mencolok yang menonjol sebagai masalah keamanan bagi saya. Jika Anda benar-benar mengkhawatirkannya, Anda selalu dapat membuat pengikat model kustom di sisi MVC.
Craig M
8
Ini gagal bagi saya. Saya harus menggunakan JSON.stringify ({...}) agar panggilan berfungsi di MVC5.
Johncl
Saya perhatikan bahwa saya harus melakukan hal yang sama saat bekerja dengan pengontrol API. Jawaban ini ditulis 4 tahun yang lalu, sebelum pengontrol API ada.
Craig M
1
Sialan, saya punya dataType dan bukan contentType, yang selalu membuat saya !!
Phil
175

Saya menemukan 3 cara untuk menerapkan ini:

Kelas C #:

public class AddressInfo {
    public string Address1 { get; set; }
    public string Address2 { get; set; }
    public string City { get; set; }
    public string State { get; set; }
    public string ZipCode { get; set; }
    public string Country { get; set; }
}

Tindakan:

[HttpPost]
public ActionResult Check(AddressInfo addressInfo)
{
    return Json(new { success = true });
}

JavaScript Anda dapat melakukannya dengan tiga cara:

1) String Kueri:

$.ajax({
    url: '/en/Home/Check',
    data: $('#form').serialize(),
    type: 'POST',
});

Data di sini adalah string.

"Address1=blah&Address2=blah&City=blah&State=blah&ZipCode=blah&Country=blah"

2) Larik Objek:

$.ajax({
    url: '/en/Home/Check',
    data: $('#form').serializeArray(),
    type: 'POST',
});

Data di sini adalah larik pasangan kunci / nilai:

=[{name: 'Address1', value: 'blah'}, {name: 'Address2', value: 'blah'}, {name: 'City', value: 'blah'}, {name: 'State', value: 'blah'}, {name: 'ZipCode', value: 'blah'}, {name: 'Country', value: 'blah'}]

3) JSON:

$.ajax({
      url: '/en/Home/Check',
      data: JSON.stringify({ addressInfo:{//missing brackets
          Address1: $('#address1').val(),
          Address2: $('#address2').val(),
          City: $('#City').val(),
          State: $('#State').val(),
          ZipCode: $('#ZipCode').val()}}),
      type: 'POST',
      contentType: 'application/json; charset=utf-8'
});

Data di sini adalah string JSON serial. Perhatikan bahwa nama tersebut harus sesuai dengan nama parameter di server !!

='{"addressInfo":{"Address1":"blah","Address2":"blah","City":"blah","State":"blah", "ZipCode", "blah", "Country", "blah"}}'
Jazaret
sumber
1
Baru saja menemukan jawaban yang hebat dan menyeluruh ini yang memecahkan pertanyaan yang belum saya ketahui. +1, terima kasih!
SeanKilleen
# 2 adalah apa yang saya cari. Ini harus menjadi jawabannya.
TheGeekZn
EDIT: harus menggunakan data: $('input, textarea, select').serialize(),milikku untuk bekerja.
TheGeekZn
Hei Jazaret !! bagaimana cara melewati tanggal ke model dengan pendekatan ke-3 ??
Guruprasad Rao
1
Maaf atas keterlambatan @GuruprasadRao Untuk melewatkan tanggal Anda dapat memiliki tanggal & waktu menjadi string dalam kode javascript dan MVC akan menerjemahkannya ke objek DateTime.
Jazaret
12

Inilah cara kerjanya untuk saya:

$.post("/Controller/Action", $("#form").serialize(), function(json) {       
        // handle response
}, "json");

[HttpPost]
public ActionResult TV(MyModel id)
{
    return Json(new { success = true });
}
Sanchitos
sumber
8

apa yang Anda miliki baik-baik saja - namun untuk menghemat beberapa pengetikan, Anda dapat menggunakannya untuk data Anda

data: $ ('# formId'). serialize ()

lihat http://www.ryancoughlin.com/2009/05/04/how-to-use-jquery-to-serialize-ajax-forms/ untuk detailnya, sintaksnya cukup mendasar.

Adam Tuliper - MSFT
sumber
Untuk menggunakan fungsi serialisasi, pemahaman saya adalah bahwa setiap anggota kelas perlu digunakan dalam objek formulir. Jika itu benar, saya mungkin SOL.
John Stone
1
ah ya .. jika tidak Anda tidak bisa menggunakan serialize lalu. Anda selalu dapat memanipulasi DOM dan membuat formulir dengan elemen-elemen itu dan menserialisasinya - tapi ... kemungkinan akan lebih bersih jika kolom diketik secara manual saja.
Adam Tuliper - MSFT
@TahaRehmanSiddiqui serialize memang berfungsi di IE, apa yang tidak berhasil? Apakah Anda mendapatkan kesalahan?
Adam Tuliper - MSFT
setiap properti model saya keluar nol
Taha Rehman Siddiqui
@TahaRehmanSiddiqui apakah 'nama' bidang formulir Anda cocok dengan nama properti model Anda?
MongooseNX
0

Jika menggunakan MVC 5 baca solusi ini!

Saya tahu pertanyaan yang secara khusus memanggil MVC 3, tetapi saya menemukan halaman ini dengan MVC 5 dan ingin memposting solusi untuk orang lain dalam situasi saya. Saya mencoba solusi di atas, tetapi tidak berhasil untuk saya, Filter Tindakan tidak pernah tercapai dan saya tidak tahu mengapa. Saya menggunakan versi 5 dalam proyek saya dan berakhir dengan filter tindakan berikut:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using System.Web.Mvc.Filters;

namespace SydHeller.Filters
{
    public class ValidateJSONAntiForgeryHeader : FilterAttribute, IAuthorizationFilter
    {
        public void OnAuthorization(AuthorizationContext filterContext)
        {
            string clientToken = filterContext.RequestContext.HttpContext.Request.Headers.Get(KEY_NAME);
            if (clientToken == null)
            {
                throw new HttpAntiForgeryException(string.Format("Header does not contain {0}", KEY_NAME));
            }

            string serverToken = filterContext.HttpContext.Request.Cookies.Get(KEY_NAME).Value;
            if (serverToken == null)
            {
                throw new HttpAntiForgeryException(string.Format("Cookies does not contain {0}", KEY_NAME));
            }

            System.Web.Helpers.AntiForgery.Validate(serverToken, clientToken);
        }

        private const string KEY_NAME = "__RequestVerificationToken";
    }
}

- Catat using System.Web.Mvcdan using System.Web.Mvc.Filters, bukanhttp pustaka (menurut saya itu adalah salah satu hal yang berubah dengan MVC v5. -

Kemudian terapkan filter saja [ValidateJSONAntiForgeryHeader] ke tindakan Anda (atau pengontrol) dan itu akan dipanggil dengan benar.

Di halaman tata letak saya tepat di atas, </body>saya punya@AntiForgery.GetHtml();

Akhirnya, di halaman Razor saya, saya melakukan panggilan ajax sebagai berikut:

var formForgeryToken = $('input[name="__RequestVerificationToken"]').val();

$.ajax({
  type: "POST",
  url: serviceURL,
  contentType: "application/json; charset=utf-8",
  dataType: "json",
  data: requestData,
  headers: {
     "__RequestVerificationToken": formForgeryToken
  },
     success: crimeDataSuccessFunc,
     error: crimeDataErrorFunc
});
blubberbo.dll
sumber
1
Apakah Anda mengambil semua nilai formulir Anda secara manual? Mengapa tidak data: $("#the-form").serialize()?
Sinjai
1
@Sinjai Saya harus melihat kode saya lagi, tetapi saya yakin saya juga melakukan pemrosesan lain di sana. ".serialize ()" juga akan berfungsi jika Anda hanya membutuhkan nilai input
blubberbo
Jangan khawatir, saya hanya penasaran.
Sinjai