Làm cách nào để đăng một mảng các đối tượng phức tạp với JSON, jQuery lên ASP.NET MVC Controller?


92

Mã hiện tại của tôi trông giống như sau. Làm cách nào để chuyển mảng của tôi cho bộ điều khiển và hành động bộ điều khiển của tôi phải chấp nhận loại tham số nào?

function getplaceholders() {
    var placeholders = $('.ui-sortable');
    var result = new Array();
    placeholders.each(function() {
        var ph = $(this).attr('id');
        var sections = $(this).find('.sort');
        var section;

        sections.each(function(i, item) {
            var sid = $(item).attr('id');

            result.push({ 'SectionId': sid, 'Placeholder': ph, 'Position': i });
        });
    });
    alert(result.toString());
    $.post(
        '/portal/Designer.mvc/SaveOrUpdate',
        result,
        function(data) {
            alert(data.Result);
        }, "json");
};

Phương thức hành động bộ điều khiển của tôi trông giống như

public JsonResult SaveOrUpdate(IList<PageDesignWidget> widgets)

Câu trả lời:


84

Tôi đã tìm thấy một giải pháp. Tôi sử dụng một giải pháp của Steve Gentile, jQuery và ASP.NET MVC - gửi JSON đến một Hành động - Đã xem lại .

Mã chế độ xem ASP.NET MVC của tôi trông giống như sau:

function getplaceholders() {
        var placeholders = $('.ui-sortable');
        var results = new Array();
        placeholders.each(function() {
            var ph = $(this).attr('id');
            var sections = $(this).find('.sort');
            var section;

            sections.each(function(i, item) {
                var sid = $(item).attr('id');
                var o = { 'SectionId': sid, 'Placeholder': ph, 'Position': i };
                results.push(o);
            });
        });
        var postData = { widgets: results };
        var widgets = results;
        $.ajax({
            url: '/portal/Designer.mvc/SaveOrUpdate',
            type: 'POST',
            dataType: 'json',
            data: $.toJSON(widgets),
            contentType: 'application/json; charset=utf-8',
            success: function(result) {
                alert(result.Result);
            }
        });
    };

và hành động của bộ điều khiển của tôi được trang trí bằng một thuộc tính tùy chỉnh

