我最近在使用Web API项目时遇到了一个(希望)小问题,该项目涉及返回对象图,以便它们可以作为JSON读取。
任务对象示例 (通过EF生成) :
//A Task Object (Parent) can consist of many Activities (Child Objects)
public partial class Task
{
public Task()
{
this.Activities = new HashSet<Activity>();
}
public int TaskId { get; set; }
public string TaskSummary { get; set; }
public string TaskDetail { get; set; }
public virtual ICollection<Activity> Activities { get; set; }
}
在我的ApiController中,我被要求一个特定的任务(通过Id)以及所有相关的活动,通过:
单一任务请求示例
//Simple example of pulling an object along with the associated activities.
return repository.Single(t => t.Id == id).Include("Activities");
一切似乎都运行正常 - 但是当我尝试导航到URL来访问它时,例如/api/tasks/1
,该方法按原样执行,但没有返回任何对象(只是一个简单的找不到页)。
如果我请求一个不包含任何活动的任务 - 一切都按预期工作,并返回Activities : []
的正确JSON对象。
我确信有很多方法可以解决这个问题 - 我只是想我会对人们认为最好的处理方法有所了解。
考虑的方法(到目前为止):
使用替代的JSON Parser(例如Newtonsoft.JSON)修复了这个问题,但在返回数据中附加了$ id和$ refs,这可能会让解析Knockout变得困难我相信。
使用投影和利用匿名类型返回数据。 (到目前为止未经测试)
完全删除Include,只需通过其他请求访问子数据。
非常感谢任何和所有建议。
答案 0 :(得分:3)
我最近遇到了与EF类型和Web API类似的问题。根据生成的EF模型的设置方式,导航属性可能会导致循环依赖。因此,如果您生成的Activity类具有Task引用,则序列化程序将尝试遍历对象图并在一个令人讨厌的循环中抛出。
一种解决方案是创建一个简单的视图模型以使序列化器工作
public class TaskViewModel {
public TaskViewModel ()
{
this.Activities = new List<ActivityViewModel>();
}
public int TaskId { get; set; }
public string TaskSummary { get; set; }
public string TaskDetail { get; set; }
public virtual IList<ActivityViewModel> Activities { get; set; }
}
public class ActivityViewModel{
public ActivityViewModel()
{
}
//Activity stuff goes here
//No reference to Tasks here!!
}
根据您正在做的事情,您甚至可以创建比这更平坦的模型,但删除任务参考将有助于序列化。这可能就是为什么它在活动为空时起作用