2013-01-12 50 views
2

通過HttpResponseMessage MVC4成功發送一個AngularJs控制器$ GetAllFolders()的範圍。

集合中的文件夾包含其他內容以及與Photo類的關聯。

文件夾可以是其他文件夾(自引用)的文件夾。

從MVC4端調試顯示,所有返回的都是很好且正確的詳細信息。

但通過角/ JSON,某些屬性是$ REF標籤,並不能看到,因爲例如:

enter image description here

我不太關心創建於FkPhotoId方法調用並擊中服務器對於圖片名稱,當我知道它已經在第一個響應中發送了。

任何想法?

UPDATE:解決方案

在Global.asax中添加此代碼:(請確保您引用它的啓動方法)

public static void ConfigureApi(HttpConfiguration config) 
    { 
     var json = config.Formatters.JsonFormatter; 
     config.Formatters.Remove(config.Formatters.XmlFormatter); 
     config.Formatters.JsonFormatter.SerializerSettings.ReferenceLoopHandling = Newtonsoft.Json.ReferenceLoopHandling.Ignore; 
    } 

enter image description here

+3

請添加您的解決方案作爲答案 - 然後這個問題將不會顯示在「未答覆」列表。你可以(也應該)也接受它。 –

+0

如何去做這件事? – Bye

+0

在下面的文本框中,輸入你的答案,點擊「發佈你的答案」按鈕。 (可以從問題中刪除您的解決方案)。然後點擊答案旁邊的複選標記。 –

回答

8

分辨率從OP( housecleaning - 標記,因此可以標記回答) 此代碼已添加到global.asax中:(請確保在啓動方法中引用它)

public static void ConfigureApi(HttpConfiguration config) 
{ 
    var json = config.Formatters.JsonFormatter; 
    config.Formatters.Remove(config.Formatters.XmlFormatter); 
    config.Formatters.JsonFormatter.SerializerSettings.ReferenceLoopHandling = Newtonsoft.Json.ReferenceLoopHandling.Ignore; 
} 
0

只是爲了增加我的兩分錢。我在我的代碼中有這額外的行,這也是造成這個問題

config.Formatters.JsonFormatter.SerializerSettings.PreserveReferencesHandling = Newtonsoft.Json.PreserveReferencesHandling.Objects; 

感謝digger69這一個。

0

我厭倦了看到這個答案「只需禁用東西並解決它。」這是懶惰的,這是錯誤的,並且對保留這些數據的有用性產生了令人難以置信的減少。

這是一個三部分的答案。第一部分是禁用集合引用並僅保留對象。

在我的情況下,我想不出一個場景,我會共享集合引用和其他代碼是混亂的。如果您需要收集參考書寫消費FE邏輯。不要只是禁用它。只是碰巧我不需要它。

config.Formatters.JsonFormatter.SerializerSettings.ReferenceLoopHandling = Newtonsoft.Json.ReferenceLoopHandling.Serialize; 
config.Formatters.JsonFormatter.SerializerSettings.PreserveReferencesHandling = Newtonsoft.Json.PreserveReferencesHandling.Objects; 
config.Formatters.JsonFormatter.SerializerSettings.ContractResolver = new CamelCasePropertyNamesContractResolver(); 

第二部分在這裏。我從另一個答案中得到了這個,並添加了一個缺失的調整。 (這是原來Resolve circular references from JSON object):

function resolveReferences(json) { 
 
    if (!json) 
 
     return json; 
 

 
    if (typeof json === 'string') 
 
     json = JSON.parse(json); 
 

 
    var byid = {}, // all objects by id 
 
     refs = []; // references to objects that could not be resolved 
 
    json = (function recurse(obj, prop, parent) { 
 
     if (typeof obj !== 'object' || !obj) // a primitive value 
 
      return obj; 
 
     if (Object.prototype.toString.call(obj) === '[object Array]') { 
 
      for (var i = 0; i < obj.length; i++) 
 
       // check also if the array element is not a primitive value 
 
       if (typeof obj[i] !== 'object' || !obj[i]) // a primitive value 
 
        continue; 
 
       else if ("$ref" in obj[i]) 
 
        obj[i] = recurse(obj[i], i, obj); 
 
       else 
 
        obj[i] = recurse(obj[i], prop, obj); 
 
      return obj; 
 
     } 
 
     if ("$ref" in obj) { // a reference 
 
      var ref = obj.$ref; 
 
      if (ref in byid) 
 
       return byid[ref]; 
 
      // else we have to make it lazy: 
 
      refs.push([parent, prop, ref]); 
 
      return; 
 
     } else if ("$id" in obj) { 
 
      var id = obj.$id; 
 
      delete obj.$id; 
 
      if ("$values" in obj) // an array 
 
       obj = obj.$values.map(recurse); 
 
      else // a plain object 
 
       for (var prop in obj) 
 
        obj[prop] = recurse(obj[prop], prop, obj); 
 
      byid[id] = obj; 
 
     } 
 
     return obj; 
 
    })(json); // run it! 
 

 
    for (var i = 0; i < refs.length; i++) { // resolve previously unknown references 
 
     var ref = refs[i]; 
 
     ref[0][ref[1]] = byid[ref[2]]; 
 
     // Notice that this throws if you put in a reference at top-level 
 
    } 
 
    return json; 
 
}

