it-roy-ru.com

Используйте jQuery для публикации данных в метод действия MVC

Я пытаюсь опубликовать данные, используя JQuery Ajax для действий MVC, используя подход ниже. Но внутри контроллера все свойства модели всегда null. Не уверен, что мне здесь не хватает.

.CSHTML  

<form id="MyForm">
<input name="PersonName" type="text" />
<input name="Address" type="text" />
<select name="States" multiple="multiple">
    <option value="TX">Texas</option>
    <option value="OK">Oklahoma</option>
    <option value="OH">Ohio</option>
</select>
<select name="Status">
    <option value="1">Active</option>
    <option value="2">Deleted</option>
    <option value="3">Pending</option>
</select>
<input type="button" value="Save" id="Save" />

JavaScript  

$(function () {
$("#Save").click(function (e) {
    var dataToPost = $("#MyForm").serialize()
    $.ajax(
    {
        type: "POST",
        data: JSON.stringify(dataToPost),
        url: "Working/Save",
        contentType: 'application/json; charset=utf-8'
    })
  })
})

Контроллер  

public class WorkingController : Controller
{
    // GET: Working
    public ActionResult Index()
    {
        return View();
    }

    public ActionResult Save(WorkingModel model)
    {
        // All model properties are null here????

        return Json("Success");
    }
 }

Модель  

public class WorkingModel
{
    public string PersonName { get; set; }
    public string Address { get; set; }
    public string[] States { get; set; }
    public string Status { get; set; }
}

EDIT1
Я добавил модель выше. Здесь сериализованные данные и данные JSON stringify, когда я нажимаю на сохранить. 

Сериализованные данные

"PersonName=Foo&Address=123+Test+Drive&States=TX&Status=1"

После JSON.Stringify

"\"PersonName=Foo&Address=123+Test+Drive&States=TX&Status=1\""

Я попытался добавить атрибут HttpPost и атрибут [FromBody] безуспешно.

Я не думаю, что мне нужно менять тип возвращаемого значения с ActionResult на JsonResult.

Также URL-адрес правильный, потому что отладчик попадает внутрь метода действия, где я могу QuickWatch свойства модели.

Обратите внимание, что это работает, если я создаю объект JSON и публикую его, как показано ниже:

var dataToPost = {
    PersonName:'Foo',
    Address: '123 Test Drive',
    State: 'TX',
    Status: 1
 }
5
LP13

Ваш код JavaScript/jQuery может быть значительно упрощен, что может быть лучшим путем:

$(function () {
    $("#MyForm").on('submit', function (e) {

        e.preventDefault() // prevent the form's normal submission

        var dataToPost = $(this).serialize()

        $.post("Working/Save", dataToPost)
            .done(function(response, status, jqxhr){ 
                // this is the "success" callback
            })
            .fail(function(jqxhr, status, error){ 
                // this is the ""error"" callback
            })
    })
})

Вы должны обрабатывать событие формы onsubmit, а не событие кнопки onclick кнопки - возможно, что-то, кроме кнопки, приведет к отправке формы. В этом случае мы хотим предотвратить поведение отправки формы по умолчанию, поскольку мы отправляем форму с помощью AJAX.

.serialize() уже правильно обрабатывает кодирование формы, поэтому вам не нужно JSON-кодировать значения формы. Это, скорее всего, причина того, что связыватель модели не перестраивает модель при обработке запроса.

$.post - это вспомогательная функция, которая оборачивает обычную работу по настройке, необходимую для $.ajax - показанная здесь версия требует URL для POST и данные для POST. Если ваш код jQuery находится в элементе script в View, то вы, вероятно, захотите использовать помощник Url.Action() - он создаст правильный URL на основе ваших правил маршрутизации. Если вы решите пойти по этому пути, вы будете использовать что-то похожее на:

$.post('@Url.Action("Save", "Working")', dataToPost)

Затем мы обрабатываем успешный ответ (что-нибудь с кодом состояния HTTP-200) и неудавшийся ответ (что-нибудь еще, в основном), используя соответствующие помощники. То, что вы делаете в этих помощниках, зависит от вас.

