Rion Williams
Rion Williams

Reputation: 76557

Dealing with Object Graphs - Web API

I recently encountered a (hopefully) small issue when toying around with a Web API project that involves returning object graphs so that they can be read as JSON.

Example of Task Object (generated through 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; }
}

within my ApiController, I am requested a specific Task (by Id) along with all of it's associated Activities, via:

Example of Single Task Request

//Simple example of pulling an object along with the associated activities.
return repository.Single(t => t.Id == id).Include("Activities");  

Everything appears to be working fine - however when I attempt to navigate to a URL to access this, such as /api/tasks/1, the method executes as it should, but no object is returned (just a simple cannot find that page).

If I request an Task that contains no activities - everything works as expected and it returns the proper JSON object with Activities : [].

I'm sure there are many way to tackle this issue - I just thought I would get some insight as to what people consider the best method of handling this.

Considered Methods (so far):

Any and all suggestions would be greatly appreciated.

Upvotes: 0

Views: 1168

Answers (1)

cecilphillip
cecilphillip

Reputation: 11596

I had a similar issue with EF types and Web API recently. Depending on how your generated EF models are setup, the navigation properties may result in circular dependencies. So if your generated Activity class has a Task reference the serializer will try to walk the object graph and get thrown in a little nasty cycle.

One solution would be to create a simple view model to get the serializer working

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

Depending on what you're doing, you may even be able to create a flatter model than this but removing the Task reference will help the serialization. That's probably why it worked when Activities was empty

Upvotes: 3

Related Questions