Cách thích hợp để sử dụng AJAX Post trong jquery để chuyển mô hình từ chế độ xem MVC3 được gõ mạnh


100

Tôi là một lập trình viên web mới vào nghề, vì vậy xin hãy tha thứ cho tôi nếu một số "biệt ngữ" của tôi không đúng. Tôi có một dự án sử dụng ASP.NET sử dụng khuôn khổ MVC3.

Tôi đang làm việc trên chế độ xem quản trị nơi quản trị viên sẽ sửa đổi danh sách thiết bị. Một trong những chức năng là nút "cập nhật" mà tôi muốn sử dụng jquery để chỉnh sửa động mục nhập trên trang web sau khi gửi bài đăng đến bộ điều khiển MVC.

Tôi cho rằng cách tiếp cận này là "an toàn" trong một cài đặt quản trị duy nhất, nơi có rất ít lo ngại về việc trang web không đồng bộ với cơ sở dữ liệu.

Tôi đã tạo một dạng xem được gõ mạnh và hy vọng sẽ chuyển dữ liệu mô hình đến điều khiển MVC bằng cách sử dụng bài đăng AJAX.

Trong bài đăng sau, tôi đã tìm thấy một cái gì đó tương tự như những gì tôi đang làm: JQuery Ajax và ASP.NET MVC3 gây ra các tham số rỗng

Tôi sẽ sử dụng mẫu mã từ bài đăng trên.

Mô hình:

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

Bộ điều khiển:

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

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

script trong View:

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

Tôi vẫn chưa có cơ hội sử dụng những thứ trên. Nhưng tôi đã tự hỏi liệu đây có phải là phương pháp "tốt nhất" để chuyển dữ liệu mô hình trở lại điều khiển MVC bằng AJAX không?

Tôi có nên lo lắng về việc lộ thông tin mô hình không?

Câu trả lời:


72

Bạn có thể bỏ qua khai báo var và stringify. Nếu không, điều đó sẽ hoạt động tốt.

$.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");
    }
});

Cảm ơn vì đã chỉ ra sự điều chỉnh nhỏ. Có bất kỳ mối quan tâm nào với việc tiết lộ cấu trúc mô hình từ quan điểm bảo mật không?
John Stone

Đối với tôi, không có gì rõ ràng là một vấn đề an ninh. Tuy nhiên, nếu bạn thực sự lo lắng về điều đó, bạn luôn có thể tạo một chất kết dính mô hình tùy chỉnh ở mặt mvc.
Craig M

8
Điều này đã thất bại đối với tôi. Tôi đã phải sử dụng JSON.stringify ({...}) để lệnh gọi hoạt động trong MVC5.
Johncl

Tôi nhận thấy rằng tôi phải làm như vậy khi làm việc với bộ điều khiển API. Câu trả lời này đã được viết cách đây 4 năm, trước khi các bộ điều khiển API tồn tại.
Craig M

1
chúa ơi, tôi đã có dataType thay vì contentType, cái đó luôn luôn có tôi !!
Phil

175

Tôi đã tìm thấy 3 cách để thực hiện điều này:

Lớp 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; }
}

Hoạt động:

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

JavaScript bạn có thể thực hiện theo ba cách:

1) Chuỗi truy vấn:

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

Dữ liệu ở đây là một chuỗi.

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

2) Mảng đối tượng:

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

Dữ liệu ở đây là một mảng các cặp khóa / giá trị:

=[{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'
});

Dữ liệu ở đây là một chuỗi JSON được tuần tự hóa. Lưu ý rằng tên phải khớp với tên tham số trong máy chủ !!

='{"addressInfo":{"Address1":"blah","Address2":"blah","City":"blah","State":"blah", "ZipCode", "blah", "Country", "blah"}}'

1
Chỉ cần xem qua câu trả lời tuyệt vời, thấu đáo này đã giải quyết các câu hỏi mà tôi chưa biết mình đã có. +1, cảm ơn!
SeanKilleen

