jqueryでAJAX Postを使用して、厳密に型指定されたMVC3ビューからモデルを渡す適切な方法


100

私は初心者のWebプログラマーなので、「専門用語」の一部が正しくない場合は許してください。MVC3フレームワークを使用したASP.NETを使用するプロジェクトがあります。

私は、管理者が機器のリストを変更する管理ビューに取り組んでいます。機能の1つは「更新」ボタンで、jqueryを使用して、MVCコントローラーに投稿を送信した後、Webページのエントリを動的に編集します。

このアプローチは、Webページがデータベースと同期しなくなる心配がほとんどない単一の管理設定で「安全」であると思います。

強く型付けされたビューを作成し、AJAXポストを使用してモデルデータをMVCコントロールに渡すことを望んでいました。

次の投稿で、私が見ているものに似ているものを見つけました: nullパラメータを引き起こすJQuery AjaxとASP.NET MVC3

上記の記事のコードサンプルを使用します。

モデル:

public class AddressInfo 
{
    public string Address1 { get; set; }
    public string Address2 { get; set; }
    public string City { get; set; }
    public string State { get; set; }
    public string ZipCode { get; set; }
    public string Country { get; set; }
}

コントローラ:

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

    [HttpPost]
    public ActionResult Check(AddressInfo addressInfo)
    {
        return Json(new { success = true });
    }
}

ビューのスクリプト:

<script type="text/javascript">
var ai = {
    Address1: "423 Judy Road",
    Address2: "1001",
    City: "New York",
    State: "NY",
    ZipCode: "10301",
    Country: "USA"
};

$.ajax({
    url: '/home/check',
    type: 'POST',
    data: JSON.stringify(ai),
    contentType: 'application/json; charset=utf-8',
    success: function (data.success) {
        alert(data);
    },
    error: function () {
        alert("error");
    }
});
</script>

私はまだこれを使う機会がありませんでした。しかし、これがAJAXを使用してモデルデータをMVCコントロールに戻す「最適な」方法であるかどうか疑問に思っていましたか?

モデル情報の公開について心配する必要がありますか?

回答:


72

var宣言と文字列化をスキップできます。それ以外の場合は、問題なく動作します。

$.ajax({
    url: '/home/check',
    type: 'POST',
    data: {
        Address1: "423 Judy Road",
        Address2: "1001",
        City: "New York",
        State: "NY",
        ZipCode: "10301",
        Country: "USA"
    },
    contentType: 'application/json; charset=utf-8',
    success: function (data) {
        alert(data.success);
    },
    error: function () {
        alert("error");
    }
});

若干の調整を指摘していただきありがとうございます。セキュリティの観点からモデル構造を公開することに懸念はありますか?
John Stone、

私にとってセキュリティの問題として目立つものは何もありません。ただし、本当に心配している場合は、mvc側でいつでもカスタムモデルバインダーを作成できます。
クレイグM

8
これは私には失敗しました。呼び出しをMVC5で機能させるには、JSON.stringify({...})を使用する必要がありました。
Johncl、2015年

私は、APIコントローラーを操作するときに同じことをしなければならないことに気づきました。この答えは4年前、APIコントローラが存在する前に書かれたものです。
Craig M

1
神ダミット、私はcontentTypeではなくdataTypeを持っていました。
Phil

175

これを実装する3つの方法を見つけました。

C#クラス:

public class AddressInfo {
    public string Address1 { get; set; }
    public string Address2 { get; set; }
    public string City { get; set; }
    public string State { get; set; }
    public string ZipCode { get; set; }
    public string Country { get; set; }
}

アクション:

[HttpPost]
public ActionResult Check(AddressInfo addressInfo)
{
    return Json(new { success = true });
}

JavaScriptでは、次の3つの方法で実行できます。

1)クエリ文字列:

$.ajax({
    url: '/en/Home/Check',
    data: $('#form').serialize(),
    type: 'POST',
});

ここのデータは文字列です。

"Address1=blah&Address2=blah&City=blah&State=blah&ZipCode=blah&Country=blah"

2)オブジェクト配列:

$.ajax({
    url: '/en/Home/Check',
    data: $('#form').serializeArray(),
    type: 'POST',
});

ここのデータは、キーと値のペアの配列です。

=[{name: 'Address1', value: 'blah'}, {name: 'Address2', value: 'blah'}, {name: 'City', value: 'blah'}, {name: 'State', value: 'blah'}, {name: 'ZipCode', value: 'blah'}, {name: 'Country', value: 'blah'}]

3)JSON:

$.ajax({
      url: '/en/Home/Check',
      data: JSON.stringify({ addressInfo:{//missing brackets
          Address1: $('#address1').val(),
          Address2: $('#address2').val(),
          City: $('#City').val(),
          State: $('#State').val(),
          ZipCode: $('#ZipCode').val()}}),
      type: 'POST',
      contentType: 'application/json; charset=utf-8'
});

