2009-07-03 30 views
11

Tôi đang sử dụng jQuery để thực hiện cuộc gọi Ajax bằng cách sử dụng Bài đăng trong ASP.NET MVC. Tôi muốn có thể chuyển một Từ điển các giá trị. Điều gần nhất tôi có thể nghĩ đến là vượt qua trong một mảng đa chiều của các chuỗi, nhưng kết quả thực sự được chuyển đến phương thức ActionResult là một mảng chuỗi một chiều có chứa một chuỗi nối của "khóa/giá trị". "cặp.Làm cách nào để chuyển một Từ điển làm tham số cho một phương thức ActionResult từ jQuery/Ajax?

Ví dụ mục đầu tiên trong "giá trị" mảng dưới đây chứa các giá trị dưới đây:

"id,200" 

Dưới đây là một ví dụ về phương pháp ActionResult tôi:

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

Dưới đây là một ví dụ về cách tôi m gọi phương thức từ jQuery:

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

Có ai biết cách chuyển từ điển o từ jQuery đến phương thức ActionResult thay vì một mảng?

Tôi thực sự muốn xác định ActionResult của tôi như thế này:

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

Bất kỳ lời đề nghị?

CẬP NHẬT: Tôi đã thử chuyển dấu phẩy trong giá trị và về cơ bản nó không thể phân tích cú pháp cặp khóa/giá trị bằng phân tích chuỗi.

đèo này:

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

kết quả trong việc này:

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

Tôi không nghĩ rằng có một cách để làm that.I có thể sai, nhưng nó sẽ là tầm thường để phân tích các dữ liệu được truyền vào như một mảng chuỗi và tự tạo từ điển bên trong phương thức AddItems. –

+0

Không chắc chắn vấn đề phân tích cú pháp nào sẽ do bất kỳ dấu phẩy nào trong các giá trị gây ra. –

+0

Cuối cùng tôi đã tìm ra, nhờ tất cả những ai đưa ra gợi ý! Tôi đã thêm giải pháp cuối cùng của tôi làm câu trả lời bên dưới. Tôi sẽ đánh dấu nó là Câu trả lời đúng ngay khi SO cho phép tôi. Cảm ơn mọi người! –

Trả lời

11

Cuối cùng tôi figured it out !! Cảm ơn những lời đề nghị tất cả mọi người! Cuối cùng tôi đã tìm ra giải pháp tốt nhất là chuyển JSON qua Http Post và sử dụng một ModelBinder tùy chỉnh để chuyển đổi JSON thành một từ điển. Một điều tôi đã làm trong giải pháp của tôi là tạo ra một đối tượng JsonDictionary kế thừa từ điển để tôi có thể đính kèm ModelBinder tùy chỉnh vào kiểu JsonDictionary, và nó sẽ không gây ra bất kỳ xung đột nào trong tương lai nếu tôi sử dụng từ điển như một tham số ActionResult sau này mục đích khác với JSON.

Dưới đây là phương pháp ActionResult thức:

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

Và jQuery "$ .post" gọi:

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

Sau đó JsonDictionaryModelBinder cần phải được đăng ký, tôi đã thêm này cho phương thức Application_Start trong vòng the Global.asax.cs:

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

Và cuối cùng là JsonDictionaryMode đối tượng lBinder và đối tượng JsonDictionary mà tôi đã tạo:

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

Có thể với chất kết dính mô hình tùy chỉnh hoặc bộ lọc. Đằng sau hậu trường - bạn sẽ phải làm điều đó bằng tay anyway (Request.Form, phân tích chuỗi, tạo tralala từ điển), nhưng ít nhất - bộ điều khiển của bạn sẽ được sạch sẽ và mã sẽ được tái sử dụng cho một hành động khác.

1

Tôi không nghĩ rằng có thể chuyển từ điển từ jQuery/Ajax sang phương thức ActionResult qua một bài đăng Http. Một điều tôi đã tìm ra rằng có vẻ là dễ nhất để làm việc với là chuyển vào một đối tượng JSON và sau đó phân tích cú pháp đó thành một từ điển.

