web-dev-qa-db-ja.com

JsonによるWeb APIのレスポンスのシリアル化に失敗しました

私はASP.NET MVC 5 Web Apiを使用しています。私はすべての私のユーザーに相談したいです。

私はapi/usersを書きました、そして私はこれを受け取ります:

"'ObjectContent`1'タイプは、コンテンツタイプ 'application/jsonのレスポンスボディのシリアル化に失敗しました。charset = utf-8'"

WebApiConfigでは、すでにこれらの行を追加しました。

HttpConfiguration config = new HttpConfiguration();
config.Formatters.XmlFormatter.SupportedMediaTypes.Remove(appXmlType);
config.Formatters.JsonFormatter.SerializerSettings.ReferenceLoopHandling = Newtonsoft.Json.ReferenceLoopHandling.Ignore; 

しかし、まだうまくいきません。

戻りデータのための私の機能はこれです:

public IEnumerable<User> GetAll()
{
    using (Database db = new Database())
    {
        return db.Users.ToList();
    }
}
95
CampDev

Web Api(または他のWebサービス)からデータをコンシューマに返す場合、データベースから取得したエンティティを返さないことを強くお勧めします。データベースではなく、データの外観を制御できるモデルを使用する方がはるかに信頼性が高く、保守性があります。そうすれば、WebApiConfigでフォーマッタをそれほど混乱させる必要はありません。子Modelをプロパティとして持つUserModelを作成して、戻りオブジェクト内の参照ループを取り除くことができます。それはシリアライザをはるかに幸せにします。

また、リクエストで「Accepts」ヘッダーを指定しているだけであれば、通常はフォーマッタやサポートされているメディアタイプを削除する必要はありません。そのようなもので遊ぶことは時々物事をより混乱させることができます。

例:

public class UserModel {
    public string Name {get;set;}
    public string Age {get;set;}
    // Other properties here that do not reference another UserModel class.
}
69
jensendp

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モデルを返すことができます

そのような単純な!

130
Lucas Roselli

正しい答えを与えることは一つのやり方ですが、一つの設定でそれを直すことができればやり過ぎです。

Dbcontextコンストラクタで使用するほうが良い

public DbContext() // dbcontext constructor
            : base("name=ConnectionStringNameFromWebConfig")
{
     this.Configuration.LazyLoadingEnabled = false;
     this.Configuration.ProxyCreationEnabled = false;
}

Asp.Net Web APIエラー: 'ObjectContent`1'タイプはコンテンツタイプ 'application/xmlのレスポンスボディのシリアル化に失敗しました; charset = utf-8'

51

このコードをglobal.asaxの下のApplication_Startに追加します。

.Ignoreから.Serializeに更新しました。それはうまくいくはずです。

GlobalConfiguration.Configuration.Formatters.JsonFormatter.SerializerSettings.ReferenceLoopHandling = Newtonsoft.Json.ReferenceLoopHandling.Serialize;
            GlobalConfiguration.Configuration.Formatters.Remove(GlobalConfiguration.Configuration.Formatters.XmlFormatter);
32
Bimal Das
public class UserController : ApiController
{

   Database db = new Database();

   // construction
   public UserController()
   {
      // Add the following code
      // problem will be solved
      db.Configuration.ProxyCreationEnabled = false;
   }

   public IEnumerable<User> GetAll()
    {
            return db.Users.ToList();
    }
}
10
Aykut

私はこのコードが好きではありません:

foreach(var user in db.Users)

代替手段として、このようなことをすることもできます。

var listOfUsers = db.Users.Select(r => new UserModel
                         {
                             userModel.FirstName = r.FirstName;
                             userModel.LastName = r.LastName;

                         });

return listOfUsers.ToList();

しかし、私はLucas Roselliのソリューションを使用しました。

更新:匿名オブジェクトを返すことで単純化された:

var listOfUsers = db.Users.Select(r => new 
                         {
                             FirstName = r.FirstName;
                             LastName = r.LastName;
                         });

return listOfUsers.ToList();
10

このコードを使ってWebApiConfig.csファイルに解決しました

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

Global.asaxファイルのApplication_Start()メソッドにこれを追加すると問題が解決します

protected void Application_Start()
{
    GlobalConfiguration.Configuration.Formatters.JsonFormatter.SerializerSettings
        .ReferenceLoopHandling = Newtonsoft.Json.ReferenceLoopHandling.Ignore;
    GlobalConfiguration.Configuration.Formatters
        .Remove(GlobalConfiguration.Configuration.Formatters.XmlFormatter); 
// ...
}

