2016-10-11 3 views
2

私は、ASP.NET Web API(.NET 4.6.2)と呼ばれるバックエンド、Web APIクライアント実装PCL(別名ミドルウェア)、Xamarin.Formsプロジェクト(フロントエンド)を含むソリューションを作成しています。私のフロントエンドでJSONレスポンスを逆シリアル化しようとすると、私のWeb APIへの最近の変更の後、私は常にStackOverflowExceptionを取得します。特定の行は次のとおりです。JsonConvert.DeserializeObjectのStackOverflowException

result_ = JsonConvert.DeserializeObject<ObservableCollection<Employee>>(Encoding.UTF8.GetString(responseData_, 0, responseData_.Length)); 

私は、オーバーフローが発生するまでプログラムは2行の間にジャンプしていることがわかり、ここでデバッグしています:(ミドルウェアで)

EmployeesManager.cs

を(ミドルウェア)で
private Image _image = new Image(); 

ImagesManager.cs

private Employee _employee = new Employee(); 
012 (ウェブAPIで)

モデル::クライアントの実装(ミドルウェア)で

public class Employee 
{ 
    public int Id { get; set; } 

    // OMITTED PROPS 

    public int? ImageId { get; set; } 
    public Image Image { get; set; } 

    public ICollection<Device> Devices { get; set; } 

    public int? TeamId { get; set; } 
    public Team Team { get; set; } 
} 

public class Image 
{ 
    [Key] 
    public int Id { get; set; } 

    [Required] 
    public byte[] Data { get; set; } 

    public int EmployeeId { get; set; } 

    public Employee Employee { get; set; } 
} 

モデルここ

は、より多くのコードです。彼らはNswagで生成されます。

public partial class Employee : INotifyPropertyChanged 
{ 
    private int _id; 

    private int? _imageId; 
    private Image _image = new Image(); // THIS LINE IS PART OF THE OVERFLOW 
    private ObservableCollection<Device> _devices; 
    private int? _teamId; 
    private Team _team = new Team(); 

    // OMITTED PROPS 

    [JsonProperty("image", Required = Required.Default, NullValueHandling = NullValueHandling.Ignore)] 
    public Image Image 
    { 
     get { return _image; } 
     set 
     { 
      if (_image != value) 
      { 
       _image = value; 
       RaisePropertyChanged(); 
      } 
     } 
    } 

public partial class Image : INotifyPropertyChanged 
{ 
    private int _id; 
    private int _employeeId; 
    private Employee _employee = new Employee(); // THIS LINE IS PART OF THE STACK OVERFLOW 
    private byte[] _data; 

    // OMITTED PROPS 