Dưới đây là phiên bản sửa đổi của các sự kêu gọi trên "$ .post" từ jQuery sẽ gửi JSON như một pseudo-Từ điển:

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

Các "Sys.Serialization.JavaScriptSerializer.serialize" chức năng là một phương pháp của thư viện JavaScript ASP.NET AJAX.

Dưới đây là phiên bản sửa đổi của phương pháp ActionResult trên:

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 
} 

Tôi nghĩ rằng điều này làm cho nó dễ dàng hơn để Unit Test bằng cách thông qua JSON, thay vì sử dụng bộ sưu tập mẫu để gửi/lấy bộ sưu tập của chính/cặp giá trị.Ngoài ra, việc làm việc dễ dàng hơn là tìm cách xây dựng IModelBinder tùy chỉnh và IModelBinder tùy chỉnh có thể gây ra các vấn đề với các phương thức ActionResult khác khi đây là phương pháp duy nhất tôi cần thực hiện.

+0

Chris, xem bình luận của tôi ở trên. Tôi vẫn nghĩ rằng bạn đang đi về điều này một cách khó khăn. Tôi không chắc chắn 100% nhưng tôi có cảm giác niggling mà bạn đang có. – griegs

0

DefaultModelBinder có thể liên kết POST của bạn với mảng hoặc từ điển. Ví dụ:

cho mảng:

public ActionResult AddItems(string[] values) 

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

hay:

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

cho từ điển:

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"); 

CẬP NHẬT:

Nếu giá trị của bạn trong đầu vào HTML sau đó trong jQuery bạn có thể làm một cái gì đó như thế này:

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

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

CẬP NHẬT:

Ngoài ra kiểm tra này: Scott Hanselman's ComputerZen.com - ASP.NET Wire Format for Model Binding to Arrays, Lists, Collections, Dictionaries

+0

Tôi đã thử ví dụ từ điển của bạn, nhưng nó không kết thúc thông số "giá trị"; nó chỉ là một từ điển trống rỗng. –

+0

Bạn đã thử từ điển values ​​thay vì Dictionary . Đồng thời kiểm tra xem các giá trị [n] của bạn có bằng không và không bị gián đoạn. Kiểm tra http://stackoverflow.com/questions/1031416/asp-net-mvc-model-binding-a-set-of-dynamically-generated-checkboxes-how-to/1031694#1031694 cũng –

0

Đây là một bài đăng cũ nhưng tôi không thể không nhận được một vài nhận xét.

@ eu-ge-ne: "DefaultModelBinder có thể liên kết POST của bạn với mảng hoặc từ điển". Đúng nhưng ít nhất là cho từ điển tôi tìm thấy các ký hiệu hình thức yêu cầu khá phản trực giác.

@Chris: Hôm qua tôi đã gặp sự cố tương tự khi cố gắng đăng từ điển JavaScript (JSON) lên phương thức hành động của bộ điều khiển. Tôi đã tìm ra một bộ mô hình tùy chỉnh hoàn toàn khác để xử lý các từ điển chung với các đối số kiểu khác nhau. Tôi đã chỉ thử nghiệm nó trong MVC 3 và có lẽ đã có lợi thế của một khuôn khổ cải tiến.

Đối với các chi tiết kinh nghiệm của tôi và mã nguồn của mô hình tùy chỉnh chất kết dính, vui lòng xem bài viết trên blog của tôi tại http://buildingwebapps.blogspot.com/2012/01/passing-javascript-json-dictionary-to.html

2

Đây là những gì tôi đã cố gắng. Tiết kiệm rất nhiều công việc. 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"); 

Action Method:

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

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

} 
+0

Không chính xác những gì tôi muốn, gây ra không có điểm để vượt qua một đối tượng, nếu bạn chỉ có thể vượt qua từ điển chính nó nhưng điều này hoạt động tốt đủ. Được thăng hạng. :) –

Các vấn đề liên quan