2014-09-04 116 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我所遇到的一切障礙,這個問題已經消耗了我的時間和思想比任何其他。

我希望我的痛苦讓別人的旅程變得更輕鬆。

快樂編碼!

相關問題