方法2:[推奨しません]
EntityFrameworkを使用している場合は、DbContextクラスのコンストラクタでプロキシを無効にできます。注:モデルを更新すると、このコードは削除されます。

public class MyDbContext : DbContext
{
  public MyDbContext()
  {
    this.Configuration.ProxyCreationEnabled = false;
  }
}
6
Er Suman G

同じエラーを生成するこのシナリオもあります:

戻りがWeb APIメソッドへのList<dynamic>である場合

例:

public HttpResponseMessage Get()
{
    var item = new List<dynamic> { new TestClass { Name = "Ale", Age = 30 } };

    return Request.CreateResponse(HttpStatusCode.OK, item);
}

public class TestClass
{
    public string Name { get; set; }
    public int Age { get; set; }
}

したがって、このシナリオでは、戻りクラス(すべてのクラス)で[KnownTypeAttribute]を次のように使用します。

[KnownTypeAttribute(typeof(TestClass))]
public class TestClass
{
    public string Name { get; set; }
    public int Age { get; set; }
}

これは私のために働きます!

6
Alex

私のお気に入り:App_Start/WebApiConfig.csに以下のコードを追加するだけです。これはデフォルトでXMLの代わりにjsonを返し、またあなたが持っていたエラーを防ぎます。 XmlFormatterなどを削除するためにGlobal.asaxを編集する必要はありません。

'ObjectContent`1'タイプは、コンテンツタイプ 'application/xmlのレスポンスボディをシリアル化できませんでした。 charset = utf-8

config.Formatters.JsonFormatter.SupportedMediaTypes.Add(new MediaTypeHeaderValue("text/html"));
4
Ogglas

次の名前空間を使用してください。

using System.Web.OData;

の代わりに :

using System.Web.Http.OData;

それは私のために働いた

2
Harish K

私のために働いた解決策:

  1. シリアル化するクラスごとに[DataContract]を使用し、各プロパティに[DataMember]属性を使用します。これはJsonの結果を取得するのに十分です(たとえば、fiddlerから)。

  2. Xmlのシリアル化を取得するには、Global.asaxに次のコードを書き込みます。

    var xml = GlobalConfiguration.Configuration.Formatters.XmlFormatter; xml.UseXmlSerializer = true;

  3. この記事を読んで、それは私がシリアル化を理解するのに役立ちました: https://www.asp.net/web-api/overview/formats-and-model-binding/json-and-xml-serialization
2

自動マッパーを使用...

public IEnumerable<User> GetAll()
    {
        using (Database db = new Database())
        {
            var users = AutoMapper.Mapper.DynamicMap<List<User>>(db.Users);
            return users;
        }
    }
2
Proximo

App_Startフォルダーで利用可能なWebApiConfig.cs内でSerializer Formatterを定義する必要があります。

Config.Formatters.Remove(config.Formatters.XmlFormatter);の追加; // JSON形式でデータを提供します

Config.Formatters.Remove(config.Formatters.JsonFormatter)の追加; //データをXML形式で提供します

1
Yogesh Dangre

Jensendpの答えに追加するには:

エンティティをユーザーが作成したモデルに渡し、そのエンティティの値を使用して、新しく作成したモデルに値を設定します。例えば:

public class UserInformation {
   public string Name { get; set; }
   public int Age { get; set; }

   public UserInformation(UserEntity user) {
      this.Name = user.name;
      this.Age = user.age;
   }
}

その後、戻り型を次のように変更します。IEnumerable<UserInformation>

1
Greg A

This is my error

基本的に1行追加します

  • entities.Configuration.ProxyCreationEnabled = false;

usersController.csに

using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Web.Http;
using UserDataAccess;

namespace SBPMS.Controllers
{
    public class UsersController : ApiController
    {


        public IEnumerable<User> Get() {
            using (SBPMSystemEntities entities = new SBPMSystemEntities()) {
                entities.Configuration.ProxyCreationEnabled = false;
                return entities.Users.ToList();
            }
        }
        public User Get(int id) {
            using (SBPMSystemEntities entities = new SBPMSystemEntities()) {
                entities.Configuration.ProxyCreationEnabled = false;
                return entities.Users.FirstOrDefault(e => e.user_ID == id);
            }
        }
    }
}

