我正在使用jQuery在ASP.NET MVC中使用Http Post进行Ajax调用。我希望能够传递一个价值词典。
我能想到的最接近的事情是传入一个多维数组的字符串,但实际传递给ActionResult方法的结果是一个包含字符串串联“key / value”的单维字符串数组对
例如,下面“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");
有谁知道如何将Dictionary对象从jQuery传递给ActionResult方法而不是数组?
我真的想定义我的ActionResult:
public ActionResult AddItems(Dictionary<string, object> values)
{
// do something
}
有什么建议吗?
UPDATE:我尝试在值中传入一个逗号,它基本上只是使得无法使用字符串解析来实际解析键/值对。
传递这个:
values: [
["id", "200,300"],
["FirstName", "Chris"]
]
结果如下:
values[0] = "id,200,300";
values[1] = "FirstName,Chris";
答案 0 :(得分:10)
最后我明白了!感谢大家的建议!我终于找到了最好的解决方案是通过Http Post传递JSON并使用自定义ModelBinder将JSON转换为Dictionary。我在我的解决方案中做的一件事是创建一个继承自Dictionary的JsonDictionary对象,这样我就可以将自定义ModelBinder附加到JsonDictionary类型,如果我稍后使用Dictionary作为ActionResult参数,它将来不会引起任何冲突与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);
}
}
答案 1 :(得分:3)
这就是我尝试过的。节省了大量的工作。 使用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; }
}
答案 2 :(得分:1)
可以使用自定义模型粘合剂或过滤器。在幕后 - 无论如何你必须手动完成(Request.Form,解析字符串,创建字典tralala),但至少 - 你的控制器将是干净的,代码将可以重复用于其他操作。
答案 3 :(得分:1)
我认为不可能通过Http Post将jQuery / Ajax中的Dictionary传递给ActionResult方法。我发现似乎最容易使用的一件事是传入一个JSON对象,然后将其解析为一个字典。
以下是jQuery中调用“$ .post”的修改版本,它将JSON作为伪字典发送:
$.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方法出现问题,这是我需要执行此操作的唯一方法。
答案 4 :(得分: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");
<强>更新:强>
答案 5 :(得分:0)
这是一篇很老的帖子,但无论如何我都不禁发表一些评论。
@ eu-ge-ne:“DefaultModelBinder能够将你的POST绑定到数组或字典。”是的,但至少对于词典,我发现所需的表格符号相当违反直觉。
@Chris:昨天我在尝试将JavaScript(JSON)字典发布到控制器操作方法时遇到了完全相同的问题。我制定了一个完全不同的自定义模型绑定器,它处理具有不同类型参数的通用字典。我只在MVC 3中进行了测试,并且可能具有改进框架的优势。
有关我的体验详情和自定义模型活页夹的源代码,请参阅http://buildingwebapps.blogspot.com/2012/01/passing-javascript-json-dictionary-to.html
上的博客文章