WebAPIで応答をシリアル化できませんでした


86

ASP.NET MVC Web APIで作業していましたが、次のエラーが発生します。

'ObjectContent`1'タイプは、コンテンツタイプ 'application / xmlの応答本文のシリアル化に失敗しました。charset = utf-8 '。

私のコントローラーは:

public Employee GetEmployees()
{
    Employee employees = db.Employees.First();
    return employees;
}

なぜこのエラーが発生するのですか?


6
表示されている例外は一般的な例外であり、さまざまな要因によって発生する可能性があります。InnerExceptionシリアル化例外のプロパティをチェックして、シリアル化が失敗した正確な原因を確認してください。
表示名

従業員タイプのコードを共有できますか?Employee型は...直列化可能ではないので、それはあるかもしれない
マギー英


回答:


121

私にとって、これは循環参照の問題でした。

受け入れられた回答は、JSONフォーマッターの動作を変更するだけなので機能しませんでしたが、ブラウザーからサービスを呼び出したときにXMLを取得していました。

これを修正するために、XMLをオフにして、JSONのみを強制的に返すようにしました。

Global.asaxファイルで、Application_Startメソッドの先頭に次の行を配置します。

GlobalConfiguration.Configuration.Formatters.JsonFormatter.SerializerSettings.ReferenceLoopHandling = Newtonsoft.Json.ReferenceLoopHandling.Ignore;
GlobalConfiguration.Configuration.Formatters.Remove(GlobalConfiguration.Configuration.Formatters.XmlFormatter);

これで、JSONの結果のみが返されます。XMLの結果が必要な場合は、別の解決策を見つける必要があります。


私のために働いた。しかし、事は私がPOSTMANを使用しているということです。Chrome拡張機能です。POSTMANでデータを投稿すると、正常に機能します。しかし、restsharpを使用すると、このエラーが発生します。とにかくあなたの解決策は私の問題を解決しました
ArgeKumandan 2015

この答えはxmlを使用するための解決策を提供しません、そしてそれは彼が求めたものです。
honestduane

私はxmlからjsonに切り替えたので私のために働きます。
Sike12 2015

実際、この答えが問題の根源になります。私が受け取った最初のエラーは循環参照エラーでした(MVCコントローラーからJSONを返そうとしました)。API継承コントローラーに切り替えると、代わりにこのエラーが発生し始めました。上記のコードをGlobal.asaxに追加すると、エラーはなくなりました。
マシュウピッツ2016

43

global.asaxファイルのApplication_start()メソッドに次の行を追加します。

GlobalConfiguration.Configuration.Formatters.JsonFormatter.SerializerSettings.ReferenceLoopHandling = Newtonsoft.Json.ReferenceLoopHandling.Ignore;

お役に立てば幸いです。


3
application_startとは何ですか?どこにありますか?そして、この線は正確にどこに配置する必要がありますか?
キアランギャラガー

4
申し訳ありませんが、このステートメントの意味は何ですか?
ブレイズ

5
Global.asax'sに行が追加されましたApplication_Startが、変更はありません。
cheesus 2013

8
これはまだ私にはうまくいきませんでした。ただし、この回答の後に別の行を追加すると、機能しました。GlobalConfiguration.Configuration.Formatters.Remove(GlobalConfiguration.Configuration.Formatters.XmlFormatter); 私は以下にもっと完全な答えを作成しました
Zane 2013年

2
この回答は、XmlSerializerによる循環参照の問題に対処するのではなく、実際にXmlSerializerを削除するため、受け入れられるべきではありません。
Believe2014 2014年

29

同じ問題が発生しました。そして、私はそれを解決しました。デフォルトのコンストラクターをDTOクラスに配置しました。

例:

public class User
{
    public User()
    {
    }
}

それがあなたとうまくいくことを願っています!


提案をありがとう、これはxml応答で私を助けました、しかし誰かがそれがデフォルトのコンストラクターを必要とする理由を知っていますか?私たちは...すでにデータを持っている
イリヤChernomordik

オブジェクトが応答からシリアル化されるとき、最初にコンストラクターが呼び出されてオブジェクトのインスタンスが作成され、その後、setメソッドを使用してデータがオブジェクトインスタンスに設定されると思います。それは私の推測です。
taynguyen 2015

これは、必要なリターンタイプについて何も想定していないため、実際に選択された回答である必要があります。これは、XMLとJSONの両方で機能します。これを投稿していただきありがとうございます。
アレンアンダーウッド

22

これをコンストラクターに入れます。これが問題を解決することを願っています:

    public MyController()
    {

        db.Configuration.ProxyCreationEnabled = false;
    }

優れたソリューション。私はそれをコンストラクターに入れる必要があり、それは機能しました。
InsParbo 2017年

これは、GlobalConfiguration設定と組み合わせて機能しました。しかし、なぜこれが機能するのですか?これがどのように問題を解決するかについての説明はありますか?そして、実際の問題は何でしたか?
Ciaran Gallagher 2017

:エンティティプロキシが何であるかを理解するためにmsdn.microsoft.com/en-us/library/jj592886(v=vs.113).aspx :ProxyCreationEnabledが何であるかを理解するためにstackoverflow.com/questions/7111109/...
Sadjad Khazaie

16

私はこれに対する2つの解決策を見つけました。最初で最も簡単に実装できるのは、IEnumerables、ICollectionsをリストのタイプに変更することです。WebAPIはこのオブジェクトをシリアル化できますが、インターフェースタイプをシリアル化することはできません。

public class Store
{

  [StringLength(5)]
    public string Zip5 { get; set; }

