2014-09-04 90 views
2

我正在使用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()。下面是我在做什么调试目的:

  1. 当我点击客户端获取进餐数据按钮,我想提出一个AJAX请求,使用jQuery,到getMealData()方法。 getMealData()方法用一些Recipe和Food数据填充Meal对象,使用JavaScriptSerializer.Serializer方法序列化Meal并将JSON字符串发送回JSON.parse方法将字符串分析为膳食对象的客户端。

  2. 在那之后,我点击发送进餐数据按钮,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字符串也不起作用。

+0

嗨,杰里米,你可以添加你的'getMealData()'代码吗?谢谢。 – 2014-09-04 03:59:44

+0

@BrentMannering - 绝对。感谢您的时间。编辑添加。 – 2014-09-04 04:07:04

+0

很高兴你发现了这个问题,你应该让你的最终更新成为答案并接受它 – 2014-09-04 20:26:43

回答

3

解决方案 - 第1部分

我发现为什么我的食谱和食品阵列是空的 - 我每餐,配方创建的每个公共财产,并在ASP.NET食品类既具有getter和一个setter - - 列表除外。我忽略了在该属性中放置一个setter,这使得它只读。因此,Web方法无法访问这些属性来设置它们。

但是,我还没有走出困境。尽管我发现了缺失的数据,但我的食物阵列在服务器端即将发布{Key:null,Value:0},即使我正在发送食物数据键值对。

解决方案 - 第2部分

我修复了这个问题。

显然,ASP.NET AJAX在涉及到KeyValuePair对象列表时反序列化JSON时存在问题。

因此,而不是使用类型,List<KeyValuePair<Food, float>>,存放我个人的食品,我创建了自己的类我称之为FoodWithAmount与性能FoodItemAmount和而不是使用这样的:List<KeyValuePair<Food, float>>,我使用的是这样的:List<FoodWithAmount> 。服务器端将JSON字符串翻译成用餐对象,完美的是,一旦我实现了这一改变。

public class FoodWithAmount 
{ 
    Food _foodItem; 
    float _amount; 

    public Food FoodItem 
    { 
     get { return _foodItem; } 
     set { _foodItem = value; } 
    } 

    public float Amount 
    { 
     get { return _amount; } 
     set { _amount = value; } 
    } 

    //Parameterless constructor is necessary for serialization 
    public FoodWithAmount() 
    { 
    } 

    public FoodWithAmount(Food foodItem, float amount) 
    { 
     _foodItem = foodItem; 
     _amount = amount; 
    } 
} 

出的同时学习JavaScript,ASP.NET,jQuery的,HTML,而且在过去的几个星期CSS我所遇到的一切障碍,这个问题已经消耗了我的时间和思想比任何其他。

我希望我的痛苦让别人的旅程变得更轻松。

快乐编码!