web-dev-qa-db-ja.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
 }
8
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エンコードする必要はありません。そうすることが、リクエストを処理するときにmodelbinderがモデルを再構築しない理由である可能性が高いです。

_$.post_は、_$.ajax_に必要な一般的なセットアップ作業をラップするヘルパー関数です。ここに示すバージョンでは、URLをPOST=に、データをPOSTに設定します。 jQueryコードがビュー内のスクリプト要素にある場合、おそらくUrl.Action()ヘルパーを使用する必要があります-ルーティングルールに基づいて正しいURLを構築します。次のようなものを使用します。

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

次に、関連するヘルパーを使用して、成功した応答(HTTP-200ステータスコードを持つもの)と失敗した応答(基本的には他のもの)を処理します。 doヘルパーで何をするかはあなた次第です。

11
Tieson T.

JSONデータではなく、標準のHTMLフォームデータを送信する必要があると思います。したがって、行を変更します。

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

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

注: jQuery documentation によると、_$.ajax_のデフォルトのcontentTypeであるため、2行目を省略することもできます。

EDIT 1これはあなたのコメントと編集への応答です。

私があなたに伝えようとしたのは、Ajaxが送信するデータは、アクションによって受信したデータの処理方法と一致する必要があるということです。モデルプロパティがnullである理由は、これら2つが一致しないためです。

アクションのコードを投稿しなかったため、データをどのように処理しているかはわかりませんが、編集1からは、送信時に機能していたため、JSONデータとして受信したデータを処理しているようです実際のJSONデータ。

したがって、次の2つのいずれかを行う必要があります。

1-実際のJSONデータを送信する:_JSON.stringify_を使用するだけでは、データが適切なJSONデータであるとは限りません。お気づきのとおり、_JSON.stringify_は文字列を引用符で囲むだけで、有効なJSON文字列になります。それだけです。しかし、それはあなたのアクションが期待していることではなく、JSONオブジェクトを期待しています。 JSONオブジェクトを送信するには、フォームフィールドを1つずつ取得してJSONオブジェクトを作成する関数を作成し、_JSON.stringify_の代わりにこの関数を呼び出す必要があります。

2-標準フォームデータを送信する:上記の回答で提案していたことです。動作させるには、JSONオブジェクトとして処理しているアクション内のすべてのコードを削除するだけです。 MVCはデフォルトで標準フォームデータを処理するように設計されているため、追加の処理は必要ありません。標準フォームデータを送信するだけで機能します。

注:AjaxはnotデータをJSON形式で送受信する必要がありません。 JSON形式は、多くのシナリオでデータを交換するのに非常に役立ちますが、特定のシナリオに適した形式を選択します。たとえば、アクションは結果のためだけにJSONオブジェクトを送り返します:return Json("Success")。単純な結果(成功と失敗)のみを送信する場合は、単純な文字列(たとえば_return "Success"_)またはブール値/整数(たとえば_return "True"_または_return "1"_)を返すことができます。 Jasonオブジェクトは、文字列から解析するために追加の処理が必要です。この処理は非常に高速で効率的ですが、追加情報を送信する必要がない場合は、文字列、ブール値、整数などの単純なデータ型を解析および処理するのが少し高速です。

7
Racil Hilan

投稿からコンテンツタイプを削除する必要があり、それを文字列化してはいけません。

$(function () {
  $("#Save").click(function (e) {
  var dataToPost = $("#MyForm").serialize()
  $.ajax(
  {
    type: "POST",
    data: dataToPost,
    url: "Working/Save"
  })
 })
})
5
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