18

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");
}

私は何を間違っていますか?

4

3 に答える 3

60

コードには多くの問題があります。マークアップから始めましょう。テーブルがあり、このテーブルの各行内に隠しフィールドが含まれています。これらの隠し要素の属性をハードコーディングした場合を除いてid、マークアップに同じ 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>
}

これで、有効なマークアップができました。submitTest次に、何らかのボタンがクリックされたときにトリガーされる JavaScript イベントに移りましょう。これがフォームの送信ボタンである場合は、送信ボタンの.submitイベントではなく、フォームのイベントを購読することをお勧め.clickします。この理由は、たとえば、フォーカスが入力フィールド内にあるときにユーザーが Enter キーを押すと、フォームが送信される可能性があるためです。この場合、クリック イベントはトリガーされません。

そう:

$(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 を逆シリアル化できません。

于 2012-12-08T16:03:38.847 に答える
7

別の簡単な方法があります。クエリ文字列を使用してデータを送信します。興味を持った場合、JSON 配列のデータ型は .xml ではないため、現在のアプローチは間違っていstringますCustomTypeModel

まず、dataajax オプションを削除します。もう必要ありません。

次に、コントローラーを次のように変更します。

[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)
于 2013-07-19T08:26:46.140 に答える
-1

あなたはMVCの世界で少し間違ったやり方をしていると思います。データをバインドするための適切なモデルがある場合は、「手作り」のJavaScriptを使用するのではなく、ボックスからのヘルパーを使用する方が適切です。非同期呼び出しが必要な場合は、HtmlHelperまたはAjaxHelperを参照してください。

@Html.TextBoxFor()また、ブロック内の表記を使用してデータをモデルにバインドします@Html.BeginForm。これにより、コードが大幅に簡素化され、JavaScriptの量が削減されます。これにより、メンテナンスが大幅に向上します。

サーバー部分では、カスタムモデルバインダーを実装し、設定を変更して、モデルバインダーを介して現在のコントローラーアクションのハンドル要求を行う必要があります。サーバーサイドコードを作成する必要がありますが、静的に型指定されたコードは、コーディングとテストが簡単に見えます。JavaScriptが実行する必要があることを実行することを好むため、またはアプリケーションのニーズに適しています=> UIを管理しますが、モデルを構築しませんサーバーサイドでの正しい解析のため。単一責任の原則に適しています。

このビデオを参照してください、これはそれを行う方法の簡単なチュートリアルです

于 2012-12-08T16:41:10.153 に答える