Опубликовать массив JSON для контроллера mvc

Я пытаюсь отправить массив JSON на контроллер MVC. Но независимо от того, что я пытаюсь, все равно 0 или null.

У меня есть эта таблица, которая содержит текстовые поля. Мне нужно, чтобы из всех этих текстовых полей был ID и значение как объект.

Это мой Javascript:

$(document).ready(function () {

    $('#submitTest').click(function (e) {

        var $form = $('form');
        var trans = new Array();

        var parameters = {
            TransIDs: $("#TransID").val(),
            ItemIDs: $("#ItemID").val(),
            TypeIDs: $("#TypeID").val(),
        };
        trans.push(parameters);


        if ($form.valid()) {
            $.ajax(
                {
                    url: $form.attr('action'),
                    type: $form.attr('method'),
                    data: JSON.stringify(parameters),
                    dataType: "json",
                    contentType: "application/json; charset=utf-8",
                    success: function (result) {
                        $('#result').text(result.redirectTo)
                        if (result.Success == true) {
                            return fase;
                        }
                        else {
                            $('#Error').html(result.Html);
                        }
                    },
                    error: function (request) { alert(request.statusText) }
                });
        }
        e.preventDefault();
        return false;
    });
});

Это мой код просмотра:

<table>
        <tr>
            <th>trans</th>
            <th>Item</th>
            <th>Type</th>
        </tr>

        @foreach (var t in Model.Types.ToList())
        {
            {
            <tr>
                <td>                  
                    <input type="hidden" value="@t.TransID" id="TransID" />
                    <input type="hidden" value="@t.ItemID" id="ItemID" />
                    <input type="hidden" value="@t.TypeID" id="TypeID" />
                </td>
            </tr>
           }
        }
</table>

Это контроллер, пытающийся получить данные:

[HttpPost]
public ActionResult Update(CustomTypeModel ctm)
{


   return RedirectToAction("Index");
}

Что я делаю неправильно?

Ответ 1

В коде есть много проблем. Начните с разметки. У вас есть таблица, и внутри каждой строки этой таблицы вы включаете скрытые поля. За исключением того, что вы жестко закодировали атрибут id для этих скрытых элементов, что означает, что вы потенциально можете привести несколько элементов с одним и тем же идентификатором в вашей разметке, что приведет к недействительной разметке.

Итак, начнем с исправления вашей разметки в первую очередь:

@foreach (var t in Model.Types.ToList())
{
    <tr>
        <td>                  
            <input type="hidden" value="@t.TransID" name="TransID" />
            <input type="hidden" value="@t.ItemID" name="ItemID" />
            <input type="hidden" value="@t.TypeID" name="TypeID" />
        </td>
    </tr>
}

Хорошо, теперь у вас есть действительная разметка. Теперь перейдите к событию javascript, который будет запущен при нажатии кнопки submitTest. Если это кнопка отправки формы, я бы рекомендовал вам подписаться на событие .submit формы вместо события .click его кнопки отправки. Причина этого заключается в том, что форма может быть представлена, например, если пользователь нажимает клавишу Enter, когда фокус находится внутри некоторого поля ввода. В этом случае событие click не будет запущено.

Итак:

$(document).ready(function () {
    $('form').submit(function () {
        // code to follow

        return false;
    });
});

Хорошо, далее идет часть, где вам нужно собрать значения скрытых элементов, которые находятся внутри таблицы, и поместить их в объект javascript, который мы впоследствии будем сериализовать JSON и отправить как часть запроса AJAX на сервер.

Отпустите:

var parameters = [];
// TODO: maybe you want to assign an unique id to your table element
$('table tr').each(function() {
    var td = $('td', this);
    parameters.push({
        transId: $('input[name="TransID"]', td).val(),
        itemId: $('input[name="ItemID"]', td).val(),
        typeId: $('input[name="TypeID"]', td).val()
    });
});

