0

我最近在玩弄一个涉及返回对象图以便可以将它们读取为 JSON 的 Web API 项目时遇到了一个(希望如此)小问题。

任务对象示例 (通过 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,该方法按应有的方式执行,但没有返回任何对象(只是一个简单的找不到该页面)。

如果我请求一个不包含活动的任务 - 一切都按预期工作,它会返回正确的 JSON 对象Activities : []

我确信有很多方法可以解决这个问题 - 我只是想我会了解人们认为处理这个问题的最佳方法。

考虑的方法(到目前为止):

  • 使用替代的 JSON 解析器(例如 Newtonsoft.JSON)修复了该问题,但在整个返回数据中附加了 $id 和 $refs,我相信这可能会使 Knockout 的解析变得困难。

  • 使用投影并利用匿名类型返回数据。(目前未测试)

  • 完全删除包含并通过另一个请求简单地访问子数据。

任何和所有的建议将不胜感激。

4

1 回答 1

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

根据您正在做的事情,您甚至可以创建一个比这更扁平的模型,但删除 Task 引用将有助于序列化。这可能就是当活动为空时它起作用的原因

于 2012-06-21T14:17:55.713 回答