Reputation: 10115
I'm trying to create an ASP.NET web service that exposes a list of students and courses with the Entity Framework. Each Course is composed of multiple Students:
public class Student
{
public int Id { get; set; }
public string Name { get; set; }
}
public class Course
{
public int Id { get; set; }
public string Title { get; set; }
public ICollection<Student> Students { get; set; }
}
I am seeding the models like so:
protected override void Seed(StudentsContext context)
{
var students = new List<Student>
{
new Student { Id = 1, Name = "stu1" },
new Student { Id = 2, Name = "stu2" },
new Student { Id = 3, Name = "stu3" },
};
students.ForEach(s => context.Students.Add(s));
context.SaveChanges();
var courses = new List<Course>
{
new Course { Id = 1, Title = "course1",
Students = new List<Student>() { students[0], students[1] } },
new Course { Id = 2, Title = "course2",
Students = new List<Student>() { students[0] } },
new Course { Id = 3, Title = "course3" },
};
courses.ForEach(c => context.Courses.Add(c));
context.SaveChanges();
}
Visual Studio generated an ApiController
for the Course
with a GetCourses()
method to get all the courses:
// GET api/Course
public IEnumerable<Course> GetCourses()
{
return db.Courses.AsEnumerable();
}
However, when I use the web service to get the list of courses, it returns back JSON with courses that have students set to null:
[{"Id":1,"Title":"course1","Students":null},
{"Id":2,"Title":"course2","Students":null},
{"Id":3,"Title":"course3","Students":null}]
How could I get the web service to include the list of students that are assigned to each course? Thanks in advance.
UPDATE
Slauma's fix of changing GetCourses
to
public IEnumerable<Course> GetCourses()
{
return db.Courses.Include(c => c.Students).AsEnumerable();
}
partially worked. martin_costello's second solution had a similar effect. Something else I needed to do was to fix my Student class to clearly indicate the many-to-many relationship:
public class Student
{
public int Id { get; set; }
public string Name { get; set; }
public ICollection<Course> CoursesAttending { get; set; }
}
public class Course
{
public int Id { get; set; }
public string Title { get; set; }
public ICollection<Student> Students { get; set; }
}
Upvotes: 0
Views: 2975
Reputation: 35
I had same problem and this way resolved for me. Add below codes in WebApiCongif.cs file :
C#
var json = config.Formatters.JsonFormatter;
json.SerializerSettings.PreserveReferencesHandling = Newtonsoft.Json.PreserveReferencesHandling.Objects;
config.Formatters.Remove(config.Formatters.XmlFormatter);
Upvotes: 0
Reputation: 609
I had the same problem and it was solved by adding virtual
modifier to model property
public virtual List<Service> Services { get; set; }
Upvotes: 0
Reputation: 10843
I think the EntityFramework features for lazy loading may not be working because your collection property is not virtual
. Also, you should call ToList()
instead of AsEnumerable()
so that the query materializes the objects from the database and executes the query before the method returns.
Otherwise the database context may be disposed and mean that the context (and database connection) no longer exist to do the look-up for the lazy loading to initialize the Students collection.
The AsEnumerable()
call is effectively a no-op that is creating a query-plan to do an operation later when the results are actually needed (e.g. in a foreach
loop). An ICollection<T>
is already an IEnumerable<T>
, so the cast would be unneccessary anyway.
The problem is that you aren't actually executing the query inside the GetCourses()
method.
Try change the code to:
// GET api/Course
public IEnumerable<Course> GetCourses()
{
return db.Courses.ToList();
}
But you may also need the Include()
call as suggested in the other answer, in which case:
// GET api/Course
public IEnumerable<Course> GetCourses()
{
return db.Courses.Include((p) => p.Students).ToList();
}
Upvotes: 2
Reputation: 177133
How could I get the web service to include the list of students that are assigned to each course?
You include by using Include
:
public IEnumerable<Course> GetCourses()
{
return db.Courses.Include(c => c.Students).AsEnumerable();
}
Upvotes: 5