2

HttpResponseMessage を介して、MVC4 は AngularJs コントローラー $scope の GetAllFolders() を正常に送信します。

コレクション内のフォルダーには、特に Photo クラスへの関連付けがあります。

フォルダーは、他のフォルダーのフォルダーにすることができます (自己参照)。

MVC4 側からのデバッグはすべて良好で、正しい詳細情報が返されたことを示しています。

ただし、Angular/Json では、特定のプロパティが $ref タグであり、次の例のように表示されません。

ここに画像の説明を入力

FkPhotoId でメソッド呼び出しを作成することはあまり気にせず、最初の応答で既に送信されていることがわかっている場合は、サーバーに画像名をヒットします。

何か案は?

更新: 解決策

このコードは、global.asax に追加されました: (必ず start メソッドで参照してください)

    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; 
    }

ここに画像の説明を入力

4

3 に答える 3

8

OP からの解決策 (ハウスクリーニング - マークを付けると、回答済みとしてマークできます) このコードは、global.asax に追加されました: (start メソッドで必ず参照してください)

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; 
}
于 2013-01-17T20:50:37.447 に答える
1

この回答「無効にして回避するだけ」を見るのにうんざりしています。それは怠惰で間違っており、このデータを保持することの有用性を信じられないほど還元しています。

これは 3 つの部分からなる答えです。最初の部分は、コレクション参照を無効にし、オブジェクトのみを保持することです。

私の場合、コレクション参照を共有し、追加のコードが乱雑になるというシナリオは考えられませんでした。コレクション参照が必要な場合は、CONSUMING 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();

第二弾はこちら。別の回答からこれを取得し、欠落していた微調整を追加しました。(これは元のJSON オブジェクトからの循環参照の解決です):

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;
}

2 番目の部分は、データを送り返す前に循環依存関係を再処理して再確立することです。私のFEはAngularアプリなので、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 ライブラリをプルダウンしてばらばらにして、オブジェクト グラフを処理する順序を決定し、デシリアライズ後に null 参照を削除できるようにする必要があります。

私にとって、これは怠惰のためにタオルを投げて循環参照を無効にするのではなく、本当の解決策に向かっています。

于 2016-10-14T22:49:16.957 に答える
0

私の2セントを追加するだけです。コードにこの余分な行があり、この問題も引き起こしていました

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

これについてdigger69に感謝します。

于 2015-10-02T08:42:02.607 に答える