[JsonFilter(Param = "widgets", JsonDataType = typeof(List<PageDesignWidget>))]
public JsonResult SaveOrUpdate(List<PageDesignWidget> widgets

Bạn có thể tìm thấy mã cho thuộc tính tùy chỉnh tại đây (liên kết hiện đã bị hỏng).

Vì liên kết bị hỏng, đây là mã cho JsonFilterAttribute

public class JsonFilter : ActionFilterAttribute
{
    public string Param { get; set; }
    public Type JsonDataType { get; set; }
    public override void OnActionExecuting(ActionExecutingContext filterContext)
    {
        if (filterContext.HttpContext.Request.ContentType.Contains("application/json"))
        {
            string inputContent;
            using (var sr = new StreamReader(filterContext.HttpContext.Request.InputStream))
            {
                inputContent = sr.ReadToEnd();
            }
            var result = JsonConvert.DeserializeObject(inputContent, JsonDataType);
            filterContext.ActionParameters[Param] = result;
        }
    }
}

JsonConvert.DeserializeObject đến từ Json.NET

Liên kết: Serializing và Deserializing JSON với Json.NET


Trông tuyệt vời - Bài đăng trên blog và các liên kết mã thuộc tính tùy chỉnh không hoạt động nữa - bạn có thể đăng lại không?
littlechris

4
Giải pháp này yêu cầu các thay đổi ở phía máy khách và máy chủ. Tôi biết bạn đã cần điều này từ lâu, nhưng tôi cũng có thể cung cấp một liên kết đến một cách tiếp cận khác, sử dụng một plugin jQuery đơn giản giúp bạn có thể chuyển đổi bất kỳ đối tượng Javascript nào thành một dạng mà trình kết nối mô hình mặc định hiểu và mô hình liên kết với các tham số. Không cần bộ lọc. faildev.blogspot.com/2010/12/… Tôi không biết bạn đã giải quyết các lỗi xác thực như thế nào nhưng tôi cũng có giải pháp cho điều đó: faildev.blogspot.com/2010/11/…
Robert Koritnik

3
Bạn có thể cung cấp nguồn / nguồn gốc của JavaScriptConvert.DeserializeObject không?
Matthieu

Đó là thư viện Newtonsoft Json - nếu bạn mở trình quản lý gói nuget và tìm kiếm trên Newtonsoft, nó sẽ hiển thị cho bạn (bây giờ là năm 2016). Có lẽ điều này bây giờ là hiển nhiên, nhưng trong trường hợp có ai đó đang thắc mắc.
Robb Sadler

22

Bộ lọc hành động, jquery stringify, bleh ...

Peter, chức năng này có nguồn gốc từ MVC. Đó là một trong những điều khiến MVC trở nên tuyệt vời.

$.post('SomeController/Batch', { 'ids': ['1', '2', '3']}, function (r) {
   ...
});

Và trong hành động,

[HttpPost]
public ActionResult Batch(string[] ids)
{
}

Hoạt động như một sự quyến rũ:

nhập mô tả hình ảnh ở đây

Nếu bạn đang sử dụng jQuery 1.4+, thì bạn muốn xem xét thiết lập chế độ truyền thống:

jQuery.ajaxSettings.traditional = true;

Như được mô tả ở đây: http://www.dovetailsoftware.com/blogs/kmiller/archive/2010/02/24/jquery-1-4-breaks-asp-net-mvc-actions-with-array-parameters

Điều này thậm chí hoạt động cho các đối tượng phức tạp. Nếu quan tâm, bạn nên xem tài liệu MVC về Model Binding: http://msdn.microsoft.com/en-us/library/dd410405.aspx


1
bạn có thể đúng, nhưng chất kết dính mô hình JSON là mới đối với MVC3 và câu hỏi đã được đặt ra vào năm 2008 khi điều này không được hỗ trợ. Nó sẽ được đề cập trong câu trả lời của bạn.
Piotr Owsiak

3
Đây là một ví dụ về truyền một mảng các đối tượng phức tạp như thế nào?
DuckMaestro

Nó không phải nhưng ví dụ vẫn áp dụng (MVC 3+). Vì vậy, miễn là tên thông số của bạn khớp với mô hình bạn mong đợi, bạn sẽ không gặp bất kỳ vấn đề nào.
J. Mitchell,

Chìa khóa ở đây là tạo một đối tượng JSON với tên tham số phương thức ("id") và sau đó đặt mảng các đối tượng phức tạp trong đó. Ngoài ra, hãy đặt tham số thứ ba là "true" và bạn sẽ quan tâm đến chế độ truyền thống.
redwards510

11

Trong .NET4.5, MVC 5không cần vật dụng.

Javascript:

đối tượng trong JS: nhập mô tả hình ảnh ở đây

cơ chế mà đăng.

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

C #

Các đối tượng:

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

Bộ điều khiển:

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

Đối tượng nhận được:

nhập mô tả hình ảnh ở đây

Hy vọng điều này giúp bạn tiết kiệm thời gian.


8

Trong nửa sau của Tạo REST API bằng ASP.NET MVC nói cả JSON và XML thuần túy , để trích dẫn:

Bây giờ chúng ta cần chấp nhận tải trọng JSON và XML, được phân phối qua HTTP POST. Đôi khi khách hàng của bạn có thể muốn tải lên một bộ sưu tập các đối tượng trong một lần để xử lý hàng loạt. Vì vậy, họ có thể tải lên các đối tượng bằng cách sử dụng định dạng JSON hoặc XML. Không có hỗ trợ gốc trong ASP.NET MVC để tự động phân tích cú pháp JSON hoặc XML đã đăng và tự động ánh xạ đến các tham số Hành động. Vì vậy, tôi đã viết một bộ lọc làm được điều đó. "

Sau đó, anh ta triển khai một bộ lọc hành động ánh xạ các đối tượng JSON tới C # với mã được hiển thị.


Tôi chỉ đang viết anwser của tôi. Nhưng dù sao thì tôi cũng sẽ đăng nó ;-)
JSC

