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

时间:2014-04-16 02:56:38

标签: c# asp.net json asp.net-web-api

我正在使用ASP.NET MVC 5 Web Api。我想咨询我的所有用户。

我写了api/users,我收到了这个:

  

"' ObjectContent`1'类型无法序列化内容类型的响应主体' application / json;字符集= 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();
    }
}

27 个答案:

答案 0 :(得分:129)

如果您正在使用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模型

这很简单!

答案 1 :(得分:70)

当涉及从Web Api(或任何其他Web服务)将数据返回给使用者时,我强烈建议不要传回来自数据库的实体。使用模型可以更加可靠和可维护,在模型中您可以控制数据的外观,而不是数据库。这样你就不必在WebApiConfig中乱用格式化程序了。您可以创建一个将子模型作为属性的UserModel,并删除返回对象中的引用循环。这使得序列化器更加快乐。

此外,如果您只是在请求中指定“接受”标头,则无需删除格式化程序或支持的媒体类型。玩弄这些东西有时会让事情变得更加混乱。

示例:

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

答案 2 :(得分:48)

如果给出正确的答案是一种方法,但是当你可以通过一个配置设置修复它时,它是一种过度杀伤。

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

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

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

答案 3 :(得分:31)

将此代码添加到global.asax下面的Application_Start

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

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

答案 4 :(得分:11)

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

答案 5 :(得分:10)

我不喜欢这段代码:

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();

答案 6 :(得分:6)

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

如果返回的是[{1}}到web api方法

示例:

List<dynamic>

因此,对于这种情况,请使用返回类中的[KnownTypeAttribute](所有这些),如下所示:

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

这对我有用!

答案 7 :(得分:6)

我使用此代码将其解析为WebApiConfig.cs文件

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

答案 8 :(得分:6)

