web-dev-qa-db-ja.com

JSON配列をMVCコントローラーに投稿する

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>

これは、データを受信しようとするコントローラーimです。

[HttpPost]
public ActionResult Update(CustomTypeModel ctm)
{


   return RedirectToAction("Index");
}

何が悪いのですか?

17
Yustme

コードには多くの問題があります。マークアップから始めましょう。テーブルがあり、このテーブルの各行内に非表示フィールドが含まれています。ただし、これらの非表示要素の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を逆シリアル化できません。

58
Darin Dimitrov

別の簡単な方法があります。クエリ文字列を使用してデータを送信します。 JSON配列のデータ型がstringではなくCustomTypeModelであるため、興味をそそられた場合、現在のアプローチは正しくありません。

まず、data ajaxオプションを削除します。それはもう必要ありません。

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

[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)
7
Amin Saqi