使用 Json 在 WebAPI 中序列化响应失败

我正在使用 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;

But it still doesn't work.

My function for return data is this:

public IEnumerable<User> GetAll()
{
using (Database db = new Database())
{
return db.Users.ToList();
}
}
231262 次浏览

When it comes to returning data back to the consumer from Web Api (or any other web service for that matter), I highly recommend not passing back entities that come from a database. It is much more reliable and maintainable to use Models in which you have control of what the data looks like and not the database. That way you don't have to mess around with the formatters so much in the WebApiConfig. You can just create a UserModel that has child Models as properties and get rid of the reference loops in the return objects. That makes the serializer much happier.

另外,如果只是在请求中指定“ Accepts”头,通常不需要删除格式化程序或支持的媒体类型。玩弄这些东西有时会让事情变得更加混乱。

例如:

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

还有一种情况会产生相同的错误:

如果返回的是一个 List<dynamic> to web api 方法

例如:

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

这对我有用!

如果您正在使用 EF,除了在 Global.asax 上添加以下代码之外

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

别忘了进口

using System.Data.Entity;

然后你可以返回自己的 EF 模型

就这么简单!

我不喜欢这个代码:

Foreach (db.Users 中的 var 用户)

作为另一种选择,人们可以这样做,这对我很有效:

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


});


return listOfUsers.ToList();

However, I ended up using Lucas Roselli's solution.

更新: 通过返回匿名对象来简化:

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


return listOfUsers.ToList();

对于詹森德普的回答,我还要补充一点:

我将把实体传递给用户创建的模型,并使用来自该实体的值来设置新创建的模型中的值。例如:

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>

给出正确的答案是一种方式去,但它是一个杀伤力,当你可以修复它的一个配置设置。

最好在 dbcontext 构造函数中使用它

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

ASP.Net Web API 错误: ObjectContent‘1 & # 39; 类型未能序列化内容类型的响应正文; application/xml; charset = utf-8 & # 39;

使用自动绘图器..。

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

我收到这个错误的另一个例子是,我的数据库查询返回了一个空值,但是我的用户/视图模型类型被设置为非空。例如,解决了将 UserModel 字段从 int更改为 int?的问题。

将此代码添加到以下 Application_Start上的 global.asax:

.Ignore更新到 .Serialize。它必须工作。

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

My personal favorite: Just add the code below to App_Start/WebApiConfig.cs. This will return json instead of XML by default and also prevent the error you had. No need to edit Global.asax to remove XmlFormatter etc.

‘ ObjectContent‘1’类型未能序列化内容类型‘ application/xml; charset = utf-8的响应正文

config.Formatters.JsonFormatter.SupportedMediaTypes.Add(new MediaTypeHeaderValue("text/html"));
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();
}
}

使用以下命名空间:

using System.Web.OData;

Instead of :

using System.Web.Http.OData;

It worked for me

对我有效的解决方案是:

  1. 对类使用 [DataContract],对每个属性使用 [DataMember]属性进行序列化。这足以得到 Json 的结果(对于某人来说)。来自小提琴手)。

  2. 要获得 xml 序列化,在 Global.asax中编写以下代码:

    Var xml = GlobalConfiguration.Configuration.Formats.XmlFormatter; UseXmlSerializer = true;

  3. 阅读这篇文章,它帮助我理解了序列化: https://www.asp.net/web-api/overview/formats-and-model-binding/json-and-xml-serialization

当 Response-Type 不是公共的时候也会发生这种情况! 在使用 VisualStudio 生成类型时,我返回了一个内部类。

internal class --> public class

虽然以上所有的答案都是正确的,但你可能需要检查一下 InnerException > ExceptionMessage

如果它像这样说“ TObjectContext 实例已被释放,不能再用于需要连接的操作。”。这可能是一个问题,因为 EF 的默认行为。

通过在 DbContext 构造函数中指定 LazyLoadingEnable = false,就可以达到这个目的。

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

有关 EF 的 EagerLoadingandLazyLoadingactivity 行为的更详细的阅读,请参阅此 MSDN 文章

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

在我的例子中,我得到了类似的错误消息:

The 'ObjectContent`1' type failed to serialize the response body for content type 'application/xml; charset=utf-8'.

但是当我深入挖掘的时候,问题是:

键入“ name. some SubRootType” 数据契约名称 “有些次根类型:// schemas.datacontract.org/2004/07/whateverservice” 考虑使用 DataContractResolver 使用 DataContractSerializer 或添加任何静态不知道的类型 已知类型的列表-例如,通过使用 KnownTypeAttribute 属性,或者将它们添加到传递给 序列化器。

The way I solved by adding KnownType.

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

这个问题的解决灵感来自于这个 回答

参考资料: https://msdn.microsoft.com/en-us/library/ms730167(v=vs.100).aspx

我使用 WebApiConfig.cs 文件的代码解决了这个问题

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

This is my error

我基本上加了一行

  • 实体配置

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:

Visual Studio 2017或2019在这一点上完全没有考虑周到,因为 Visual Studio 本身要求输出为 Json格式,而 Visual Studio 的默认格式是“ “ XmlFormat”(config. Formats.XmlFormatter)”。

VisualStudio 应该自动完成这项工作,而不是给开发人员带来这么多麻烦。

要更正此问题,请转到 WebApiConfig.cs文件,并添加

Var json = config. Formatters. JsonFormatter; 保留参考处理 = 牛顿软件 设置格式化程序。删除(设置格式化程序。 XmlFormatter) ;

after "MapHttpAttributeRoutes () ;" in the Register(HttpConfiguration config) method. This would allow your project to produce json output.

在我的案例中,我解决了重建数据库的问题。 我在一个模型中做了一些修改,并在 Package Manager 控制台中启动了 Update-Database,我得到了以下错误:

”ALTERTABLE 语句与 FOREIGNKEY 约束“ FK _ dbo 冲突。活动 _ dbo。Projects _ ProjectId”。冲突发生在数据库“ TrackEmAllContext-20190530144302”、表“ dbo”中。“项目”,列“ ID”

In case: If adding code to WebApiConfig.cs or Global.asax.cs doesn't work for you:

.ToList();

Add. ToList ()函数。

我尝试了所有的解决方案,但下面的方法对我很有效:

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

希望能有所帮助。

添加下面一行

this.Configuration.ProxyCreationEnabled = false;

使用 ProxyCreationEnabled作为 false的两种方法。

  1. 将其添加到 DBContext构造函数中

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

OR

  1. Add the line inside of Get method

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

在类中使用[ Serializer ] :

例如:

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

我成功了!

您必须在 App _ Start 文件夹中的 WebApiConfig.cs 中定义 Serializer Formatter,如

添加 config.Formats.delete (config.Formats.XmlFormatter) ; //它将为您提供 JSON 格式的数据

添加 config.Formats.delete (config.Formats.JsonFormatter) ; // which will provide you data in XML Format

在我的例子中,当我在导航属性之前删除虚拟关键字时,它被修复了, 我是说参考表。 所以我改变了

public virtual MembershipType MembershipType { get; set; }

致:

public MembershipType MembershipType { get; set; }

只需在 global.asax 中输入以下代码行:

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

进口

using System.Data.Entity;