我正在使用jQuery AJAX函數將複雜的JavaScript對象傳遞給ASP.NET Web服務中的Web方法。我跟着這篇文章(等等)中的建議:將複雜的JavaScript對象傳遞給ASP.NET Web服務
Using Complex Types to Make Calling Services Less Complex
我現在能夠從客戶端到瀏覽器和瀏覽器從到客戶端傳遞對象。但是,我遇到了一個超出我的技能來治癒的問題。當從客戶端到瀏覽器傳遞一個複雜對象時,數據在旅途中不知何故被「丟失」。它在JSON字符串中傳遞給Web服務,但是當ASP.NET AJAX將JSON字符串轉換爲對象的新實例並將其傳遞給服務方法時,會丟失部分內容。
複雜類型是一個Meal對象,由幾個屬性組成,一組用於膳食的Recipes和一組單獨的Food項目。數組中的每個Recipe對象都由幾個屬性和一個Food items的「字典」組成,其中Food項作爲鍵和它們各自的值作爲值。食物對象只具有屬性。看哪,各種物體的結構在JavaScript:
function Meal() {
this.MealNumber;
this.MealName;
this.MealType;
this.Ratio;
this.DailyCalorieTarget;
this.Recipes = [];
this.Foods = []
}
function Recipe() {
this.RecipeNumber;
this.RecipeName;
this.RecipeInstructions;
this.Foods = [];
}
function Food() {
this.FoodNumber;
this.FoodName;
this.CaloriesPerGram;
this.FatPerGram;
this.CarbsPerGram;
this.DietaryFiberPerGram;
this.ProteinPerGram;
this.Category;
}
現在,請在Web Service對應的對象:
Meal:
int MealNumber;
string MealName;
string MealType;
float Ratio;
int DailyCalorieTarget;
List<Recipe> Recipes;
List<KeyValuePair<Food, float>> Foods;
Recipe:
int RecipeNumber;
string RecipeName;
string RecipeInstructions;
List<KeyValuePair<Food, float>> Foods;
Food:
int FoodNumber;
string FoodName;
float CaloriesPerGram;
float FatPerGram;
float CarbsPerGram;
float DietaryFiberPerGram;
float ProteinPerGram;
string Category;
正如你所看到的,性質是相同的。你們中的一些人可能會問,爲什麼我在服務器端使用KeyValuePairs列表,而不是Dictionary對象。剩下的人已經知道Dictionary對象不會序列化成JSON字符串,並且KeyValuePairs的List將會。
現在,對於這個問題:我的web服務中有兩個web方法 - getMealData()和postMealData()。下面是我在做什麼調試目的:
當我點擊客戶端獲取進餐數據按鈕,我想提出一個AJAX請求,使用jQuery,到getMealData()方法。 getMealData()方法用一些Recipe和Food數據填充Meal對象,使用JavaScriptSerializer.Serializer方法序列化Meal並將JSON字符串發送回JSON.parse方法將字符串分析爲膳食對象的客戶端。
在那之後,我點擊發送進餐數據按鈕,JSON.stringify我剛從getMealData()方法創建完全相同的對象使用以下腳本:
功能postMealData(){
var DTO = { 'meal': meal } $.ajax({ type: "POST", url: "KetoCompanionService.asmx/postMealObject", data: JSON.stringify(DTO), contentType: "application/json; charset=utf-8", dataType: "json", success: function (msg) { $('#returnedData').html(msg.d); }, error: function (msg) { $('#returnedData').html(msg.responseText); } });
}
在獲得進餐數據並將其發送回服務器之間,我也沒有什麼不可以。這裏發生的一切就是我從服務器獲取JSON數據並將其解析爲JavaScript對象。我將EXACT SAME對象字符串化並將其發送回服務器。但是,我在服務器端獲得的內容與我發送的內容不匹配。
JSON字符串,我得到從服務器端的getMealData方法回:
{"MealNumber":1,"MealName":"Cheese Pizza, Strawberries, and Cream","MealType":"Dinner","Ratio":2.25,"DailyCalorieTarget":1600,"Recipes":[{"RecipeNumber":10,"RecipeName":"Cheese Pizza","RecipeInstructions":"Just fix the damned thing...","Foods":[{"Key":{"FoodNumber":1,"FoodName":"Eggs","CaloriesPerGram":1.432,"FatPerGram":0.823,"CarbsPerGram":0.234,"DietaryFiberPerGram":0,"ProteinPerGram":0.432,"Category":"Protein"},"Value":20},{"Key":{"FoodNumber":2,"FoodName":"Nuts","CaloriesPerGram":2.432,"FatPerGram":1.823,"CarbsPerGram":1.234,"DietaryFiberPerGram":1,"ProteinPerGram":1.432,"Category":"Protein"},"Value":10}]}],"Foods":[{"Key":{"FoodNumber":3,"FoodName":"Strawberries","CaloriesPerGram":0.332,"FatPerGram":0.723,"CarbsPerGram":0.034,"DietaryFiberPerGram":0.2,"ProteinPerGram":0.232,"Category":"Carbs"},"Value":120}]}
,我得到來自postMealData方法後面,它已被翻譯ASP後的字符串。NET AJAX插入服務器端的膳食物體看起來是這樣的:
{"MealNumber":1,"MealName":"Cheese Pizza, Strawberries, and Cream","MealType":"Dinner","Ratio":2.25,"DailyCalorieTarget":1600,"Recipes":[],"Foods":[]}
簡而言之,配方和食品陣列現在是空的。該數據發生了什麼?當然,我在來自客戶端的傳出數據和傳入的Web方法中設置斷點。該對象在離開時非常好,但在到達時丟失了數組數據。
我非常謙虛地承認我可以在做複雜的字符串化時犯一個愚蠢的錯誤。但是,我沒有做這個字符串化 - ASP.NET和JavaScript。我所做的只是在它們之間來回傳遞琴絃。
有什麼關於我失蹤的列表序列化?
H-E雙曲棍球棒在這裏可能會發生什麼?我正在拉我的頭髮!
感謝您花時間閱讀這麼長的文章。
傑里米
編輯補充:
客戶端getMealData()代碼:
function getMealData() {
$.ajax({
type: "POST",
url: "KetoCompanionService.asmx/getMealObject",
data: "{}",
contentType: "application/json; charset=utf-8",
dataType: "json",
success: function (msg) {
meal = JSON.parse(msg.d);
// Insert the returned HTML into the <div>.
$('#returnedData').html(msg.d);
},
error: function (msg) {
$('#returnedData').html(msg.responseText);
}
});
}
服務器端getMealDataMethod:
[WebMethod]
[ScriptMethod(UseHttpGet=false, ResponseFormat = ResponseFormat.Json)]
public string getMealObject() {
JavaScriptSerializer js = new JavaScriptSerializer();
_meal = new Meal();
_meal.MealNumber = 1;
_meal.MealName = "Cheese Pizza, Strawberries, and Cream";
_meal.MealType = "Dinner";
_meal.Ratio = 2.25f;
_meal.DailyCalorieTarget = 1600;
Recipe _recipe1 = new Recipe();
_recipe1.RecipeNumber = 10;
_recipe1.RecipeName = "Cheese Pizza";
_recipe1.RecipeInstructions = "Just fix the damned thing...";
Food _recipe1Food1 = new Food();
_recipe1Food1.FoodNumber = 1;
_recipe1Food1.FoodName = "Eggs";
_recipe1Food1.CaloriesPerGram = 1.432f;
_recipe1Food1.FatPerGram = 0.823f;
_recipe1Food1.CarbsPerGram = 0.234f;
_recipe1Food1.DietaryFiberPerGram = 0.0f;
_recipe1Food1.ProteinPerGram = 0.432f;
_recipe1Food1.Category = "Protein";
KeyValuePair<Food, float> _kvp1 = new KeyValuePair<Food, float>(_recipe1Food1, 20.0f);
_recipe1.Foods.Add(_kvp1);
Food _recipe1Food2 = new Food();
_recipe1Food2.FoodNumber = 2;
_recipe1Food2.FoodName = "Nuts";
_recipe1Food2.CaloriesPerGram = 2.432f;
_recipe1Food2.FatPerGram = 1.823f;
_recipe1Food2.CarbsPerGram = 1.234f;
_recipe1Food2.DietaryFiberPerGram = 1.0f;
_recipe1Food2.ProteinPerGram = 1.432f;
_recipe1Food2.Category = "Protein";
KeyValuePair<Food, float> _kvp2 = new KeyValuePair<Food, float>(_recipe1Food2, 10.0f);
_recipe1.Foods.Add(_kvp2);
_meal.Recipes.Add(_recipe1);
Food _mealFood1 = new Food();
_mealFood1.FoodNumber = 3;
_mealFood1.FoodName = "Strawberries";
_mealFood1.CaloriesPerGram = 0.332f;
_mealFood1.FatPerGram = 0.723f;
_mealFood1.CarbsPerGram = 0.034f;
_mealFood1.DietaryFiberPerGram = 0.2f;
_mealFood1.ProteinPerGram = 0.232f;
_mealFood1.Category = "Carbs";
KeyValuePair<Food, float> _kvp3 = new KeyValuePair<Food, float>(_mealFood1, 120.0f);
_meal.Foods.Add(_kvp3);
string returnString = js.Serialize(_meal);
return returnString;
}
UPDATE:
在我的getMealData()JavaScript函數中,我只是簡單地存儲了原始字符串,而不是從服務器解析返回的JSON數據並將其存儲在膳食對象中。
然後,在我的postMealData()JavaScript函數,而不是字符串化,將創建已經餐對象,我用的原始文本我自己的字符串化所做的:
var DTO = "{ \"meal\" : " + meal + "}";
然後,我發送的DTO字符串作爲我在AJAX請求中的data:
屬性。
我得到了同樣的結果。這幾乎就像ASP.NET使用不同的算法來序列化餐食對象,而不是將其反序列化。即使是我發回給我的原始JSON字符串也不起作用。
嗨,傑里米,你可以添加你的'getMealData()'代碼嗎?謝謝。 – 2014-09-04 03:59:44
@BrentMannering - 絕對。感謝您的時間。編輯添加。 – 2014-09-04 04:07:04
很高興你發現了這個問題,你應該讓你的最終更新成爲答案並接受它 – 2014-09-04 20:26:43