11

jQueryを使用して、ASP.NETMVCのHttpPostを使用してAjax呼び出しを行っています。値のディクショナリを渡せるようにしたいと思います。

私が考えることができる最も近いことは、文字列の多次元配列を渡すことでしたが、実際にActionResultメソッドに渡される結果は、「キー/値」ペアの文字列連結を含む1次元文字列配列です。

たとえば、以下の「values」配列の最初の項目には、以下の値が含まれています。

"id,200"

これが私のActionResultメソッドの例です:

public ActionResult AddItems(string[] values)
{
    // do something
}

jQueryからメソッドを呼び出す方法の例を次に示します。

$.post("/Controller/AddItems",
    {
        values: [
            ["id", "200"],
            ["FirstName", "Chris"],
            ["DynamicItem1", "Some Value"],
            ["DynamicItem2", "Some Other Value"]
        ]
    },
    function(data) { },
    "json");

辞書オブジェクトをjQueryから配列ではなくActionResultメソッドに渡す方法を知っている人はいますか?

ActionResultを次のように定義したいと思います。

public ActionResult AddItems(Dictionary<string, object> values)
{
    // do something
}

助言がありますか?

更新:値内にコンマを渡そうとしましたが、基本的に、文字列解析を使用してキーと値のペアを実際に解析することは不可能です。

これを渡す:

values: [
    ["id", "200,300"],
    ["FirstName", "Chris"]
]

結果は次のようになります。

values[0] = "id,200,300";
values[1] = "FirstName,Chris";
4

6 に答える 6

10

やっとわかった!!みんなの提案に感謝します!最終的に最善の解決策は、JSON を Http Post 経由で渡し、カスタム ModelBinder を使用して JSON を Dictionary に変換することであることがわかりました。私のソリューションで行ったことの 1 つは、Dictionary を継承する JsonDictionary オブジェクトを作成して、カスタム ModelBinder を JsonDictionary タイプにアタッチできるようにすることです。 JSON とは目的が異なります。

最終的な ActionResult メソッドは次のとおりです。

public ActionResult AddItems([Bind(Include="values")] JsonDictionary values)
{
    // do something
}

そして jQuery の "$.post" 呼び出し:

$.post("/Controller/AddItems",
{
    values: Sys.Serialization.JavaScriptSerializer.serialize(
            {
                id: 200,
                "name": "Chris"
            }
        )
},
function(data) { },
"json");

次に、JsonDictionaryModelBinder を登録する必要があります。これを Global.asax.cs 内の Application_Start メソッドに追加しました。

protected void Application_Start()
{
    ModelBinders.Binders.Add(typeof(JsonDictionary), new JsonDictionaryModelBinder());
}

最後に、作成した JsonDictionaryModelBinder オブジェクトと JsonDictionary オブジェクトを次に示します。

public class JsonDictionary : Dictionary<string, object>
{
    public JsonDictionary() { }

    public void Add(JsonDictionary jsonDictionary)
    {
        if (jsonDictionary != null)
        {
            foreach (var k in jsonDictionary.Keys)
            {
                this.Add(k, jsonDictionary[k]);
            }
        }
    }
}

public class JsonDictionaryModelBinder : IModelBinder
{
    #region IModelBinder Members

    public object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext)
    {
        if (bindingContext.Model == null) { bindingContext.Model = new JsonDictionary(); }
        var model = bindingContext.Model as JsonDictionary;

        if (bindingContext.ModelType == typeof(JsonDictionary))
        {
            // Deserialize each form/querystring item specified in the "includeProperties"
            // parameter that was passed to the "UpdateModel" method call

            // Check/Add Form Collection
            this.addRequestValues(
                model,
                controllerContext.RequestContext.HttpContext.Request.Form,
                controllerContext, bindingContext);

            // Check/Add QueryString Collection
            this.addRequestValues(
                model,
                controllerContext.RequestContext.HttpContext.Request.QueryString,
                controllerContext, bindingContext);
        }

        return model;
    }

    #endregion

    private void addRequestValues(JsonDictionary model, NameValueCollection nameValueCollection, ControllerContext controllerContext, ModelBindingContext bindingContext)
    {
        foreach (string key in nameValueCollection.Keys)
        {
            if (bindingContext.PropertyFilter(key))
            {
                var jsonText = nameValueCollection[key];
                var newModel = deserializeJson(jsonText);
                // Add the new JSON key/value pairs to the Model
                model.Add(newModel);
            }
        }
    }

    private JsonDictionary deserializeJson(string json)
    {
        // Must Reference "System.Web.Extensions" in order to use the JavaScriptSerializer
        var serializer = new System.Web.Script.Serialization.JavaScriptSerializer();
        return serializer.Deserialize<JsonDictionary>(json);
    }
}
于 2009-07-03T20:23:41.003 に答える
4

