Як опублікувати масив складних об’єктів за допомогою JSON, jQuery до контролера ASP.NET MVC?


92

Мій поточний код виглядає наступним чином. Як я можу передати свій масив контролеру і які параметри повинен приймати мій дію контролера?

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

Мій метод дії контролера виглядає так

public JsonResult SaveOrUpdate(IList<PageDesignWidget> widgets)

Відповіді:


84

Я знайшов рішення. Я використовую рішення Steve Gentile, jQuery та ASP.NET MVC - надсилання JSON до Action - Revisited .

Мій код подання ASP.NET MVC виглядає так:

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

і моя дія контролера прикрашена спеціальним атрибутом

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

Код спеціального атрибута можна знайти тут (посилання порушено).

Оскільки посилання порушено, це код для 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 від Json.NET

Посилання: Серіалізація та десеріалізація JSON за допомогою Json.NET


Чудово виглядає - Повідомлення в блозі та посилання на власні коди атрибутів більше не працюють - чи можете ви перепостити?
littlechris

4
Це рішення вимагає змін на стороні клієнта та сервера. Я знаю, що вам це потрібно було давно, але я також можу надати посилання на інший підхід, який використовує простий плагін jQuery, який дає змогу перетворити будь-який об'єкт Javascript у форму, яку за замовчуванням зв'язувач моделі розуміє і модель прив'язує до параметрів. Фільтри не потрібні. erraticdev.blogspot.com/2010/12/… Я не знаю, як ви вирішили помилки перевірки, але у мене є рішення і для цього: erraticdev.blogspot.com/2010/11/…
Роберт Корітнік,

3
Чи можете ви вказати джерело / походження JavaScriptConvert.DeserializeObject?
Matthieu

Це бібліотека Newsonoft Json - якщо ви відкриєте менеджер пакунків nuget і здійсните пошук на Newtonsoft, вона з’явиться для вас (тепер це 2016). Можливо, це зараз очевидно, але на випадок, якщо хтось задається питанням.
Робб Садлер,

22

Фільтри дій, jquery stringify, bleh ...

Пітер, ця функціональність є рідною для MVC. Це одна з речей, яка робить MVC таким чудовим.

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

І в дії,

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

Працює як шарм:

введіть тут опис зображення

Якщо ви використовуєте jQuery 1.4+, тоді ви хочете переглянути традиційний режим:

jQuery.ajaxSettings.traditional = true;

Як описано тут: http://www.dovetailsoftware.com/blogs/kmiller/archive/2010/02/24/jquery-1-4-breaks-asp-net-mvc-actions-with-array-parameters

Це працює навіть для складних об'єктів. Якщо ви зацікавлені, вам слід ознайомитися з документацією MVC про прив’язку моделі: http://msdn.microsoft.com/en-us/library/dd410405.aspx


1
Ви можете мати рацію, але підшивка моделі JSON є новою для MVC3, і питання було задано в 2008 році, коли це не підтримувалось. Варто зазначити у вашій відповіді.
Piotr Owsiak

3
Як це приклад передачі масиву складних об’єктів ?
DuckMaestro

Це не так, але приклад все ще застосовується (MVC 3+). Поки ваші імена параметрів збігаються з моделлю, яку ви очікуєте, у вас не буде проблем.
J. Mitchell

Ключовим тут є створення об’єкта JSON з ім’ям параметра методу („ідентифікатори”), а потім розміщення масиву складних об’єктів у ньому. Крім того, зробіть третій параметр «істинним», і ви подбаєте про традиційний режим.
redwards510

11

В .NET4.5, MVC 5немає необхідності для віджетів.

Javascript:

об'єкт в JS: введіть тут опис зображення

механізм, який робить пост.

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

C #

Об'єкти:

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

Контролер:

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

Об'єкт отримано:

введіть тут опис зображення

Сподіваюся, це заощадить ваш час.


8

Ближче до другої половини API створення REST за допомогою ASP.NET MVC, який говорить як JSON, так і звичайний XML , цитую:

Тепер нам потрібно прийняти корисне навантаження JSON та XML, доставлене через HTTP POST. Іноді ваш клієнт може захотіти завантажити колекцію об’єктів одним кадром для пакетної обробки. Отже, вони можуть завантажувати об’єкти у форматі JSON або XML. В ASP.NET MVC немає вбудованої підтримки для автоматичного синтаксичного аналізу розміщених JSON або XML та автоматичного зіставлення з параметрами Action. Отже, я написав фільтр, який це робить ".

Потім він реалізує фільтр дій, який відображає JSON до об'єктів C # із показаним кодом.


Я просто писав свій анзар. Але я все одно опублікую ;-)
АТ

7

Спочатку завантажте цей код JavaScript, JSON2.js , який допоможе нам серіалізувати об’єкт у рядок.

У моєму прикладі я публікую рядки jqGrid через 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");
            }
        }
    });

Тепер на контролері:

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

Створіть клас JsonFilter (завдяки посиланням на 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;
            }
        }
    }

Створіть інший клас, щоб фільтр міг проаналізувати рядок JSON до фактичного об'єкта, яким можна керувати: Цей клас comissionsJS - це всі рядки мого jqGrid.

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

Сподіваюся, цей приклад допоможе проілюструвати, як опублікувати складний об’єкт.


0

Боже мій. не потрібно робити нічого особливого. лише в розділі допису виконайте такі дії:

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

На сервері використовуйте це:

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

це посилання допоможе вам зробити ...


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

    }
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.