私は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();
}
}
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.
}
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モデルを返すことができます
そのような単純な!
正しい答えを与えることは一つのやり方ですが、一つの設定でそれを直すことができればやり過ぎです。
Dbcontextコンストラクタで使用するほうが良い
public DbContext() // dbcontext constructor
: base("name=ConnectionStringNameFromWebConfig")
{
this.Configuration.LazyLoadingEnabled = false;
this.Configuration.ProxyCreationEnabled = false;
}
このコードをglobal.asax
の下のApplication_Start
に追加します。
.Ignore
から.Serialize
に更新しました。それはうまくいくはずです。
GlobalConfiguration.Configuration.Formatters.JsonFormatter.SerializerSettings.ReferenceLoopHandling = Newtonsoft.Json.ReferenceLoopHandling.Serialize;
GlobalConfiguration.Configuration.Formatters.Remove(GlobalConfiguration.Configuration.Formatters.XmlFormatter);
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();
}
}
私はこのコードが好きではありません:
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();
このコードを使ってWebApiConfig.csファイルに解決しました
var json = config.Formatters.JsonFormatter;
json.SerializerSettings.PreserveReferencesHandling = Newtonsoft.Json.PreserveReferencesHandling.Objects;
config.Formatters.Remove(config.Formatters.XmlFormatter);
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;
}
}
同じエラーを生成するこのシナリオもあります:
戻りが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; }
}
これは私のために働きます!
私のお気に入り: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"));
次の名前空間を使用してください。
using System.Web.OData;
の代わりに :
using System.Web.Http.OData;
それは私のために働いた
私のために働いた解決策:
シリアル化するクラスごとに[DataContract]を使用し、各プロパティに[DataMember]属性を使用します。これはJsonの結果を取得するのに十分です(たとえば、fiddlerから)。
Xmlのシリアル化を取得するには、Global.asaxに次のコードを書き込みます。
var xml = GlobalConfiguration.Configuration.Formatters.XmlFormatter; xml.UseXmlSerializer = true;
自動マッパーを使用...
public IEnumerable<User> GetAll()
{
using (Database db = new Database())
{
var users = AutoMapper.Mapper.DynamicMap<List<User>>(db.Users);
return users;
}
}
App_Startフォルダーで利用可能なWebApiConfig.cs内でSerializer Formatterを定義する必要があります。
Config.Formatters.Remove(config.Formatters.XmlFormatter);の追加; // JSON形式でデータを提供します
Config.Formatters.Remove(config.Formatters.JsonFormatter)の追加; //データをXML形式で提供します
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行追加します
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);
}
}
}
}
私の場合、私は同様のエラーメッセージがありました:
'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'で競合が発生しました。"
場合:WebApiConfig.csまたはGlobal.asax.csにコードを追加してもうまくいかない場合:
.ToList();
.ToList()関数を追加してください。
私はすべての解決策を試してみましたが、以下がうまくいきました。
var allShops = context.shops.Where(s => s.city_id == id)**.ToList()**;
return allShops;
願っています、それは役立ちます。
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出力を生成できます。
このエラーが発生したもう1つのケースは、データベースクエリでnull値が返されたが、ユーザー/ビューモデルの種類がNULL不可として設定されていた場合です。例えば、私のUserModelフィールドをint
からint?
に解決しました。
Response-Typeが公開されていない場合も同様です。型を生成するためにVisual Studioを使用したときに内部クラスを返しました。
internal class --> public class
下の行を追加
this.Configuration.ProxyCreationEnabled = false;
ProxyCreationEnabled
をfalse
として使用する2つの方法.
DBContext
コンストラクタ内に追加します
public ProductEntities() : base("name=ProductEntities")
{
this.Configuration.ProxyCreationEnabled = false;
}
または
Get
メソッドの内側に行を追加します
public IEnumerable<Brand_Details> Get()
{
using (ProductEntities obj = new ProductEntities())
{
this.Configuration.ProxyCreationEnabled = false;
return obj.Brand_Details.ToList();
}
}
上記のすべての答えは正しいのですが、InnerException> ExceptionMessageを確認してください。
もし "TObjectContextインスタンスが破棄され、接続を必要とする操作に使用できなくなった" "のようなものであれば。これは、EFのデフォルト動作のために問題になる可能性があります。
DbContextコンストラクタにLazyLoadingEnabled = falseを代入するとうまくいくでしょう。
public class MyDbContext : DbContext
{
public MyDbContext()
{
this.Configuration.LazyLoadingEnabled = false;
}
}
EFのEagerLoadingとLazyLoadingの動作についての詳細な読み方は、これを参照してください MSDN Article 。
クラスに[Serializable]を使用します。
例:
[Serializable]
public class UserModel {
public string Name {get;set;}
public string Age {get;set;}
}
それは私のために働いた!