До сих пор мы заполнили наши параметры, теперь отправьте их на сервер:

$.ajax({
    url: this.action,
    type: this.method,
    data: JSON.stringify(parameters),
    contentType: 'application/json; charset=utf-8',
    success: function (result) {
        // ...
    },
    error: function (request) { 
        // ...
    }
});

Теперь перейдите на сервер. Как всегда, мы начинаем с определения модели представления:

public class MyViewModel
{
    public string TransID { get; set; }
    public string ItemID { get; set; }
    public string TypeID { get; set; }
}

и действия контроллера, которые возьмут коллекцию этой модели:

[HttpPost]
public ActionResult Update(IList<MyViewModel> model)
{
    ...
}

И вот окончательный код на стороне клиента:

$(function() {
    $('form').submit(function () {
        if ($(this).valid()) {
            var parameters = [];
            // TODO: maybe you want to assign an unique id to your table element
            $('table tr').each(function() {
                var td = $('td', this);
                parameters.push({
                    transId: $('input[name="TransID"]', td).val(),
                    itemId: $('input[name="ItemID"]', td).val(),
                    typeId: $('input[name="TypeID"]', td).val()
                });
            });

            $.ajax({
                url: this.action,
                type: this.method,
                data: JSON.stringify(parameters),
                contentType: 'application/json; charset=utf-8',
                success: function (result) {
                    // ...
                },
                error: function (request) { 
                    // ...
                }
            });
        }
        return false;
    });
});

Очевидно, что если ваша модель просмотра отличается (вы не указали ее в своем вопросе), вам может потребоваться адаптировать код так, чтобы он соответствовал вашей структуре, в противном случае связующее устройство по умолчанию не сможет десериализовать JSON.

Ответ 2

Существует еще один простой способ: с помощью Query String отправить ваши данные. Если вас заинтересовали, ваш текущий подход неверен, поскольку тип данных массива JSON string not CustomTypeModel.

Прежде всего, удалите параметр data ajax. Нам это больше не нужно.

Во-вторых, измените свой контроллер следующим образом:

[HttpPost]
public ActionResult Update(string json)
{
    // this line convert the json to a list of your type, exactly what you want.
    IList<CustomTypeModel> ctm = 
         new JavaScriptSerializer().Deserialize<IList<CustomTypeModel>>(json);

    return RedirectToAction("Index");
}

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

public class CustomTypeModel
{
    // int, or maybe string ... whatever you want.
    public int TransIDs { get; set; }
    public int ItemIDs { get; set; }
    public int TypeIDs { get; set; }
}

Примечание2: Этот подход полезен, если вы хотите отправить данные через строки запроса. Итак, ваш URL-адрес может быть таким:

url: '/controller/action?json=' + JSON.stringify(trans)

Ответ 3

Я думаю, что вы делаете что-то неправильно для мира MVC. Если у вас есть подходящая модель для привязки данных, вам лучше использовать помощники, выходящие из коробки, вместо использования "ручного" JavaScript. Взгляните на HtmlHelper или AjaxHelper, если вам нужны асинхронные вызовы.

И привяжите данные к модели, используя нотацию @Html.TextBoxFor() внутри блока @Html.BeginForm. Это значительно упростит ваш код и уменьшит количество javascript, что намного лучше для обслуживания.

На серверной части вам необходимо реализовать настраиваемое связующее устройство и изменить настройки, чтобы сделать запрос на управление текущим действием контроллера через ваше связующее устройство. Вам понадобится написать некоторый код сервера, но статически типизированный код выглядит проще для кода и тестирования или для меня, и это лучше подходит или для вашего приложения, потому что я предпочитаю, чтобы JavaScript делал то, что он должен делать = > управление пользовательским интерфейсом, но не создание модели для правильного разбора на сервере. Это лучше подходит для принципа единой ответственности.

Смотрите это видео, это простой учебник, как это сделать