第二部分是重新處理和重新建立之前發送回數據循環依賴。我的FE是一個角度應用程序,所以我個人在ajax帖子之前在注入的HTTP攔截器中調用它(注意我正在檢查名爲「typeName」的屬性,因爲所有具有該屬性的對象都被假定爲將會反序列化在後端)。

function processReferenceEstablishment(data) { 
 
    if (!data || typeof (data) === 'function') 
 
     return undefined; 
 

 
    var processData = []; 
 
    var tiers = {}; 
 
    var refKey = 1; 
 
    if (Array.isArray(data)) { 
 
     data = jQuery.extend([], data); 
 
    } else { 
 
     data = jQuery.extend({}, data); 
 
    } 
 

 

 
    
 

 
    var retVal = (function recurse(obj, tier) { 
 
     tiers[tier] = tiers[tier] || {}; 
 
     tiers[tier].width = tiers[tier].width ? tiers[tier].width + 1 : 1; 
 
     if (obj) { 
 
      if (typeof obj !== 'object' || typeof (obj) === 'function') { 
 
       return obj; 
 
      } 
 

 
      for (var key in data) { 
 
       var val = data[key]; 
 
       if (key.indexOf("$") > -1 || typeof(val) === 'function') { 
 
        delete data[key]; 
 
       } 
 
      } 
 
      if (Array.isArray(obj)) { 
 
       obj = jQuery.extend([], obj); 
 
       for (var ix = 0; ix < obj.length; ix++) { 
 
        obj[ix] = recurse(obj[ix], tier); 
 
       } 
 
      } 
 
      else if ('typeName' in obj) { 
 
       if (obj.skipSend) { 
 
        return undefined; 
 
       } 
 
       obj = jQuery.extend({}, obj); 
 
       var found = false; 
 
       for (var pdIx = 0; pdIx < processData.length; pdIx++) { 
 
        var item = processData[pdIx]; 
 
        if (item.id === obj.id && item.typeName === obj.typeName) { 
 
         found = true; 
 
         if (!item.jsonTier || item.jsonTier > tier) { 
 
          item.jsonTier = tier; 
 
          item.jsonWidth = tiers[tier].width; 
 
         } 
 
         if (tier === item.jsonTier && item.jsonWidth > tiers[tier].width) { 
 
          item.jsonWidth = tiers[tier].width; 
 
         } 
 
         if (tier > item.jsonTier || (tier === item.jsonTier && item.jsonWidth < tiers[tier].width)) { 
 
          return { $ref: item.$id.toString() }; 
 
         } 
 
         break; 
 
        } 
 
       } 
 
       if (!found) { 
 
        obj.$id = refKey; 
 
        refKey++; 
 
        processData.push({$id:obj.$id, id: obj.id, typeName: obj.typeName, jsonTier: tier, jsonWidth: tiers[tier].width }); 
 
       } 
 
       var keys = Object.keys(obj); 
 
       keys.sort(); 
 
       for (var key in keys) { 
 
        key = keys[key]; 
 
        obj[key] = recurse(obj[key], tier + 1); 
 
       } 
 
      } 
 
     } 
 
     return obj; 
 
    })(data, 1); 
 

 
    retVal = (function recurse(obj, tier) { 
 
     tiers[tier] = tiers[tier] || {}; 
 
     tiers[tier].destWidth = tiers[tier].destWidth ? tiers[tier].destWidth + 1 : 1; 
 
     if (typeof obj !== 'object' || !obj) { 
 
      return obj; 
 
     } 
 
     if (Array.isArray(obj)) { 
 
      for (var ix = 0; ix < obj.length; ix++) { 
 
       obj[ix] = recurse(obj[ix], tier); 
 
      } 
 
     } 
 
     else if ('typeName' in obj) { 
 
      var found = false; 
 
      for (var pdIx = 0; pdIx < processData.length; pdIx++) { 
 
       var item = processData[pdIx]; 
 
       if (item.id === obj.id && item.typeName === obj.typeName) { 
 
        found = true; 
 
        if (item.jsonTier < tier || (item.jsonTier === tier && item.jsonWidth < tiers[tier].destWidth)) { 
 
         return { $ref: item.id.toString() }; 
 
        } 
 
       } 
 
      } 
 
      var keys = Object.keys(obj); 
 
      keys.sort(); 
 
      for (var key in keys) { 
 
       key = keys[key]; 
 
       obj[key] = recurse(obj[key], tier + 1); 
 
      } 
 
     } 
 
     return obj; 
 
    })(retVal, 1); 
 
    return retVal; 
 
}

現在,予以明確。我重新建立$ ref和$ id經常發生錯誤,並且在後端返回null的時候,我得到奇怪的集合對象引用或導航屬性對象引用。我仍在爲此努力。我真的需要拉下NewtonSoft.JSON庫並將它們分開以找出處理對象圖的順序,以便在反序列化之後消除空引用。

對我來說,這是一個真正的解決方案,而不是扔在毛巾和禁用循環參考,因爲懶惰。