4

次のモデル、ビュー、およびコントローラーがあります。

モデル

 public class Person {
        public string Name;// { get; set; }
        public string Occupation { get; set; }
        public int Salary { get; set; }
        public int[] NumArr { get; set; }
    }

意見

<input type="button" id="Test" value="Test" />

@section Javascript{
<script type="text/javascript">
    $(function () {
        $("#Test").click(function () {
            var data = { Name: "Michael Tom", Occupation: "Programmer", Salary: 8500, NumArr: [2,6,4,9] };
            var url = "Home/GetJson";
            $.ajax({
                url: url,                
                dataType: "json",
                type: "POST",
                data: data,
                traditional: true,
                success: function (result) {

                }
            });

        });
    });        
</script>
}

コントローラ

public class HomeController : Controller
    {
        public ActionResult Index()
        {
            return View();
        }

        public JsonResult GetJson(Person person) {            

            return Json(......);
        }
    }

上記のコードに基づいて、3 つの質問をしたいと思います。

  1. プロパティの代わりに public フィールドを使用すると、シリアライザーは json オブジェクトを C# モデルにシリアル化しないため、コントローラーの "Name" フィールドに対して常に null を取得します。なぜそのようなことが起こるのですか?

  2. NumArr プロパティのタイプを List に変更すると、機能しません。int[] の代わりに List を使用するにはどうすればよいでしょうか? 私はJSから配列を渡していることを知っています。JS からも List を渡すことはできますか?

  3. 「traditional: false」ではシリアル化が機能しないため、View の Javascript コード ブロックで「traditional: true」を使用しています。jQuery には 3 つのバージョンの Json シリアライザがあると聞きました。ASP.NET MVC のシリアライザーは古いバージョンのみをサポートしています。本当ですか?

3.1. 本当なら、jQuery の最新バージョンをサポートする MVC のシリアライザーの最新バージョンをいつ入手する予定なのか知りたいです。

3.2. カスタム ビュー エンジンを登録できるように、カスタム Javascript シリアライザーを登録する方法はありますか? 私の友人は、カスタム値プロバイダーまたはカスタム モデル バインダーを登録し、カスタム値プロバイダー/モデル バインダーでカスタム JS シリアライザーを使用できると提案してくれました。

前もって感謝します。私の質問がよくわからない場合は、遠慮なくお知らせください。ありがとう!

4

1 に答える 1

14

1) プロパティの代わりにパブリック フィールドを使用する場合、シリアライザーは json オブジェクトを C# モデルにシリアル化しないため、コントローラーの "Name" フィールドに対して常に null を取得します。なぜそのようなことが起こるのですか?

モデル バインダーはプロパティでのみ機能するためです。これは設計によるものです。通常、フィールドはクラス内でプライベートにする必要があります。それらは実装の詳細です。プロパティを使用して、一部の動作を外界に公開します。

2) NumArr プロパティのタイプを List に変更すると、機能しません。int[] の代わりに List を使用するにはどうすればよいでしょうか? 私はJSから配列を渡していることを知っています。JS からも List を渡すことはできますか?

それはうまくいくはずです。List<int>IEnumerable<int>またはのどちらを使用int[]しても同じであり、機能します。たとえば、複雑なオブジェクトのコレクションを使用したい場合はうまくいきませんList<SomeComplexType>(これに対する解決策については、以下の私の回答を参照してください)。

3) 「traditional: false」ではシリアル化が機能しないため、View の Javascript コード ブロックで「traditional: true」を使用しています。jQuery には 3 つのバージョンの Json シリアライザがあると聞きました。ASP.NET MVC のシリアライザーは古いバージョンのみをサポートしています。本当ですか?

はい、従来のパラメーターは、jQuery がパラメーターをシリアル化する方法を変更したときに、jQuery 1.4 で導入されました。この変更は、モデル バインダーがリストにバインドするときに MVC で使用する標準の規則と互換性がありませんでした。

FireBug などの JavaScript デバッグ ツールをダウンロードして、プレイを開始してください。このパラメーターを設定すると、jQuery が要求を送信する方法の違いがわかります。


以上のことから、JSON でエンコードされたリクエストをコントローラー アクションに送信することをお勧めします。これはあらゆる複雑なオブジェクトで機能し、JSON は標準の相互運用可能な形式であるため、使用している jQuery のバージョンなどを自問する必要はありません。標準の相互運用可能な形式の利点は、使用するシステムに関係なく、同じ言語で話せるようにする必要があることです (もちろん、それらのシステムにバグがあり、定義された標準を尊重していない場合を除きます)。

しかし、ここで、application/x-www-form-urlencodedも標準的で不可逆的な形式であると言えます。そして、それは本当です。問題は、入力フィールドの名前をモデルのプロパティにバインドするときに、モデル バインダーが規則を使用することです。そして、この規則は、相互運用性や業界標準とはほど遠いものです。

たとえば、モデルの階層を持つことができます。

public class Person
{
    public string Name { get; set; }
    public string Occupation { get; set; }
    public int Salary { get; set; }
    public List<SubObject> SubObjects { get; set; }
}

public class SubObject
{
    public int Id { get; set; }
    public string Name { get; set; }
}

任意の複雑な階層を想像できます (JSON 形式でサポートされていない循環参照を除く)。

その後:

var data = { 
    name: "Michael Tom", 
    occupation: "Programmer", 
    salary: 8500, 
    subObjects: [
        { id: 1, name: 'sub 1' },
        { id: 2, name: 'sub 2' },
        { id: 3, name: 'sub 3' }
    ] 
};

$.ajax({
    url: "Home/GetJson",
    type: "POST",
    data: JSON.stringify({ person: data }),
    contentType: 'application/json',
    success: function (result) {

    }
});

Content-Type リクエスト HTTP ヘッダーをapplication/jsonに設定して、ビルトインの JSON 値プロバイダー ファクトリにリクエストが JSON エンコードされていることを示し (JSON.stringifyメソッドを使用)、厳密に型指定されたモデルに解析します。このJSON.stringifyメソッドは最新のブラウザーにネイティブに組み込まれていますが、レガシー ブラウザーをサポートしたい場合は、json2.jsスクリプトをページに含めることができます。

于 2012-04-02T14:36:03.273 に答える