JSON响应不包含所有项

时间:2016-08-09 15:57:29

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

出于某种原因,只有每个数组的第一项作为JSON返回,任何线索为什么?

以下是我在调试过程中看到的内容,您可以看出,“类别”中有两个项目,“任务”中有两个项目:

enter image description here

Postman JSON结果(它应该返回所有项目,不应该吗?): enter image description here

供参考,这是我的'Category.cs':

public class Category
{
    public int CategoryId { get; set; }
    public string Name { get; set; }
    public DateTime Timestamp { get; set; }
    public string Username { get; set; }

    public ApplicationUser ApplicationUser { get; set; }

    public virtual ICollection<Task> Tasks { get; set; }
}

我的'Task.cs':

public class Task
{
    public int TaskId { get; set; }
    public string Name { get; set; }
    public DateTime Timestamp { get; set; }

    public virtual Category Category { get; set; }
}

和我的Api:

    [HttpGet]
    public JsonResult Get()
    {
        var result = _repo.GetAllForUser("lucas@test.com");

        return Json(result);
    }

和存储库:

    public IEnumerable<Category> GetAllForUser(string name)
    {
        return _ctx.Categories
                    .Where(c => c.ApplicationUser.UserName == name)
                    .Include(c => c.Tasks)
                    .ToList();           
    }

这是我插入数据库的内容,以及我应该从Api中检索的内容:

        categories.Add(new Category
        {
            Name = "cat 1",
            Tasks = new List<Task>
            {
                new Task { Name="task 1" },
                new Task { Name="task 2" }
            }
        });
        categories.Add(new Category
        {
            Name = "cat 2",
            Tasks = new List<Task>
            {
                new Task { Name="task 3" },
                new Task { Name="task 4" }
            }
        });

2 个答案:

答案 0 :(得分:2)

正如Kiran所指出的,你的模型中有循环引用,这会导致异常。 This bug错误地使看起来像,就像请求正在使用部分数据完成一样。 (循环引用是类别 - &gt;任务 - &gt;任务 - &gt;类别)

实际发生的是响应的JSON序列化中途未处理的异常。 ASP.NET Core不会中止连接(应该如此),而是发送所有序列化的内容,直到发生错误。

您可以定义一个DTO类,它不会将Task的引用包含回Category,或者返回匿名类型:

[HttpGet]
public JsonResult Get()
{
    var result = _repo.GetAllForUser("lucas@test.com");

    var response = new {
        categoryId: result.CategoryId,
        name: result.Name,
        timestamp: result.Timestamp,
        username: result.Username,
        tasks: result.Tasks.Select(t => new {
            taskId: t.TaskId,
            name: t.Name,
            timestamp: t.Timestamp
        })
    };

    return Json(response);
}

如果您经常这样做,那么创建DTO类并使用AutoMapper之类的工具为您进行映射是有意义的。

答案 1 :(得分:1)

Nate的答案是完美的,他回答了一些很好的建议,这些建议指出我为我的场景找到了很好的解决方案。我决定分享它以防有人遇到类似的问题。提醒一下,这是带有Api的ASP.NET Core Model First MVC项目。我已经使用AutoMapper将我的Model First类映射到相应的视图模型。

以下是我的Model First课程:

public class Category
{
    public Category()
    {
        Tasks = new HashSet<Task>();
    }

    public int CategoryId { get; set; }
    public string Name { get; set; }
    public DateTime Timestamp { get; set; }
    public string Username { get; set; }

    public ApplicationUser ApplicationUser { get; set; }

    public virtual ICollection<Task> Tasks { get; set; }
}

public class Task
{
    public int TaskId { get; set; }
    public string Name { get; set; }
    public DateTime Timestamp { get; set; }
    public int CategoryId { get; set; }

    public virtual Category Category { get; set; }
}

对应的视图模型:

public class CategoryViewModel
{
    public int CategoryId { get; set; }
    public string Name { get; set; }
    public DateTime Timestamp { get; set; }

    public IEnumerable<TaskViewModel> Tasks { get; set; }
}

public class TaskViewModel
{
    public int TaskId { get; set; }
    public string Name { get; set; }
    public DateTime Timestamp { get; set; }
}

AutoMapper设置在&#39; Setup.cs&#39;文件:

Mapper.Initialize(config =>
        {
            config.CreateMap<Category, CategoryViewModel>().ReverseMap();
            config.CreateMap<Task, TaskViewModel>().ReverseMap();
        });

最后我的全面工作Api方法:

[HttpGet]
    public JsonResult Get()
    {
        var result = Mapper.Map<IEnumerable<CategoryViewModel>>(_repo.GetAllForUser("lucas@test.com"));

        return Json(result);
    }