7

Đầu tiên hãy tải xuống mã JavaScript này, JSON2.js , sẽ giúp chúng tôi tuần tự hóa đối tượng thành một chuỗi.

Trong ví dụ của tôi, tôi đăng các hàng của jqGrid qua Ajax:

    var commissions = new Array();
    // Do several row data and do some push. In this example is just one push.
    var rowData = $(GRID_AGENTS).getRowData(ids[i]);
    commissions.push(rowData);
    $.ajax({
        type: "POST",
        traditional: true,
        url: '<%= Url.Content("~/") %>' + AREA + CONTROLLER + 'SubmitCommissions',
        async: true,
        data: JSON.stringify(commissions),
        dataType: "json",
        contentType: 'application/json; charset=utf-8',
        success: function (data) {
            if (data.Result) {
                jQuery(GRID_AGENTS).trigger('reloadGrid');
            }
            else {
                jAlert("A problem ocurred during updating", "Commissions Report");
            }
        }
    });

Bây giờ trên bộ điều khiển:

    [HttpPost]
    [JsonFilter(Param = "commissions", JsonDataType = typeof(List<CommissionsJs>))]
    public ActionResult SubmitCommissions(List<CommissionsJs> commissions)
    {
        var result = dosomething(commissions);
        var jsonData = new
        {
            Result = true,
            Message = "Success"
        };
        if (result < 1)
        {
            jsonData = new
            {
                Result = false,
                Message = "Problem"
            };
        }
        return Json(jsonData);
    }

Tạo một lớp JsonFilter (nhờ tham chiếu JSC).

    public class JsonFilter : ActionFilterAttribute
    {
        public string Param { get; set; }
        public Type JsonDataType { get; set; }
        public override void OnActionExecuting(ActionExecutingContext filterContext)
        {
            if (filterContext.HttpContext.Request.ContentType.Contains("application/json"))
            {
                string inputContent;
                using (var sr = new StreamReader(filterContext.HttpContext.Request.InputStream))
                {
                    inputContent = sr.ReadToEnd();
                }
                var result = JsonConvert.DeserializeObject(inputContent, JsonDataType);
                filterContext.ActionParameters[Param] = result;
            }
        }
    }

Tạo một lớp khác để bộ lọc có thể phân tích cú pháp chuỗi JSON thành đối tượng có thể thao tác thực tế: Lớp comissionsJS này là tất cả các hàng của jqGrid của tôi.

    public class CommissionsJs
    {
        public string Amount { get; set; }

        public string CheckNumber { get; set; }

        public string Contract { get; set; }
        public string DatePayed { get; set; }
        public string DealerName { get; set; }
        public string ID { get; set; }
        public string IdAgentPayment { get; set; }
        public string Notes { get; set; }
        public string PaymentMethodName { get; set; }
        public string RowNumber { get; set; }
        public string AgentId { get; set; }
    }

Tôi hy vọng ví dụ này sẽ giúp minh họa cách đăng một đối tượng phức tạp.


0

Ôi chúa ơi. không cần phải làm bất cứ điều gì đặc biệt. chỉ trong phần bài đăng của bạn làm như sau:

    $.post(yourURL,{ '': results})(function(e){ ...}

Trong máy chủ sử dụng cái này:

   public ActionResult MethodName(List<yourViewModel> model){...}

liên kết này giúp bạn hoàn thành ...


-1
    [HttpPost]
    public bool parseAllDocs([FromBody] IList<docObject> data)
    {
        // do stuff

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