ここのデータはシリアライズされたJSON文字列です。名前はサーバーのパラメーター名と一致する必要があることに注意してください!!

='{"addressInfo":{"Address1":"blah","Address2":"blah","City":"blah","State":"blah", "ZipCode", "blah", "Country", "blah"}}'

1
私がまだ知らなかった質問を解決するこの素晴らしい、徹底的な答えに出くわしただけです。+1、ありがとう!
SeanKilleen 2013

#2は私が探していたものでした。これが答えになるはずです。
TheGeekZn 2013

編集:data: $('input, textarea, select').serialize(),私の仕事に使用する必要がありました。
TheGeekZn 2013

やあジャザレット!! 3番目のアプローチでモデルに日付を渡す方法??
Guruprasad Rao 2015

1
遅れて申し訳ありません@GuruprasadRao日付を渡すには、日付と時刻をJavaScriptコードの文字列にすることができ、MVCはそれをDateTimeオブジェクトに変換します。
Jazaret

12

これは私にとってそれが働いた方法です:

$.post("/Controller/Action", $("#form").serialize(), function(json) {       
        // handle response
}, "json");

[HttpPost]
public ActionResult TV(MyModel id)
{
    return Json(new { success = true });
}

8

あなたが持っているものは問題ありません-しかし、いくつかのタイピングを節約するために、あなたは単にあなたのデータに使用することができます

データ:$( '#formId')。serialize()

詳細についてはhttp://www.ryancoughlin.com/2009/05/04/how-to-use-jquery-to-serialize-ajax-forms/を参照してください。構文はかなり基本的です。


serialize関数を使用するために、クラスオブジェクトの各メンバーをフォームオブジェクトで使用する必要があることを理解しています。それが正しければ、私はSOLかもしれません。
John Stone、

1
ah ya ..そうでない場合は、serializeを使用できません。ただし、常にDOMを操作し、それらの要素を使用してフォームを作成し、シリアル化することができます。
Adam Tuliper-MSFT、2011年

@TahaRehmanSiddiquiシリアライズはIEで実際に機能しますが、何が機能しませんか?エラーが発生しますか?
Adam Tuliper-MSFT 2013年

私のモデルのすべてのプロパティがnullになる
Taha Rehman Siddiqui 2013年

@TahaRehmanSiddiquiフォームフィールドの「名前」は、モデルプロパティの名前と一致しますか?
MongooseNX

0

MVC 5を使用している場合は、このソリューションをお読みください。

特にMVC 3に関する質問を知っていますが、MVC 5でこのページに出くわし、私の状況で他の人のために解決策を投稿したいと思いました。上記の解決策を試しましたが、うまくいきませんでした。アクションフィルターに到達できず、その理由を理解できませんでした。プロジェクトでバージョン5を使用していて、次のアクションフィルターが作成されました。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using System.Web.Mvc.Filters;

namespace SydHeller.Filters
{
    public class ValidateJSONAntiForgeryHeader : FilterAttribute, IAuthorizationFilter
    {
        public void OnAuthorization(AuthorizationContext filterContext)
        {
            string clientToken = filterContext.RequestContext.HttpContext.Request.Headers.Get(KEY_NAME);
            if (clientToken == null)
            {
                throw new HttpAntiForgeryException(string.Format("Header does not contain {0}", KEY_NAME));
            }

            string serverToken = filterContext.HttpContext.Request.Cookies.Get(KEY_NAME).Value;
            if (serverToken == null)
            {
                throw new HttpAntiForgeryException(string.Format("Cookies does not contain {0}", KEY_NAME));
            }

            System.Web.Helpers.AntiForgery.Validate(serverToken, clientToken);
        }

        private const string KEY_NAME = "__RequestVerificationToken";
    }
}

ライブラリではなく、using System.Web.Mvcとをメモしてください(これはMVC v5で変更された点の1つだと思います。-using System.Web.Mvc.Filtershttp

次に、フィルターを適用します [ValidateJSONAntiForgeryHeader]、アクション(またはコントローラー)にを正しく呼び出されます。

私のレイアウトページの真上</body>@AntiForgery.GetHtml();

最後に、私のRazorページで、ajax呼び出しを次のように実行します。

var formForgeryToken = $('input[name="__RequestVerificationToken"]').val();

$.ajax({
  type: "POST",
  url: serviceURL,
  contentType: "application/json; charset=utf-8",
  dataType: "json",
  data: requestData,
  headers: {
     "__RequestVerificationToken": formForgeryToken
  },
     success: crimeDataSuccessFunc,
     error: crimeDataErrorFunc
});

1
すべてのフォーム値を手動で取得していますか?なんでdata: $("#the-form").serialize()
シンジャイ

1
@Sinjai私はもう一度コードを確認する必要がありますが、そこで他の処理も行っていると思います。「.serialize()」は、入力値だけが必要な場合にも機能します
blubberbo

心配はいりません、私はただ興味がありました。
シンジャイ2017
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.