2

現在、MVC 3 アプリのビューからコントローラーに JSON オブジェクトを投稿しようとしていますが、リクエストからのデータがコントローラー アクションのモデル パラメーターにバインドされることを期待しています。ただし、HTTP POST 要求を調べると、データがクエリ文字列として渡されているように見え、その理由がわかりません (これはまったく新しいことです)。

ここに私のPOSTリクエストがあります:

    $.ajax({
        type: 'POST',
        url: "Test/Add",
        data: { Name: name, Age: age },
        success: function (data) {
            console.log("success");
        },
        error: function (xhr, data, message) {
            console.log(data + ": " + message);
        },
        dataType: "json"
    });

これが私のコントローラーからのコードで、その後にバインドしようとしているモデルのコードが続きます。

    [HttpPost]
    public ActionResult Add(PersonModel person)
    {
        System.Threading.Thread.Sleep(1000);

        return View();
    }

    // person model:
    public class Person {

        public string Name {get;set;}
        public int Age {get;set;}

    }

これはフィドラーからのリクエストです - 不明な部分をハイライトしました:

ここに画像の説明を入力

コンテンツ タイプは「application/json」であり、データはクエリ文字列のようには見えないだろうと考えました-次のようになると思いました:

{
    Name: "James",
    Age: 13
}

最終的な問題は、コントローラー アクションにブレークポイントを設定すると、データが入力された Person オブジェクトが表示されることを期待していますが、常に null であるということです。署名を次のように置き換えると(object name, object age)、パラメーターの値が取得されます (両方の文字列配列 - name は、「James」に等しい 1 つの要素を持つ文字列配列です)。

私が間違っていたアイデアはありますか?

ああ、参考までに、私は実際には 13 歳ではありません。それらは私がマッシュした最初の数字でした。

ありがとう!

ジェームズ

4

2 に答える 2

2

@Davidは、contentTypeを「application/json」に設定する必要があるという点で正しいです。ただし、JSONも送信する必要があります。オブジェクトを送信しています。JSONに変換するには、JSON.stringifyを使用します。このcontentType設定でオブジェクトとして送信しようとしましたが、サーバーエラーが発生しました。contentTypeを設定しなくても、実際に正しく動作するようになりました。リクエストは「Name=James&Age = 13」として検出されましたが、MVCはそれをオブジェクトに変換できました。結果をJSONとしてエコーバックして表示するように、テストを変更しました。

これが変更されたコントローラーです

        [HttpPost]
    public string Add(PersonModel person)
    {
        JavaScriptSerializer serializer = new JavaScriptSerializer();
        string result = serializer.Serialize(person);

        return result;
    }

    // person model:
    public class PersonModel
    {

        public string Name { get; set; }
        public int Age { get; set; }

    }

変更されたJavascriptとHTMLは次のようになります。

<input id="doAjax" type="button"  value="Send Json..."/>
<br />
Results:<br />
<textarea id="results" cols="30" rows="3"></textarea>
<script type="text/javascript">

 $( document ).ready( function () {
    $( "#doAjax" ).click( sendJson );
} );

function sendJson() {
    var name = "James";
    var age = "13";
    var person = { Name: name, Age: age };
    var personJson = JSON.stringify( person );
    $.ajax( {
        type: 'POST',
        url: "Test/Add",
        data: personJson,
        contentType: 'application/json',
        success: function ( data ) {
            var jsonStr = JSON.stringify( data );
            $( "#results" ).val( jsonStr );
        },
        error: function ( xhr, data, message ) {
            var jsonStr = JSON.stringify( data );
            $( "#results" ).val( jsonStr + ": " + message );
        },
        dataType: "json"
    } );
}

いくつかのテストの結果は次のとおりです。

データ=人; contentType=設定されていません。request = "Name = James&Age = 13"; response = "{" Name ":" James "、" Age ":13}"

データ=personJson; contentType=設定されていません。request = "{" Name ":" James "、" Age ":" 13 "}"; response = "{" Name ":null、" Age ":0}"

データ=人; contentType ='application / json'; request = "Name = James&Age = 13"; response = "System.ArgumentException:無効なJSONプリミティブ:名前"

データ=personJson; contentType ='application / json'; request = "{" Name ":" James "、" Age ":" 13 "}"; response = "{" Name ":" James "、" Age ":" 13 "}"

contentTypeが設定されていない場合、デフォルトで「application/x-www-form-urlencoded」に設定されることに注意してください。

于 2012-04-05T13:31:51.700 に答える
1

dataType渡される$.ajaxのは、予期される応答タイプです。contentTypeペイロード タイプを指定するには、 を追加する必要があります。

$.ajax({
    type: 'POST',
    url: "Test/Add",
    data: { Name: name, Age: age },
    contentType: 'application/json' //*********
    success: function (data) {
        console.log("success");
    },
    error: function (xhr, data, message) {
        console.log(data + ": " + message);
    },
    dataType: "json"
});

.ajax()これは、デフォルトの contentType が「application/x-www-form-urlencoded」であることを示すjQuery ドキュメントです。

于 2012-04-05T12:08:19.053 に答える