Global.asax protected void Application_Start() { GlobalConfiguration.Configuration.Formatters.JsonFormatter.SerializerSettings .ReferenceLoopHandling = Newtonsoft.Json.ReferenceLoopHandling.Ignore; GlobalConfiguration.Configuration.Formatters .Remove(GlobalConfiguration.Configuration.Formatters.XmlFormatter); // ... } 文件的public class MyDbContext : DbContext { public MyDbContext() { this.Configuration.ProxyCreationEnabled = false; } } 方法中添加此内容可以解决问题

fontName = 'malgun.ttf'      # One of Korean fonts.
fontSize = 25
imgMode = 'RGBA'
fillColor = (0, 0, 0)
bgColor = (255, 255, 255)
font = ImageFont.truetype(os.path.join(os.environ['WINDIR'], 'fonts', fontName), fontSize)
img = Image.new(imgMode, font.getsize(c), bgColor)
draw = ImageDraw.Draw(img)
draw.text((0, 0), c, fill=fillColor, font=font)

方法2:[不推荐]
如果您正在使用EntityFramework,则可以在DbContext类构造函数中禁用代理。注意:如果您更新模型

,将删除此代码
update

答案 9 :(得分:4)

我个人最喜欢的:只需将以下代码添加到App_Start/WebApiConfig.cs即可。这将默认返回json而不是XML,并且还可以防止出现错误。无需修改Global.asax即可删除XmlFormatter等。

  

'ObjectContent`1'类型无法序列化内容类型'application / xml的响应主体;字符集= UTF-8

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

答案 10 :(得分:2)

使用AutoMapper ...

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

答案 11 :(得分:2)

使用以下命名空间:

using System.Web.OData;

而不是:

using System.Web.Http.OData;

它对我有用

答案 12 :(得分:2)

对我有用的解决方案:

  1. 对每个属性的类和[DataMember]属性使用[DataContract]进行序列化。这足以获得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

答案 13 :(得分:1)

只需在global.asax中添加以下行:

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

导入

using System.Data.Entity;

答案 14 :(得分:1)

This is my error

我基本上添加了一行

  • 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:

答案 15 :(得分:1)

添加到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>

答案 16 :(得分:0)

虽然以上所有这些答案都是正确的,但可能需要检查 InnerException&gt; ExceptionMessage 即可。

如果它说的是“T 他已经处理了ObjectContext实例,并且不能再用于需要连接的操作。”。由于EF的默认行为,这可能是一个问题。

通过在DbContext构造函数中指定 LazyLoadingEnabled = false ,可以解决问题。

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

有关EF的EagerLoading和LazyLoading行为的更详细阅读,请参阅此MSDN Article

答案 17 :(得分:0)

在我的情况下,我有类似的错误消息:

  

&#39; ObjectContent`1&#39;类型无法序列化响应正文   内容类型&#39; application / xml;字符集= UTF-8&#39;

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

  

键入&#39; name.SomeSubRootType&#39;   与数据合同名称   &#39; SomeSubRootType://schemas.datacontract.org/2004/07/WhatEverService'   不是预期的。如果是的话,请考虑使用DataContractResolver   使用DataContractSerializer或添加静态未知的任何类型   已知类型的列表 - 例如,通过使用KnownTypeAttribute   属性或将它们添加到传递给的已知类型列表中   串行器。

我通过添加KnownType来解决这个问题。

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

这是从answer启发而来的。

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

答案 18 :(得分:0)

当Response-Type不公开时,也会发生这种情况! 我返回了一个内部类,因为我使用Visual Studio生成了类型。

internal class --> public class

答案 19 :(得分:0)

我收到此错误的另一种情况是我的数据库查询返回空值但我的用户/视图模型类型设置为不可为空。例如,将我的UserModel字段从int更改为int?已解决。

答案 20 :(得分:0)

Visual Studio 2017或2019对此完全没有考虑,因为Visual Studio本身要求输出为 json 格式,而Visual Studio的默认格式为“ 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输出。

答案 21 :(得分:0)

就我而言,我解决了重新创建数据库的问题。 我对模型进行了一些更改,并在Package Manager控制台中启动Update-Database,出现以下错误:

  

“ ALTER TABLE语句与FOREIGN KEY约束“ FK_dbo.Activities_dbo.Projects_ProjectId”冲突。冲突发生在数据库“ TrackEmAllContext-20190530144302”的表“ dbo.Projects”的“ Id”列中。”

答案 22 :(得分:0)

如果:如果向 WebApiConfig.cs Global.asax.cs 添加代码对您不起作用:

get_qs_list = [model.objects.filter(title__icontains=query) for model in PostType.__subclasses__()] # This contains QuerySet instances now.
for qs in get_qs_list:
    # qs iterator returns QuerySet instance
    for instance in qs:
        # instance iterator is single Model instance from QuerySet collection
        print(instance.title)

添加.ToList()函数。

我尝试了所有解决方案,但以下方法对我有用:

.ToList();

我希望这会有所帮助。

答案 23 :(得分:0)

添加以下行


IF (SELECT * FROM `NodesInfo` WHERE `Nodename` = '".$row2['nodeName']."') IS NOT NULL 

    THEN
        UPDATE `NodesInfo` SET `Time Stamp`= '".$row2['timeStamp']."',`Status`= '$status' WHERE `Nodename` = '".$row2['nodeName']."'

ELSE 

    INSERT INTO `NodesInfo`(`Nodename`, `Category`, `Time Stamp`, `Type`, `Status`) VALUES ('".$row2['nodeName']."','NodeMCUMQTTData','".$row2['timeStamp']."','$type','$status') 

END IF  

this.Configuration.ProxyCreationEnabled = false; 用作ProxyCreationEnabled的两种方法。

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

    DBContext

OR

  1. public ProductEntities() : base("name=ProductEntities") { this.Configuration.ProxyCreationEnabled = false; } 方法内添加行

    Get

答案 24 :(得分:0)

将[可序列化]用于课程:

示例:

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

对我有用!

答案 25 :(得分:0)

您将必须在App_Start文件夹中可用的WebApiConfig.cs中定义序列化器格式化程序,例如

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

添加config.Formatters.Remove(config.Formatters.JsonFormatter);     //将为您提供XML格式的数据

答案 26 :(得分:0)

在我的情况下,

该问题在导航属性之前删除虚拟关键字时已得到修复, 我的意思是参考表。 所以我改变了

obj.product.id

收件人:

public virtual MembershipType MembershipType { get; set; }