JQuery Post для ASP.NET API-контроллера

У меня есть форма, которая создается через jquery:

 $.get("/api/get/getListItems", function (data) {
                var table = "";
                table += "<table>";
                $.each(data, function (y, z) {
                    console.log(z);
                    table += '<tr>';
                    $.each(this, function (k, v) {
                        table += '<td><input type="text" name="' + k + '" id="' + k + '" value="' + v + '" /></td>';
                    });
                    table += '<td><input type="checkbox" name="selected" id="selected" /></td>';

                    table += '</tr>';
                });
                table += '<tr><td><input type="submit" id="submit" name="submit" value="Save To Database" /></td></tr>';
                table += '</table>';
                $('#form').html(table);
            });

и он генерирует этот HTML (10 строк полей ввода, 7 столбцов и 1 флажок): http://jsfiddle.net/8zpr2fkL/1/

и я отправляю форму, когда нажата кнопка отправки:

$("#form").submit(function (event) {
        $.post("/api/update/", $("#form").serialize(), alert('success'));
    });

Теперь я передаю данные в контроллер ASP.NET API:

[HttpPost]
        public dynamic Post([FromBody]CellModel cells)
        {
                UpdateClass jobs = new UpdateClass();
                return jobs;
        }

и вот мой класс CellModel:

public class CellModel
    {
        public uint scheduleTaskID { get; set; }
        public string task { get; set; }
        public string baselineDate { get; set; }
        public string scheduledDate { get; set; }
        public string actualDate { get; set; }
        public string finishedDate { get; set; }
        public bool selected { get; set; }

        public override string ToString()
        {
            return scheduleTaskID.ToString();
        }
    }

Моя проблема в том, что когда я нажимаю submit, чтобы отправить данные и поставить точку останова на метод контроллера, количество ячеек равно 0, есть ли что-то, что я здесь отсутствует? Я пытаюсь передать все данные во входном тексте на контроллер. Ничто не передается моему контроллеру. Что я делаю не так?

Это данные, которые я пытаюсь передать через jquery $ ('# form'). Serialize():

scheduleTaskID=194&task=Permit&baselineDate=6%2F23%2F2005+8%3A00%3A00+AM&scheduledDate=6%2F23%2F2005+8%3A00%3A00+AM&actualDate=6%2F23%2F2005+8%3A00%3A00+AM&finishedDate=&scheduleTaskID=195&task=Office+Files&baselineDate=7%2F13%2F2005+8%3A00%3A00+AM&scheduledDate=7%2F13%2F2005+8%3A00%3A00+AM&actualDate=7%2F13%2F2005+8%3A00%3A00+AM&finishedDate=&scheduleTaskID=196&task=Foundation&baselineDate=7%2F27%2F2005+8%3A00%3A00+AM&scheduledDate=7%2F27%2F2005+8%3A00%3A00+AM&actualDate=8%2F13%2F2005+8%3A00%3A00+AM&finishedDate=&scheduleTaskID=197&task=Framing&baselineDate=8%2F5%2F2005+8%3A00%3A00+AM&scheduledDate=8%2F5%2F2005+8%3A00%3A00+AM&actualDate=8%2F23%2F2005+8%3A00%3A00+AM&finishedDate=&scheduleTaskID=198&task=Finishes+Exterior&baselineDate=8%2F26%2F2005+8%3A00%3A00+AM&scheduledDate=8%2F26%2F2005+8%3A00%3A00+AM&actualDate=9%2F14%2F2005+8%3A00%3A00+AM&finishedDate=&scheduleTaskID=199&task=Drywall&baselineDate=9%2F2%2F2005+8%3A00%3A00+AM&scheduledDate=9%2F2%2F2005+8%3A00%3A00+AM&actualDate=9%2F16%2F2005+8%3A00%3A00+AM&finishedDate=&scheduleTaskID=200&task=Flooring&baselineDate=9%2F1%2F2005+8%3A00%3A00+AM&scheduledDate=9%2F1%2F2005+8%3A00%3A00+AM&actualDate=9%2F20%2F2005+8%3A00%3A00+AM&finishedDate=&scheduleTaskID=201&task=General+Finish&baselineDate=9%2F12%2F2005+8%3A00%3A00+AM&scheduledDate=9%2F12%2F2005+8%3A00%3A00+AM&actualDate=&finishedDate=&scheduleTaskID=202&task=Final+PDI&baselineDate=10%2F11%2F2005+8%3A00%3A00+AM&scheduledDate=10%2F11%2F2005+8%3A00%3A00+AM&actualDate=&finishedDate=&scheduleTaskID=203&task=Permit&baselineDate=4%2F6%2F2005+8%3A00%3A00+AM&scheduledDate=4%2F6%2F2005+8%3A00%3A00+AM&actualDate=4%2F6%2F2005+8%3A00%3A00+AM&finishedDate=