    public virtual List<StoreReport> StoreReports { get; set; }  //use a list here
 }

もう1つのオプションは、ネイティブJSONシリアライザーを使用せず、WebApiConfigのRegisterメソッドでこのオーバーライドを実行することです。

        var json = config.Formatters.JsonFormatter;
        json.SerializerSettings.PreserveReferencesHandling = Newtonsoft.Json.PreserveReferencesHandling.Objects;
        config.Formatters.Remove(config.Formatters.XmlFormatter);

1
リストへの変更は私にとってはうまくいきましたが、パラメーターなしのコンストラクターの追加も私にとってはうまくいき、IEnumerable <Widget>を返し続けることができました
Mike Cheel 2013

8

解決策は簡単です。

LINQクエリの後に、.ToList()(または必要に応じてToDictionary)を追加します。

データの遅延読み込みよりも積極的な読み込みを行います


1
アクションの戻り値の型をに変更し、戻り値にIENumerable追加.TiList()することでうまくいきました。
リカルドソウザ

5

**このバグは、クライアント側からリクエストWeb api / wcf / ...から呼び出すときに発生しますが、副作用として、includeキーワードで依存関係を含める必要があります。****

public CustomerPortalContext()
            : base("Name=CustomerPortalContext")
        {
            base.Configuration.ProxyCreationEnabled = false;
        }

4

Global.asaxに以下のコードを追加する以外に、EFを使用している場合

            GlobalConfiguration.Configuration.Formatters.JsonFormatter.SerializerSettings.ReferenceLoopHandling = Newtonsoft.Json.ReferenceLoopHandling.Ignore;
        GlobalConfiguration.Configuration.Formatters.Remove(GlobalConfiguration.Configuration.Formatters.XmlFormatter);          

インポートすることを忘れないでください

using System.Data.Entity;

その後、あなたはあなた自身のEFモデルを返すことができます



3

EntityFrameworkでWebAPIを使用する場合、ソリューションが失敗して、Jsonを使用してWebAPIで応答をシリアル化できない可能性があり ます

基本的に、各EFモデルに対応するモデルを作成する必要があります。これにより、クラス間の依存関係が削除され、簡単にシリアル化できるようになります。

コード:(参照リンクから取得)

UserModelを作成する

public class UserModel
{
    public string FirstName { get; set; }
    public string LastName { get; set; }
}

メソッドを変更するGetAll()

public IEnumerable<UserModel> GetAll()
{
    using (Database db = new Database ())
    {
        List<UserModel> listOfUsers = new List<UserModel>();
        UserModel userModel = new UserModel();
        foreach(var user in db.Users)
        {
           userModel.FirstName = user.FirstName;
           userModel.LastName = user.LastName;
           listOfUsers.Add(userModel);
        }
        IEnumerable<UserModel> users = listOfUsers;

        return users;
    }
}

2

デフォルトのエンティティ6はXML使用してAPIを作成し、プロジェクトでファイル「Global.asax」ファイルを見つけて次の行を追加します。

GlobalConfiguration.Configuration.Formatters.Remove(GlobalConfiguration.Configuration.Formatters.XmlFormatter);

この行は、XMLフォーマッターを削除します。


あなたは、ヘッダーのContent-Typeを追加した場合、こんにちは、ウェブAPIのシリアル化XMLとJSONのレスポンス:アプリケーション/ JSON、レスポンスはJSONであり、あなたは常にあなたがXML形式としてそれを見ることができるブラウザで、このヘッダーを定義する必要が
Roberthソリス

1

しかし、他のエンティティ/クラスでこの問題を見つけた場合は、クラスごとに新しいDTOを作成する必要があり、それらがたくさんある場合は問題を見つけることができます。また、この問題を解決するためだけにDTOを作成すると思います。最善の方法ではありません...

これを試しましたか?

var json = GlobalConfiguration.Configuration.Formatters.JsonFormatter;
json.SerializerSettings.PreserveReferencesHandling = 
Newtonsoft.Json.PreserveReferencesHandling.All;

よろしく


1

うーん、以下が役立つかもしれません。

同じ例外が発生しました。私の場合、エンティティコード用に作成された実際のpocoエンティティを最初に渡していました。他のエンティティとの関係が含まれているため、その上にviewmapper / dtoエンティティを作成して返します。

今は問題なく動作します。

Pocoエンティティ:

public class Tag
{
public int Id{get;set;}
public string Title{get;set;}
public IList<Location> Locations{get;set;}
}

ViewMapper / Dto

public class TagResultsViewMapper
{
public int Id{get;set;}
public string Title{get;set;}
//just remove the following relationship 
//public IList<Location> Locations{get;set;}
}

0

あなたの質問は私のものと非常に似ています。データベースから直接データを返さないでください。このためには、モデルを作成し、表示するデータを関連付ける必要があります。

私の例では、Jsonがシリアル化できなかったユーザーに関するデータがあり、userModelを作成し、APIで、データベースからUserの代わりにuserModelを返します。

UserとUserModelの間でデータを変換または関連付けるロジックはAPIに含まれている必要があります。

Jsonを使用してWebAPIで応答をシリアル化できませんでした


0

これは、odata WebAPI呼び出しから返ってきた特定のエラーでした。

The 'ObjectContent`1' type failed to serialize the response 
body for content type 'application/json; odata.metadata=minimal'.

私はついに、dbContextクラスのonModelCreatingで割り当てられているテーブル名の形式が不適切であることがわかりました。そのため、SqlClientは、dbに存在しないテーブルを探していました。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.