Here is my output:

1

私の場合、私は同様のエラーメッセージがありました:

'ObjectContent`1'タイプは、コンテンツタイプ 'application/xmlのレスポンスボディをシリアル化できませんでした。 charset = utf-8 '.

しかし、私がそれをさらに深く掘り下げると、問題は次のとおりでした。

データコントラクト名 'SomeSubRootType://schemas.datacontract.org/2004/07/WhatEverService'と 'name.SomeSubRootType'を入力することはできません。 DataContractSerializerを使用している場合、または既知のタイプのリストに静的に知られていないタイプを追加する場合(たとえば、KnownTypeAttribute属性を使用する場合やシリアライザに渡される既知のタイプのリストに追加する場合)は、DataContractResolverの使用を検討してください。

KnownTypeを追加して解決した方法。

[KnownType(typeof(SomeSubRootType))]
public partial class SomeRootStructureType

これはこのことに触発されて解決されました 答え

参照: https://msdn.Microsoft.com/ja-jp/library/ms730167(v = vs.100).aspx

私の場合は、データベースの再作成を解決しました。モデルを変更し、Package ManagerコンソールでUpdate-Databaseを起動すると、次のようなエラーが表示されました。

"ALTER TABLEステートメントがFOREIGN KEY制約" FK_dbo.Activities_dbo.Projects_ProjectId "と競合しました。データベース" TrackEmAllContext-20190530144302 "、テーブル" dbo.Projects "、列 'Id'で競合が発生しました。"

0
Manuel Sansone

場合:WebApiConfig.csまたはGlobal.asax.csにコードを追加してもうまくいかない場合:

.ToList();

.ToList()関数を追加してください。

私はすべての解決策を試してみましたが、以下がうまくいきました。

var allShops = context.shops.Where(s => s.city_id == id)**.ToList()**;
return allShops;

願っています、それは役立ちます。

0
Catalyst

Visual Studio自体では出力をjson形式にする必要があるのに対し、Visual Studioのデフォルト形式は "であるため、Visual Studio 2017または2019ではまったく考えられません。 XmlFormat "(config.Formatters.XmlFormatter)

Visual Studioは、開発者に多くの手間をかけずに、これを自動的に行うべきです。

この問題を解決するには、WebApiConfig.csファイルに移動して、

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

Register(HttpConfiguration config)メソッドの "config.MapHttpAttributeRoutes();"の後。これにより、プロジェクトはjson出力を生成できます。

0
William Hou

このエラーが発生したもう1つのケースは、データベースクエリでnull値が返されたが、ユーザー/ビューモデルの種類がNULL不可として設定されていた場合です。例えば、私のUserModelフィールドをintからint?に解決しました。

0
marshall

Response-Typeが公開されていない場合も同様です。型を生成するためにVisual Studioを使用したときに内部クラスを返しました。

internal class --> public class
0
Vanice

下の行を追加

this.Configuration.ProxyCreationEnabled = false;

ProxyCreationEnabledfalseとして使用する2つの方法.

  1. DBContextコンストラクタ内に追加します

    public ProductEntities() : base("name=ProductEntities")
    {
        this.Configuration.ProxyCreationEnabled = false;
    }
    

または

  1. Getメソッドの内側に行を追加します

    public IEnumerable<Brand_Details> Get()
    {
        using (ProductEntities obj = new ProductEntities())
        {
            this.Configuration.ProxyCreationEnabled = false;
            return obj.Brand_Details.ToList();
        }
    }
    
0
Sudipta Saha

上記のすべての答えは正しいのですが、InnerException> ExceptionMessageを確認してください。

もし "TObjectContextインスタンスが破棄され、接続を必要とする操作に使用できなくなった" "のようなものであれば。これは、EFのデフォルト動作のために問題になる可能性があります。

DbContextコンストラクタにLazyLoadingEnabled = falseを代入するとうまくいくでしょう。

public class MyDbContext : DbContext
{
  public MyDbContext()
  {
    this.Configuration.LazyLoadingEnabled = false;
  }
}

EFのEagerLoadingとLazyLoadingの動作についての詳細な読み方は、これを参照してください MSDN Article

0
Bhramar

クラスに[Serializable]を使用します。

例:

[Serializable]
public class UserModel {
    public string Name {get;set;}
    public string Age {get;set;}
}

それは私のために働いた!

0
Msxmania