ОБНОВИТЬ

Я изменился:

$("#form").submit(function (event) {
            $.post("/api/update/", $("#form").serialize(), alert('success'));
        });

в

$("#form").submit(function (event) {
        var array = [];
        $('#form > table > tbody  > tr').each(function (elem) {
            var item = {};
            item.scheduleTaskID = $(this).find("td > #scheduleTaskID").val();
            item.task = $(this).find("td > #task").val();
            item.baselineDate = $(this).find("td > #baselineDate").val();
            item.scheduledDate = $(this).find("td > #scheduledDate").val();
            item.actualDate = $(this).find("td > #actualDate").val();
            item.finishedDate = $(this).find("td > #finishedDate").val();
            item.selected = $(this).find("td > #selected").val();
            array.push(item);
        });
        console.log(JSON.stringify(array));
        $.post("/api/update/", JSON.stringify(array), alert('success'), 'json');
    });

в моем консольном журнале мои данные выглядят так:

[{"scheduleTaskID":"203","task":"Permit","baselineDate":"4/6/2005 8:00:00 AM","scheduledDate":"4/6/2005 8:00:00 AM","actualDate":"4/6/2005 8:00:00 AM","finishedDate":"","selected":"on"},{"scheduleTaskID":"195","task":"Office Files","baselineDate":"7/13/2005 8:00:00 AM","scheduledDate":"7/13/2005 8:00:00 AM","actualDate":"7/13/2005 8:00:00 AM","finishedDate":"","selected":"on"},{"scheduleTaskID":"196","task":"Foundation","baselineDate":"7/27/2005 8:00:00 AM","scheduledDate":"7/27/2005 8:00:00 AM","actualDate":"8/13/2005 8:00:00 AM","finishedDate":"","selected":"on"},{"scheduleTaskID":"197","task":"Framing","baselineDate":"8/5/2005 8:00:00 AM","scheduledDate":"8/5/2005 8:00:00 AM","actualDate":"8/23/2005 8:00:00 AM","finishedDate":"","selected":"on"},{"scheduleTaskID":"198","task":"Finishes Exterior","baselineDate":"8/26/2005 8:00:00 AM","scheduledDate":"8/26/2005 8:00:00 AM","actualDate":"9/14/2005 8:00:00 AM","finishedDate":"","selected":"on"},{"scheduleTaskID":"199","task":"Drywall","baselineDate":"9/2/2005 8:00:00 AM","scheduledDate":"9/2/2005 8:00:00 AM","actualDate":"9/16/2005 8:00:00 AM","finishedDate":"","selected":"on"},{"scheduleTaskID":"200","task":"Flooring","baselineDate":"9/1/2005 8:00:00 AM","scheduledDate":"9/1/2005 8:00:00 AM","actualDate":"9/20/2005 8:00:00 AM","finishedDate":"","selected":"on"},{"scheduleTaskID":"201","task":"General Finish","baselineDate":"9/12/2005 8:00:00 AM","scheduledDate":"9/12/2005 8:00:00 AM","actualDate":"","finishedDate":"","selected":"on"},{"scheduleTaskID":"202","task":"Final PDI","baselineDate":"10/11/2005 8:00:00 AM","scheduledDate":"10/11/2005 8:00:00 AM","actualDate":"","finishedDate":"","selected":"on"},{"scheduleTaskID":"203","task":"Permit","baselineDate":"4/6/2005 8:00:00 AM","scheduledDate":"4/6/2005 8:00:00 AM","actualDate":"4/6/2005 8:00:00 AM","finishedDate":"","selected":"on"},{}]

и в моем API-интерфейсе ASP.NET я изменил свой метод на это:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Web.Http;
using MvcApplication1.Models;

namespace MvcApplication1.Controllers
{
    public class UpdateController : ApiController
    {
        [HttpPost]
        public dynamic Post(List<CellModel> cells)
        {
                UpdateClass jobs = new UpdateClass();
                //jobs.PostScheduledTasks(cells);
                return cells;
        }

    }
}

Я поставил точку останова в начале метода Post и когда он попал в точку останова, он говорит, что ячейки Count = 0.. Я вижу сетевой вызов, только если я вернул false после моего почтового вызова и ответ пуст [] Почему это данные, которые не передаются моему контроллеру, потому что форма создается jquery?

