我正在使用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