10
Tieson T.

Я думаю, что вы должны представить стандартные данные формы HTML, а не данные JSON. Следовательно, измените строки:

data: JSON.stringify(dataToPost),
contentType: 'application/json; charset=utf-8'

в 

data: dataToPost,
contentType: 'application/x-www-form-urlencoded; charset=UTF-8'

Примечание: Вы также можете пропустить вторую строку, потому что это contentType по умолчанию для $.ajax Согласно документации jQuery .

EDIT 1 Это ответ на ваш комментарий и редактирование.

Я пытался вам сказать, что данные, которые отправляет ваш Ajax, должны соответствовать тому, как вы обрабатываете данные, полученные вашим действием. Причина, по которой свойства вашей модели null, заключается в том, что эти два свойства не совпадают.

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

Таким образом, вы должны сделать одну из двух вещей:

1. Отправка реальных данных JSON. Простое использование JSON.stringify не означает, что ваши данные теперь соответствуют данным JSON. Как вы обнаружили, JSON.stringify просто обернул вашу строку кавычками, сделав ее допустимой строкой JSON, и все. Но это не то, что ожидает ваше действие, это ожидает объект JSON. Чтобы отправить объект JSON, вам, вероятно, нужно написать функцию, которая принимает поля формы одно за другим, и построить объект JSON, а затем вызвать эту функцию вместо JSON.stringify.

2. Отправьте данные стандартной формы: это то, что я предлагал в своем ответе выше. Чтобы заставить его работать, просто удалите весь код в вашем действии, который обрабатывает его как объект JSON. MVC по умолчанию предназначен для обработки стандартных данных формы, поэтому дополнительная обработка не требуется. Просто отправьте ему данные стандартной формы, и он будет работать.

Примечание: Ajax not не должен отправлять/получать данные в формате JSON. Формат JSON очень полезен для обмена данными во многих сценариях, но вы выбираете формат, который соответствует вашему конкретному сценарию. Например, ваше действие отправляет обратно объект JSON только для результата: return Json("Success"). Если вы хотите отправить только простой результат (успех или неудача), вы можете вернуть простую строку (например, return "Success") или даже логическое/целое число (например, return "True" или return "1"). Объекты Jason нуждаются в дополнительной обработке, чтобы разобрать их в строке. Хотя эта обработка очень быстрая и эффективная, она все же немного быстрее анализирует и обрабатывает простые типы данных, такие как string, boolean или integer, если вам не нужно отправлять дополнительную информацию.

5
Racil Hilan

я просто должен удалить тип контента из поста и не зачеркнуть его, и это сработало

$(function () {
  $("#Save").click(function (e) {
  var dataToPost = $("#MyForm").serialize()
  $.ajax(
  {
    type: "POST",
    data: dataToPost,
    url: "Working/Save"
  })
 })
})
4
LP13

Переместите предыдущий текст ответа в Pastebin , поскольку я был не прав, ответ выглядит следующим образом:

Просто прочитайте ваши изменения, ваша проблема в том, что JSON выглядит забавно: "\" PersonName = Foo & Address = 123 + Test + Drive & States = TX & Status = 1\"" Это не будет переводиться в WorkingModel.

Я рекомендую создать пользовательский объект JS и опубликовать его. Я просто запустил проект VS MVC и сделал его, все работает :)

$(function() {
    $("#Save").click(function(e) {
        var personName = $("[name='PersonName']").val();
        var address = $("[name='Address']").val();
        var states = $("[name='States']").val();
        var status = $("[name='Status']").val();
        var dataToPost = {
            PersonName: personName,
            Address: address,
            States: states,
            Status: status
        };

        $.ajax(
        {
            type: "POST",
            data: JSON.stringify(dataToPost),
            url: "Save",
            contentType: 'application/json; charset=utf-8'
        });
    });
});

Надеюсь это поможет!

1
Michael Crook