Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/asp.net-mvc/16.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
如何将字典作为参数从jQuery/Ajax传递给ActionResult方法?_Jquery_Asp.net Mvc_Ajax_Actionresult - Fatal编程技术网

如何将字典作为参数从jQuery/Ajax传递给ActionResult方法?

如何将字典作为参数从jQuery/Ajax传递给ActionResult方法?,jquery,asp.net-mvc,ajax,actionresult,Jquery,Asp.net Mvc,Ajax,Actionresult,我使用jQuery在ASP.NETMVC中使用Http Post进行Ajax调用。我希望能够通过一本价值观词典 我能想到的最接近的事情是传入一个多维字符串数组,但实际上传递给ActionResult方法的结果是一个一维字符串数组,其中包含“键/值”对的字符串串联 例如,以下“值”数组中的第一项包含以下值: "id,200" 下面是我的ActionResult方法的一个示例: public ActionResult AddItems(string[] values) { // do so

我使用jQuery在ASP.NETMVC中使用Http Post进行Ajax调用。我希望能够通过一本价值观词典

我能想到的最接近的事情是传入一个多维字符串数组,但实际上传递给ActionResult方法的结果是一个一维字符串数组,其中包含“键/值”对的字符串串联

例如,以下“值”数组中的第一项包含以下值:

"id,200"
下面是我的ActionResult方法的一个示例:

public ActionResult AddItems(string[] values)
{
    // do something
}
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
}
public ActionResult AddItems([Bind(Include="values")] JsonDictionary 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
}
var postData = $('input#id1, input#id2, ..., input#idN").serialize();
// or
var postData = $('input.classOfYourInputs").serialize();

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

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

可以使用自定义模型绑定器或过滤器。在幕后-无论如何你都必须手动操作(Request.Form、解析字符串、创建字典tralala),但至少-你的控制器是干净的,代码可以用于其他操作。

我认为不可能通过Http Post将字典从jQuery/Ajax传递到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(string[] values)
{
    // do something
}
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
}
public ActionResult AddItems([Bind(Include="values")] JsonDictionary values)
{
    // do something
}
public ActionResult附加项(字典值)
{
//必须引用“System.Web.Extensions”才能使用JavaScriptSerializer
var json=new System.Web.Script.Serialization.JavaScriptSerializer();
var data=json.Deserialize(routeValue);
//做点什么
}

我认为这使得通过传递JSON进行单元测试变得更加容易,而不是使用表单集合来发送/检索键/值对集合。此外,开始工作比弄清楚如何构建自定义IModelBinder更容易,而且自定义IModelBinder可能会导致其他ActionResult方法出现问题,而我只需要这样做。

DefaultModelBinder可以将文章绑定到数组或字典。例如:

对于阵列:

public ActionResult AddItems(string[] values)

$.post("/Controller/AddItems", { values: "values[0]=200&values[1]=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");
更新:


再检查一下:

我终于明白了!!谢谢大家的建议!我最终发现最好的解决方案是通过HTTPPOST传递JSON,并使用自定义ModelBinder将JSON转换为字典。我在解决方案中做的一件事是创建一个从Dictionary继承的JsonDictionary对象,这样我就可以将自定义ModelBinder附加到JsonDictionary类型,如果我以后将Dictionary作为ActionResult参数用于JSON以外的用途,它将不会在将来导致任何冲突

以下是最终的ActionResult方法:

public ActionResult AddItems(string[] values)
{
    // do something
}
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
}
public ActionResult AddItems([Bind(Include="values")] JsonDictionary values)
{
    // do something
}
以及jQuery“$.post”调用:

然后需要注册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);
    }
}
公共类JsonDictionary:字典
{
公共JsonDictionary(){}
公共无效添加(JsonDictionary JsonDictionary)
{
if(jsonDictionary!=null)
{
foreach(jsonDictionary.Keys中的变量k)
{
添加(k,jsonDictionary[k]);
}
}
}
}
公共类JsonDictionaryModelBinder:IModelBinder
{
#区域成员
公共对象绑定模型(ControllerContext ControllerContext,ModelBindingContext bindingContext)
{
如果(bindingContext.Model==null){bindingContext.Model=new JsonDictionary();}
var model=bindingContext.model为JsonDictionary;
if(bindingContext.ModelType==typeof(JsonDictionary))
{
//反序列化“includeProperties”中指定的每个表单/查询字符串项
//传递给“UpdateModel”方法调用的参数
//检查/添加表单集合
这是addRequestValues(
模型
controllerContext.RequestContext.HttpContext.Request.Form,
controllerContext、bindingContext);
//检查/添加查询字符串集合
这是addRequestValues(
模型
controllerContext.RequestContext.HttpContext.Request.QueryString,
controllerContext、bindingContext);
}
收益模型;
}
#端区
私有void addRequestValues(JsonDictionary模型、NameValueCollection NameValueCollection、ControllerContext ControllerContext、ModelBindingContext bindingContext)
{
foreach(nameValueCollection.Keys中的字符串键)
{
if(bindingContext.PropertyFilter(键))
{
var jsonText=nameValueCollection[key];
var newModel=反序列化JSON(jsonText);
//将新的JSON键/值对添加到模型中
model.Add(newModel);
}
}
}
私有JsonDictionary反序列化json(字符串json)
{
//必须引用“System.Web.Extensions”才能使用JavaScriptSerializer
var serializer=new System.Web.Script.Serialization.JavaScriptSerializer();
返回序列化程序。反序列化(json);
}
}

这是一篇老文章,但我还是忍不住要说几句话

@eu ge ne:“DefaultModelBinder能够将您的帖子绑定到数组或字典。”这是真的,但至少对于字典,我发现所需的形式表示法相当违反直觉

@克丽丝:昨天我很高兴