Как отправить массив сложных объектов с помощью 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

Я нашел решение. Я использую решение Стива Джентиле, 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 03
4
Это решение требует изменений на стороне клиента и сервера. Я знаю, что вам это было нужно давно, но я также могу предоставить ссылку на другой подход, в котором используется простой плагин jQuery, который позволяет преобразовать любой объект Javascript в форму, которую связывает модель по умолчанию и связывает ее с параметрами. Никаких фильтров не требуется. erraticdev.blogspot.com/2010/12/… Я не знаю, как вы решали ошибки проверки, но у меня есть решение и для этого: erraticdev.blogspot.com/2010/11/…
Роберт Коритник,
3
Можете ли вы указать источник / происхождение JavaScriptConvert.DeserializeObject?
Matthieu
Это библиотека Newtonsoft 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+). Пока имена ваших параметров совпадают с ожидаемой моделью, у вас не будет никаких проблем.
Дж. Митчелл
Ключевым моментом здесь является создание объекта JSON с именем параметра метода («ids»), а затем размещение в нем массива сложных объектов. Кроме того, сделайте третий параметр «истинным», и вы позаботитесь о традиционном режиме.
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

Ко второй половине создания REST API с использованием ASP.NET MVC, который использует как JSON, так и простой XML , процитируем:

Теперь нам нужно принять полезную нагрузку JSON и XML, доставленную через HTTP POST. Иногда ваш клиент может захотеть загрузить коллекцию объектов за один раз для пакетной обработки. Таким образом, они могут загружать объекты в формате JSON или XML. В ASP.NET MVC нет встроенной поддержки для автоматического анализа опубликованного JSON или XML и автоматического сопоставления с параметрами действия. Итак, я написал фильтр, который это делает ".

Затем он реализует фильтр действий, который сопоставляет JSON с объектами C # с показанным кодом.

анонимный
источник
Я как раз писал свой ответ. Но все равно выложу ;-)
JSC
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; }
    }

Надеюсь, этот пример поможет проиллюстрировать, как опубликовать сложный объект.

Санчитос
источник
-1
    [HttpPost]
    public bool parseAllDocs([FromBody] IList<docObject> data)
    {
        // do stuff

    }
JsonW
источник
-1

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

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

На сервере используйте это:

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

эта ссылка поможет вам сделать ...

Махди Могими
источник