.net核心:不完整的JSON响应

时间:2017-11-21 18:11:15

标签: c# asp.net-core .net-core asp.net-core-mvc

我正在尝试构建简单的API用于培训,在我的数据库中我获得了用户(名字,姓氏,电子邮件密码,list<sports>)和体育(名称,用户ID)。 一切都没关系,当我想要获得我的用户时,我得到了一个填充了体育的对象。但是JSON响应是不完整的,它在中间被“切断”。

[{"firstName":"Nicolas","lastName":"Bouhours","email":"n.bouh@test.com","password":"nico@hotmail.fr","sports":[{"name":"Trail","userId":1

这是我的控制者:

// GET: api/Users
[HttpGet]
public IEnumerable<User> GetUsers()
{
    var users = _context.Users.Include(u => u.Sports).ToList();
    return users;
}

我的模特:

public class Sport : BaseEntity
{
    public string Name { get; set; }

    public int UserId { get; set; }
    public User User { get; set; }
}

public class User : BaseEntity
{
    public String FirstName { get; set; }
    public String LastName { get; set; }
    public String Email { get; set; }
    public String Password { get; set; }

    public List<Sport> Sports { get; set; }
}

public class SportAppContext : DbContext
{
    public SportAppContext(DbContextOptions<SportAppContext> options) : base(options)
    { }

    public DbSet<User> Users { get; set; }
    public DbSet<Sport> Sports { get; set; }
}

我真的不明白发生了什么,如果你有任何想法

6 个答案:

答案 0 :(得分:7)

我现在遇到同样的问题。您还可以更改JSON序列化/配置设置以忽略自引用循环,如接受的答案for this question

中所示
public void ConfigureServices(IServiceCollection services)
{
    services.AddMvc().AddJsonOptions(options => {
        options.SerializerSettings.ReferenceLoopHandling = ReferenceLoopHandling.Ignore;
    });
}

答案 1 :(得分:6)

我在其中一个项目中遇到过这个问题。这是由自引用循环引起的。

您需要创建一些DTO(数据传输对象),用于生成JSON。

在您的DTO中删除反向关系,以便最终得到类似

的内容
    public class SportDto
    {
        public string Name { get; set; }
    }

    public class UserDto
    {
        public String FirstName { get; set; }
        public String LastName { get; set; }
        public String Email { get; set; }
        public String Password { get; set; }

        public List<SportDto> Sports { get; set; }
    }

然后,您将用户UserSport模型映射到UserDtoSportDto 执行此映射的一个好工具是AutoMapper。您可以阅读文档以了解如何开始。

映射完成后,您将 DTOs 作为JSON发送,而不是模型

答案 2 :(得分:0)

就我而言,这可以通过使用Newtonsoft解决我在核心3上的问题: https://docs.microsoft.com/en-us/aspnet/core/web-api/advanced/formatting?view=aspnetcore-3.0#add-newtonsoftjson-based-json-format-support

  

在ASP.NET Core 3.0之前,默认使用的JSON格式化程序   使用Newtonsoft.Json包实现。在ASP.NET Core 3.0中或   稍后,默认的JSON格式器基于System.Text.Json。   支持基于Newtonsoft.Json的格式化程序和功能   通过安装Microsoft.AspNetCore.Mvc.NewtonsoftJson NuGet   包并在Startup.ConfigureServices中对其进行配置。

    public void ConfigureServices(IServiceCollection services)
{
    services.AddControllers()
        .AddNewtonsoftJson();
}

答案 3 :(得分:0)

在我看来,选择的答案也是正确的,我的JSON响应被JSON响应中的引用循环截断,并设置ReferenceLoopHandling.Ignore确实解决了我的问题。但是,这并不是我认为的最佳解决方案,因为这可以在模型中维护循环引用。更好的解决方案是在模型中使用[JsonIgnore]属性。

模型中的问题在这里:

public class Sport : BaseEntity
{
    public string Name { get; set; }

    public int UserId { get; set; }
    public User User { get; set; }  //This is the cause of your circular reference
}

public class User : BaseEntity
{
    public String FirstName { get; set; }
    public String LastName { get; set; }
    public String Email { get; set; }
    public String Password { get; set; }

    public List<Sport> Sports { get; set; }
}

如您所见,您的“用户”导航属性是该响应被截断的地方。具体来说,它将导致json响应中的每个Sport包含响应中每个Sport条目的所有用户信息。 Newtonsoft不喜欢这样。解决方案是简单地[JsonIngore]导致此循环引用的导航属性。在您的代码中,这将是:

public class Sport : BaseEntity
{
    public string Name { get; set; }

    public int UserId { get; set; }
    [JsonIgnore]
    public User User { get; set; }  //fixed
}

public class User : BaseEntity
{
    public String FirstName { get; set; }
    public String LastName { get; set; }
    public String Email { get; set; }
    public String Password { get; set; }

    public List<Sport> Sports { get; set; }
}

答案 4 :(得分:0)

只需添加另一个可能发生这种情况的方案即可。如果您的DAL返回可查询对象,也会发生这种情况。在我的场景中,我从DAL返回了一个装箱的对象,并且有类似linq查询的内容

 ...
 RootLevelProp1 = "asd",
 RootLevelProp2 = "asd",
 Trades = b.Trades.OrderBy(c => c.Time).Select(c => new
                {
                    c.Direction,
                    c.Price,
                    c.ShareCount,
                    c.Time
                }) //<---- This was being returned as a queryable to the controller 

Trades查询从未执行过,即使其根对象调用了.ToListAsync()。发生的事情是,控制器将返回结果,但仅返回Trades节,并且Json无法正确终止。然后,我意识到在我编写的某些自定义中间件中捕获了一个异常,它抱怨数据读取器已经打开。在不深入调查的情况下,我认为它必须对DI以及它如何处理上下文的生命周期进行某些处理。解决方法是仅在交易中添加ToList。从DAL传递数据是一种丑陋的方式,但这只是一个有趣的项目。

答案 5 :(得分:-1)

面对类似的问题,响应被截断了。问题是尝试格式化日期的吸气剂方法。