ОБНОВИТЬ

По-прежнему нет решения, я посмотрел на свою сеть, назову это AM, а код состояния - 301:

enter image description here

Ответы

Ответ 1

Не используйте $.post использовать пост ajax и задавать тип содержимого "application/json; charset = utf-8"

var data = JSON.stringify(array);
$.ajax({
  url:"/api/update/",
  type:"POST",
  data:data,
  contentType:"application/json; charset=utf-8",
  dataType:"json",
  success: function(data){
    console.log(data);
  }
});

проблема в том, что вам нужно сказать веб-серверу, что вы отправляете json и невозможен с помощью $.post

Это действительно нормально, и я тоже борется с этим (а иногда и забываю), здесь вы можете видеть, что вам нужно использовать $.ajax

JQuery - Как сделать $.post() использовать contentType = application/json?

Ответ 2

Хотя у вас есть альтернативный подход @dariogriffo, я хочу дать вам полное решение, используя ваш первоначальный подход с $.post.

Ваш первоначальный подход с сериализацией формы был правильным, поэтому следующий код верен:

$("#form").submit(function (event) {
   $.post("/api/update/", $("#form").serialize(), alert('success'));
});

Однако это не работало, потому что ваша динамическая форма не соответствует соглашениям об именах для полей ввода, ожидаемых с помощью связующего объекта модели MVC по умолчанию ASP.NET MVC, и, как следствие, ваша сериализованная форма не была чем-то, что связующее устройство по умолчанию могло быть привязано к вашей модели cells. Вот почему вы не получали никаких ячеек в контроллере при выполнении POST.

Чтобы выяснить, что это означает, ASP.NET ожидает, что каждое поле ввода, соответствующее свойству модели, будет иметь следующий формат имени, если вы отправляете на обычный контроллер MVC 5:

actionattributename[index].propertyname

Если вы отправляете на контроллер Web API 2, это должно быть:

[index].propertyname

Поскольку ваш атрибут action имеет именованные cells и у него есть свойство scheduledTaskID, и вы отправляете его на контроллер WebAPI, один из ваших входов будет выглядеть так:

<input type="text" name="[0].scheduleTaskID" id="scheduleTaskID" value="194">

Есть еще несколько правил, связанных с структурированием формы, чтобы сделать ее связанной. Вы можете найти хорошее сообщение в блоге об этом здесь:

http://haacked.com/archive/2008/10/23/model-binding-to-a-list.aspx/

Если вы следовали этому соглашению по форме, вы могли бы отправить свою сериализованную форму своему контроллеру, ожидая List<CellModel> cells не используя подход JSON, который намного дороже, как это было предложено в других ответах.

Ниже приведен скрипт с образцом, правильно структурированным с помощью правил привязки по умолчанию Web API 2:

http://jsfiddle.net/8zpr2fkL/12/

Вы можете попробовать использовать $.post эту форму, используя $.post для своего веб-контроллера api, и он должен работать как шарм!

Ответ 3

Я знаю, это уже разрешено с использованием .ajax вместо .post. Я думал об обмене этим, поскольку я решил это использовать .post. Как упоминалось выше, поскольку он размещается с типом Content-Type:application/x-www-form-urlencoded; charset=UTF-8 Content-Type:application/x-www-form-urlencoded; charset=UTF-8, cells параметров в методе post будут содержать count = 0.

Чтобы решить эту проблему, вам необходимо вручную захватить объект запроса и получить данные для публикации, а затем выполнить десериализацию и получить объект в виде List<CellModel>. Я использовал весь опубликованный код OP и только что изменил метод post как показано ниже, и он сработал.

[HttpPost]
public dynamic Post(List<CellModel> cells)
{
    string content = string.Empty;
    if (HttpContext.Current.Request.InputStream.CanSeek)
    {
        HttpContext.Current.Request.InputStream.Seek(0, System.IO.SeekOrigin.Begin);
    }
    using (System.IO.StreamReader reader = new System.IO.StreamReader(HttpContext.Current.Request.InputStream))
    {
        content = reader.ReadToEnd();
    }
    if (!string.IsNullOrEmpty(content))
    {
        // Deserialize and operate over cells.
        try
        {
            var obj = Newtonsoft.Json.JsonConvert.DeserializeObject(content, typeof(List<CellModel>));
        }
        catch (Exception ex)
        {
            return ex;
        }

    }
    return cells;
}

Вот что я получаю во время отладки.

enter image description here

enter image description here