これは私が試したものです。多くの作業を節約します。Javascript:

  var dict = {};       
        dict["id"] = "200";
        dict["FirstName"] = "Chris";
        dict["DynamicItem1"] = "Some Value";
        dict["DynamicItem2"] = "Some Other Value";

        var theObject = {};
        theObject.dict = dict;
        $.post(URL, theObject, function (data, textStatus, XMLHttpRequest) {
            console.log("success");
        }, "json");

アクション方法:

public ActionResult MethodName(DictionaryModel obj)
    {
       //Action method logic
    }

public class DictionaryModel
{
    public Dictionary<string, string> dict { get; set; }

}
于 2014-10-21T08:56:26.450 に答える
1

Http Post を介して jQuery/Ajax から ActionResult メソッドに Dictionary を渡すことはできないと思います。最も簡単に作業できると思われることの 1 つは、JSON オブジェクトを渡し、それを解析して辞書に入れることです。

JSON を疑似辞書として送信する jQuery からの「$.post」の呼び出しの修正版を次に示します。

$.post("/Controller/AddItems",
    {
        values: Sys.Serialization.JavaScriptSerializer.serialize(
                {
                    id: 200,
                    "name": "Chris"
                }
            )
    },
    function(data) { },
    "json");

「Sys.Serialization.JavaScriptSerializer.serialize」関数は、ASP.NET AJAX JavaScript ライブラリのメソッドです。

上記の ActionResult メソッドの修正版は次のとおりです。

public ActionResult AddItems(Dictionary<string, object> values)
{
    // Must Reference "System.Web.Extensions" in order to use the JavaScriptSerializer
    var json = new System.Web.Script.Serialization.JavaScriptSerializer();
    var data = json.Deserialize<Dictionary<string, string>>(routeValues);

    // do something
}

これにより、フォーム コレクションを使用してキーと値のペアのコレクションを送信/取得する代わりに、JSON を渡すことで単体テストがはるかに簡単になると思います。また、カスタム IModelBinder を構築する方法を理解するよりも作業を開始する方が簡単です。カスタム IModelBinder は、これを行う必要がある唯一のメソッドである場合、他の ActionResult メソッドで問題を引き起こす可能性があります。

于 2009-07-03T03:02:47.677 に答える
1

カスタム モデル バインダーまたはフィルターで可能です。舞台裏では、とにかく手動で行う必要があります (Request.Form、文字列の解析、辞書 tralala の作成)。ただし、少なくとも、コントローラーはクリーンになり、コードは別のアクションで再利用できるようになります。

于 2009-07-03T02:16:23.327 に答える
0

DefaultModelBinderは、POSTを配列またはディクショナリにバインドできます。例えば:

アレイの場合:

public ActionResult AddItems(string[] values)

$.post("/Controller/AddItems", { values: "values[0]=200&values[1]=300" },
    function(data) { }, "json");

また:

$.post("/Controller/AddItems", { values: "values=200&values=300" },
    function(data) { }, "json");

辞書の場合:

public ActionResult AddItems(Dictionary<string, object> values)

$.post("/Controller/AddItems", {
    values: "values[0].Key=value0&values[0].Value=200&values[1].Key=value1&values[1].Value=300" }, function(data) { }, "json");

更新しました:

値がHTML入力の場合、jQueryでは次のように実行できます。

var postData = $('input#id1, input#id2, ..., input#idN").serialize();
// or
var postData = $('input.classOfYourInputs").serialize();

$.post("/Controller/AddItems", { values: postData }, function(data) { }, "json");

更新しました:

また、これを確認してください:Scott HanselmanのComputerZen.com-配列、リスト、コレクション、辞書にモデルをバインドするためのASP.NETワイヤー形式

于 2009-07-03T09:15:12.847 に答える
0

これは古い投稿ですが、とにかくいくつかの発言をせずにはいられません。

@eu-ge-ne: "DefaultModelBinder は POST を配列または辞書にバインドできます。" 確かにそうですが、少なくとも辞書の場合、必要なフォーム表記は直感に反するものだと思います。

@Chris: 昨日、JavaScript (JSON) 辞書をコントローラー アクション メソッドに投稿しようとしたときに、まったく同じ問題が発生しました。異なる型引数を持つ汎用辞書を処理する、まったく異なるカスタム モデル バインダーを作成しました。私は MVC 3 でのみテストしましたが、おそらく改善されたフレームワークの利点がありました。

私の経験とカスタム モデル バインダーのソース コードの詳細については、http://buildingwebapps.blogspot.com/2012/01/passing-javascript-json-dictionary-to.htmlにある私のブログ投稿を参照してください。

于 2012-01-19T09:27:18.983 に答える