Reputation: 119
public JsonResult JTask(int id)
{
using (TestDb db = new TestDb())
{
var a = db.ToDos.Where(todo => todo.UserId == id);
return Json(a, JsonRequestBehavior.AllowGet);
}
}
I have a problem with returning JsonResult
When I run this code code I get the error
"The operation cannot be completed because the
DbContext
has been disposed."
I tried adding .ToList()
at the end of the line 3, as was suggested, but then I got the error
"A circular reference was detected while serializing an object of type System.Data.Entity.DynamicProxies."
Upvotes: 2
Views: 1045
Reputation: 4561
It's not very obvious, but the built-in Json
method only does the serialization after the JTask
method has finished executing. By that time, of course, the context has been disposed, resulting in the original error you are describing.
If you have an ICollection<TodoItem>
property inside your Todo
class, each of those will have a ToDo
property which is a reference back to the parent. And each of those ToDo
properties will also have ICollection<TodoItem>
children, which has a reference back to the parent again, and so on and so forth. This can potentially loop for infinity, and when the serializer tries to serialize the object, it gives up with a circular reference error.
One way to solve both of these problems at the same time is by using viewmodels. A viewmodel is an intermediate class that holds only a subset of the properties that a model class has. The typical flow is for the model class to get converted to a viewmodel first, then it would be the viewmodel that gets serialized as json:
var viewModels = new List<TodoViewModel>();
using (TestDb db = new TestDb())
{
var todoModels = db.ToDos.Where(todo => todo.UserId == id).ToList();
foreach (var model in todoModels)
{
var todoViewModel = new TodoViewModel
{
// Populate viewmodel properties here
Text = model.Text
};
viewModels.Add(todoViewModel);
}
}
return Json(viewModels, JsonRequestBehavior.AllowGet);
I wrote a blog post about the advantages of using viewmodels. You can check it out here if you're interested: Why Use ViewModels
Upvotes: 2
Reputation: 2442
var a = db.ToDos.Where(todo => todo.UserId == id).ToList();
Upvotes: 0
Reputation: 37281
Because Linq is Lazy by the time the JSON
tries to get the data out of a
(and only then actually goes to db
) the db
has already been disposed - when leaving the scope of the using
public JsonResult JTask(int id)
{
using (TestDb db = new TestDb())
{
var a = db.ToDos.Where(todo => todo.UserId == id).ToList();
return Json(a, JsonRequestBehavior.AllowGet);
}
}
Upvotes: 1