无法序列化Web API中的响应


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类型的代码吗?可能是因为Employee类型无法序列化...
Maggie Ying


Answers:


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

这个答案没有提供使用xml的解决方案,而这正是他的要求。
诚实的

当我从xml切换到json时对我有用。
Sike12

实际上,这个答案是问题的根源。我收到的第一个错误是循环引用错误(试图从MVC控制器返回JSON)。当我切换到API继承的控制器时,我开始出现此错误。当我将以上代码添加到Global.asax时,错误消失了。
马修·皮茨

43

在您的global.asax文件中的Application_start()方法中,添加以下行:

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

希望对您有所帮助!


3
什么是application_start,在哪里可以找到?而这条线到底应该放在哪里?
Ciaran Gallagher

4
抱歉,这句话是什么意思?
布莱斯

5
行已添加到Global.asax的中Application_Start,但没有更改。
cheesus

8
这仍然对我不起作用。但是,我在此答案的后面添加了另一行,它起作用了:GlobalConfiguration.Configuration.Formatters.Remove(GlobalConfiguration.Configuration.Formatters.XmlFormatter); 我在下面创建了一个更完整的答案
Zane

2
不应该接受此答案,因为它确实删除了XmlSerializer,而不是解决了XmlSerializer的循环引用问题。
Believe2014 2014年

29

我遇到了同样的问题。我解决了。我将默认构造函数放入DTO类。

例如:

public class User
{
    public User()
    {
    }
}

希望它与您合作!


感谢您的建议,这对xml响应有所帮助,但是有人知道为什么它需要默认构造函数吗?我们已经有了数据……
Ilya Chernomordik

我认为当从响应序列化一个对象时,首先调用构造函数以创建对象实例,然后使用set方法将数据设置为对象实例。那是我的猜测。
taynguyen 2015年

实际上,这应该是选择的答案,因为它不会对所需的返回类型进行任何假设。这将适用于XML和JSON。感谢您发布此信息。
艾伦·安德伍德

22

把它放在构造函数中。希望这能解决问题:

    public MyController()
    {

        db.Configuration.ProxyCreationEnabled = false;
    }

优秀的解决方案。我需要将其放入构造函数中,并且它可以正常工作。
InsParbo

与GlobalConfiguration设置结合使用时,这对我有用。但是为什么这样做呢?关于如何解决此问题的任何解释吗?到底是什么问题?
Ciaran Gallagher

要了解什么实体代理是:msdn.microsoft.com/en-us/library/jj592886(v=vs.113).aspx 要了解什么是ProxyCreationEnabled:stackoverflow.com/questions/7111109/...
Sadjad Khazaie

16

我找到了两种解决方案。第一个也是最容易实现的方法是将任何IEnumerables,ICollections更改为List类型。WebAPI可以序列化该对象,但是不能序列化接口类型。

public class Store
{

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

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

另一个选择是不使用本机JSON序列化程序,并在WebApi Config的Register方法中运行此替代:

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

1
在更改为List的情况下,为我工作时,添加无参数的构造函数也对我
有用

8

解决方法很简单。

LINQ查询后,添加.ToList()(或ToDictionary(如果需要))。

它比数据的延迟加载更渴望加载


1
将动作返回类型更改为IENumerable并添加.TiList()到返回中对我有用。
里卡多·索扎

5

**从客户端从请求Web api / wcf / ...进行调用时会发生此错误,但副作用是,您将需要通过include关键字包含依赖关系。**

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

4

如果您使用的是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模型



3

如果您将Web API与Entity Framework一起使用,则可能无法通过Json在Web API中序列化响应的解决方案

基本上,您需要创建一个与每个EF模型相对应的模型,这消除了类之间的依赖关系并允许轻松进行序列化。

代码:(摘自引用链接)

创建一个用户模型

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格式化程序。


您好,Web API将响应序列化为XML和JSON,如果您添加标头Content-Type:application / json,则响应为JSON,则需要定义此标头,在浏览器中始终可以将其视为XML格式
RoberthSolís

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无法序列化的有关User的数据,我创建了一个userModel,并且在我的API中,我从数据库中返回了userModel而不是User。

在User和UserModel之间转换或关联数据的逻辑必须在API中。

无法使用Json序列化Web API中的响应


0

这是我从odata Web API调用中得到的特定错误:

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

我终于想通了,我的DbContext类有一个格式不正确的表名在onModelCreating被分配..所以SqlClient中病危寻找一个表,在我的数据库是不存在的

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.