    [JsonProperty("employee", Required = Required.Default, NullValueHandling = NullValueHandling.Ignore)] 
    public Employee Employee 
    { 
     get { return _employee; } 
     set 
     { 
      if (_employee != value) 
      { 
       _employee = value; 
       RaisePropertyChanged(); 
      } 
     } 
    } 

私はXamarin.Formsプロジェクトを通じてウェブAPIクライアント実装を使用します。動作はすべてのプラットフォームで同じです。ただし、iOSとUWPだけがスタックオーバーフローを認識します。 Android上では、Web APIからデータを読み込んでいるときに例外なしでアプリが終了するだけです。

誰かがもっとコードを見たい場合は、要求されたコードを含む小さなパッケージを用意することができます。これらをすべてここに投稿すると、読みやすさが完全に損なわれます。

私はNewtonsoft Json.NET、Entity Framework 6、NSwag 6、Xamarin.Forms v2.3.2.127を使用します。

+3

オブジェクトは相互に参照し、無限の再帰を引き起こします。シリアライザがこれらのプロパティを追跡しようとしないように、 '[JsonIgnore]'またはそれに類するもので1つ以上のナビゲーションプロパティを修飾する必要があるかもしれません。 – David

+0

@zuckerthoben、どのようにテンプレートを生成しましたか? T4?あなたが私を助けることができると確信しています。[こちら](https://github.com/NSwag/NSwag/issues/553)を見てください。 – Shimmy

+0

@Shimmyあなたの問題が解決されたことを知りました。私は自動統合を持っていないので、とにかく助けてくれませんでした。 Web APIがそれほど変わっていないので、私はそれを必要としません。 – zuckerthoben

答えて

1

私はOxidda、DavidとEJoshuaSの答えに従った。ここで

は、完全なドキュメントの目的のための完全なソリューションです:

私はミドルウェア(ウェブAPIクライアントPCL)内のImageクラスの従業員のプロパティでJsonIgnoreを入れてみました。不思議なことに、問題を解決しなかった。私はまだプロパティの後ろにプライベート変数を持つスタックオーバーフローを持っています。 ここでは、JsonIgnoreをWeb API(バックエンド)のImageクラスのEmployeeナビゲーション・プロパティと、DeviceクラスのEmployeeナビゲーション・プロパティに置きます。その後、APIが既に無視されているため、これらのプロパティのJSONは受信されないため、APIクライアント(ミドルウェア)からナビゲーションプロパティ(画像クラスの従業員とデバイスクラスのEmployee)を完全に削除しました。 エラーは今や離れており、私は要求と応答にかなりのスピードをもたらしました。 Web API(バックエンド)が正常に動作していて関係に問題がないように見えますが、オプションモデルのナビゲーションプロパティは高いオーバーヘッドをもたらしました。クラスは非常に小さく、データベースのテーブルはほとんど空ですが、影響は大きいようです。

TL; DR:ソースでの循環参照の可能性を排除しました。クライアントに反映された変更。問題は解決され、巨大なスピードブーストも受けました。

誰かが私のソリューションの完全な設計に興味を持っている場合、ここでは小さなサマリーがあります。それは大好きです。

  1. Entity Framework 6を​​使用してASP.NET Web API(.NET 4.6.2)プロジェクトを作成しました。リレーションシップを追加し、DbContextを追加したモデルを追加しました。スキャフォールドされた非同期コントローラ。 Web APIが実行されます。エンティティフレームワークをJSonで使用するときは、遅延読み込みを使用しないでください。代わりに私はコントローラで熱心な負荷を使用します。
  2. Xamarin PCLが使用しているのと同じプロファイルのPCLを作成しました。したがって、Xamarinソリューションだけでなく、他のすべての標準.NETソリューションとも互換性があります。
  3. Web APIに基づいてNSwagのミドルウェアAPIを生成しました。基本的には、プログラムにAPI.dllをロードし、設定を選択すると、C#でWeb APIの完全なPCL互換クライアント実装が提供されます。 APIは非常に高レベルで非同期なので、.NETフロントエンドでAPIを簡単に使用できます。
  4. お好みのフロントエンドソリューションを追加します。クライアントAPIを使用してデータを簡単に使用できます。

基本的にはあなただけのWeb APIのいくつかのプロパティを書き込む(+ JSONシリアライザとDbContextを設定)し、全体のバックエンドとミドルウェアの残りが生成されることができます。大好きです。

1

これは以前私に起こっていました。それはオブジェクト間の循環参照によるものでした。従業員は、従業員を参照する画像と画像を参照しています。

ImageクラスのEmployeeプロパティの上に[JsonIgnore]を配置してみてください。

+0

私は同意する、これは正しいソリューションだと思う。 – EJoshuaS

+0

循環参照はWeb APIでは問題ありません。循環参照がある場合、Web APIは有効なjsonを返しません。 Webサーバー上でwiresharkを実行し、要求と応答が有効であることを検証します。 クライアントの実装に循環参照に関する問題があると思われます。この問題です。そこで、私は、JsonIgnoreをapiクライアントの画像クラスのナビゲーションプロパティに配置しようとします。 – zuckerthoben

+1

@zuckerthoben Web APIの観点から、循環参照は問題ではないかもしれませんが、多くのシリアライゼーションライブラリにとっては間違いなく問題です。 – EJoshuaS