DbContext in ASP.NET Core throws System.ObjectDisposedException

-1

I am saving a Todo model to database using EF Core in ASP.NET Core app. But when I try to print the success message using Console.Writeline it throws System.ObjectDisposedException

Here's full application github code link

Here's ToDo model:

public class Todo
{
    public int Id { get; set; }

    [Required]
    [MaxLength(10)]
    public string Title { get; set; }

    public bool IsCompleted { get; set; } = false;
}

Here's the business logic that throws exception.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using ToDoApp.Models;
using ToDoApp.Data;

namespace ToDoApp
{
    public class ToDoService
    {
        readonly ToDoContext _context;

        public ToDoService(ToDoContext context)
        {
            _context = context;
        }

        public async Task<int> CreateToDo(CreateToDoBindingModel input)
        {
            Todo todo = new()
            {
                Title = input.Title,
                IsCompleted = input.IsCompleted
            };

            _context.Add(todo);
            await _context.SaveChangesAsync();
            Console.WriteLine("Successfully saved todo.");
            return task.Id;
        }
    }
}

Exception Details:

System.ObjectDisposedException
  HResult=0x80131622
  Message=Cannot access a disposed context instance. A common cause of this error is disposing a context instance that was resolved from dependency injection and then later trying to use the same context instance elsewhere in your application. This may occur if you are calling 'Dispose' on the context instance, or wrapping it in a using statement. If you are using dependency injection, you should let the dependency injection container take care of disposing context instances.
Object name: 'ToDoContext'.
  Source=Microsoft.EntityFrameworkCore
  StackTrace:
   at Microsoft.EntityFrameworkCore.DbContext.CheckDisposed()

Why does Console.Writeline throws exception?

Edit: Here's ToDoContext:

    public class ToDoContext: DbContext
    {
        public ToDoContext(DbContextOptions<ToDoContext> options)
        : base(options)
        { }

        public DbSet<Todo> Todos { get; set; }
    }

Here's how it is registered in Startup.cs:

public void ConfigureServices(IServiceCollection services)
        {
            services.AddRazorPages();

            var connectionString = Configuration["ConnectionString"];
            services.AddDbContext<ToDoContext>(options => options.UseNpgsql(connectionString));

            services.AddScoped<ToDoService>();
        }

Here's full application github code link

c#
asp.net-core
entity-framework-core
objectdisposedexception
asked on Stack Overflow Apr 28, 2021 by abcDE • edited Apr 28, 2021 by abcDE

1 Answer

0

Problem is in this part of your code:

 public IActionResult OnPostAsync()
        {
            if (!ModelState.IsValid)
            {
                return Page();
            }
            Task<int> id =  _service.CreateTask(Input);//<--- this line
            return RedirectToPage("Index");
        }

After call createTask that returns a task means not complete yet and you don't wait for it to be completed, When call RedirectToPage current request finished. because your service and dbcontext added to DI with Scope lifetime that means the life of object is during the request and when request finished that object will disposed.

So for solve problem just use this way:

 public async Task<IActionResult> OnPostAsync()
        {
            if (!ModelState.IsValid)
            {
                return Page();
            }
            int id = await _service.CreateTask(Input);
            return RedirectToPage("Index");
        }
answered on Stack Overflow Apr 28, 2021 by Saeed Esmaeelinejad

User contributions licensed under CC BY-SA 3.0