# 2 là những gì tôi đang tìm kiếm. Đây nên là câu trả lời.
TheGeekZn

EDIT: phải sử dụng data: $('input, textarea, select').serialize(),cho tôi để làm việc.
TheGeekZn,

Này Jazaret !! làm thế nào để chuyển ngày sang mô hình với cách tiếp cận thứ 3 ??
Guruprasad Rao

1
Xin lỗi vì sự chậm trễ @GuruprasadRao Để chuyển một ngày, bạn có thể đặt ngày và giờ là một chuỗi trong mã javascript và MVC sẽ dịch nó sang một đối tượng DateTime.
Jazaret

12

Đây là cách nó làm việc cho tôi:

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

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

8

những gì bạn có đều ổn - tuy nhiên để tiết kiệm một số lần nhập, bạn có thể chỉ cần sử dụng cho dữ liệu của mình

dữ liệu: $ ('# formId'). serialize ()

xem http://www.ryancoughlin.com/2009/05/04/how-to-use-jquery-to-serialize-ajax-forms/ để biết thêm chi tiết, cú pháp khá cơ bản.


Để sử dụng hàm serialize, tôi hiểu rằng mỗi thành viên của lớp cần được sử dụng trong một đối tượng biểu mẫu. Nếu điều đó đúng, tôi có thể là SOL.
John Stone

1
ah ya .. nếu không bạn không thể sử dụng serialize sau đó. mặc dù vậy bạn luôn có thể thao tác DOM và tạo một biểu mẫu với các phần tử đó và tuần tự hóa nó - nhưng ... có thể sẽ gọn gàng hơn khi chỉ nhập các trường theo cách thủ công.
Adam Tuliper - MSFT

@TahaRehmanSiddiqui serialize thực sự hoạt động trong IE, điều gì không hoạt động? Bạn có mắc lỗi gì không?
Adam Tuliper - MSFT

mỗi tài sản của mô hình của tôi là sắp ra rỗng
Taha Rehman Siddiqui

@TahaRehmanSiddiqui có "tên" của các trường biểu mẫu của bạn khớp với tên của thuộc tính mô hình của bạn không?
MongooseNX

0

Nếu sử dụng MVC 5, hãy đọc giải pháp này!

Tôi biết câu hỏi được gọi riêng cho MVC 3, nhưng tôi tình cờ tìm thấy trang này với MVC 5 và muốn đăng một giải pháp cho bất kỳ ai khác trong tình huống của tôi. Tôi đã thử các giải pháp trên, nhưng chúng không hiệu quả với tôi, Bộ lọc hành động không bao giờ đạt được và tôi không thể tìm ra lý do. Tôi đang sử dụng phiên bản 5 trong dự án của mình và đã kết thúc với bộ lọc hành động sau:

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";
    }
}

- Ghi chú using System.Web.Mvcusing System.Web.Mvc.Filters, không phải các httpthư viện (Tôi nghĩ đó là một trong những thứ đã thay đổi với MVC v5. -

Sau đó, chỉ cần áp dụng bộ lọc [ValidateJSONAntiForgeryHeader] cho hành động của bạn (hoặc bộ điều khiển) và nó sẽ được gọi chính xác.

Trong trang bố cục của tôi ngay phía trên, </body>tôi có@AntiForgery.GetHtml();

Cuối cùng, trong trang Razor của tôi, tôi thực hiện lệnh gọi ajax như sau:

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
});

1
Bạn có đang truy xuất tất cả các giá trị biểu mẫu của mình theo cách thủ công không? Tại sao không data: $("#the-form").serialize()?
Sinjai

1
@Sinjai Tôi sẽ phải xem lại mã của mình, nhưng tôi tin rằng tôi cũng đang thực hiện một số xử lý khác trong đó. ".serialize ()" cũng sẽ làm việc nếu bạn chỉ cần các giá trị đầu vào
blubberbo

Đừng lo lắng, tôi chỉ tò mò.
Sinjai
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.