C# JSON响应不包括所有项
出于某种原因,每个数组中只有第一项作为JSON返回,有什么线索吗 以下是我在调试期间看到的内容,正如您所知,我在“类别”中有两项,在“任务”中有两项: Postman JSON结果(它应该返回所有项目,不是吗?) 以下是我的“Category.cs”,仅供参考:C# JSON响应不包括所有项,c#,.net,json,api,asp.net-core,C#,.net,Json,Api,Asp.net Core,出于某种原因,每个数组中只有第一项作为JSON返回,有什么线索吗 以下是我在调试期间看到的内容,正如您所知,我在“类别”中有两项,在“任务”中有两项: Postman JSON结果(它应该返回所有项目,不是吗?) 以下是我的“Category.cs”,仅供参考: public class Category { public int CategoryId { get; set; } public string Name { get; set; } public Date
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; }
}
我的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();
}
public IEnumerable GetAllForUser(字符串名称)
{
返回_ctx.Categories
.Where(c=>c.ApplicationUser.UserName==name)
.包括(c=>c.任务)
.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" }
}
});
类别。添加(新类别)
{
Name=“第1类”,
任务=新列表
{
新任务{Name=“Task 1”},
新任务{Name=“Task 2”}
}
});
类别。添加(新类别)
{
Name=“第2类”,
任务=新列表
{
新任务{Name=“Task 3”},
新任务{Name=“Task 4”}
}
});
正如Kiran指出的,您的模型中有循环引用,这导致了异常。错误地使请求看起来是用部分数据完成的。(循环引用为类别->任务->任务->类别)
实际发生的是在响应的JSON序列化进行到一半时出现了一个未处理的异常。ASP.NET Core没有中止连接(应该如此),而是发回在错误发生之前序列化的所有内容
您可以定义不包含从任务
返回到类别
的引用的DTO类,也可以返回匿名类型:
[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之类的工具为您进行映射是有意义的。Nate的回答很完美,他给出了很好的建议,指出我需要为我的场景找到很好的解决方案。我已经决定分享它,以防有人会遇到类似的问题。作为提醒,这是ASP.NET核心模型第一个使用Api的MVC项目。我已经使用AutoMapper将我的模型第一个类映射到相应的视图模型 以下是我的第一节课:
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; }
}
公共类类别
{
公共类别()
{
Tasks=newhashset();
}
public int CategoryId{get;set;}
公共字符串名称{get;set;}
公共日期时间时间戳{get;set;}
公共字符串用户名{get;set;}
公共应用程序用户应用程序用户{get;set;}
公共虚拟ICollection任务{get;set;}
}
公开课任务
{
public int TaskId{get;set;}
公共字符串名称{get;set;}
公共日期时间时间戳{get;set;}
public int CategoryId{get;set;}
公共虚拟类别{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; }
}
public类CategoryViewModel
{
public int CategoryId{get;set;}
公共字符串名称{get;set;}
公共日期时间时间戳{get;set;}
公共IEnumerable任务{get;set;}
}
公共类任务视图模型
{
public int TaskId{get;set;}
公共字符串名称{get;set;}
公共日期时间时间戳{get;set;}
}
“setup.cs”文件中的自动映射设置:
Mapper.Initialize(config =>
{
config.CreateMap<Category, CategoryViewModel>().ReverseMap();
config.CreateMap<Task, TaskViewModel>().ReverseMap();
});
Mapper.Initialize(配置=>
{
config.CreateMap().ReverseMap();
config.CreateMap().ReverseMap();
});
最后是我的完整Api方法:
[HttpGet]
public JsonResult Get()
{
var result = Mapper.Map<IEnumerable<CategoryViewModel>>(_repo.GetAllForUser("lucas@test.com"));
return Json(result);
}
[HttpGet]
publicjsonresult Get()
{
var result=Mapper.Map(_repo.GetAllForUser(“lucas@test.com"));
返回Json(结果);
}
你能分享一下你的任务
模型的样子吗?通过添加更多相关的代码来提供更相关的代码编辑问题code@mic4ael:没有Json类,它是来自controller的Json方法,是状态代码为的新JsonObjectResult的快捷方式。您是否在Windows上运行应用程序?根据您的模型,您似乎有循环引用(任务引用类别,反之亦然),这会导致Json.net引发异常:…请尝试以下操作:启用日志记录,并查看是否有任何异常被记录…还可以尝试非IIS场景(示例:直接在控制台中执行dotnet运行
并启用控制台日志记录)很好的解释,谢谢。事实上,这是循环引用,一旦我从我的任务类中删除了Category变量,它就如预期的那样工作了。对我来说奇怪的是,这就是EF建议连接模型第一个类的方式。在执行查询时,也很容易在类之间导航。那么实际的建议是什么呢n、 我应该在创建模型第一类时阻止循环引用,或者我应该从Api返回一个匿名类型,就像上面指定的那样。thanks@lucas直接返回实体模型作为响应通常不是一个好主意,因为它们通常有您不想要或不需要用户看到的东西(包括循环引用)。我认为最好的解决方案是拥有另一组可以映射到的模型(DTO或“响应模型”)。
[HttpGet]
public JsonResult Get()
{
var result = Mapper.Map<IEnumerable<CategoryViewModel>>(_repo.GetAllForUser("lucas@test.com"));
return Json(result);
}