7

I am trying to write a controller that receives a request from an AJAX call and performs some calls to the database via the DBContext. However, when I place the command var user = await GetCurrentUserAsynch(); in front of any calls to the DBContext, as shown below, I get an ObjectDisposedException (Cannot access a disposed object).

It appears to be the UserManager and the DBContext not playing nicely together, however I can't find much information on the matter.

[HttpPost]        
public async void EditUserMapItemAjax([FromBody]UserMapItemViewModel userMapItemViewModel)
{            
    var user = await GetCurrentUserAsync();
    var mapItem = _db.MapItems.SingleOrDefault(x => x.Id == userMapItemViewModel.MapItemId);   

    ...
}

private Task<ApplicationUser> GetCurrentUserAsync() => _userManager.GetUserAsync(HttpContext.User);
9
  • Which provider are you using? GetUserAsync is just wraps the call around the underlying IUserStore<T> Commented Dec 19, 2016 at 19:39
  • @Tseng I am new to most of the concepts - .net core, entity, and identity, so I apologize if this doesn't answer your question. In my Startup.ConfigServies I have: services.AddIdentity<ApplicationUser, IdentityRole>() and services.AddScoped<UserManager<ApplicationUser>>();. Application user extends IdentityUser. Commented Dec 19, 2016 at 19:52
  • Identity is backed by a database and the provider connects it. See it as database driver. Which database are you using with Identity? MSSQL? Sqlite? Mysql? Postgresql? In UserManager there is no code which calls dispose, it just delegates it to the provider. The SQLServer provider also has no disposing in it, so I suspect you are using some other provider. Also you don't need to register services.AddScoped<UserManager<ApplicationUser>>(); manually, Identity should doing that already, iirc Commented Dec 19, 2016 at 20:15
  • @Tseng thanks for the explanation! I'm using MSSQLLocalDB. Commented Dec 19, 2016 at 20:34
  • 3
    Does changing the method declaration to async Task instead of async void solve it? Commented Dec 19, 2016 at 20:59

1 Answer 1

27

Declare your controller action as async Task, not async void.

With the latter, as soon as your method hits the first await, it returns control to the caller, and because ASP.NET now has no way to track its progress (as it would have when it returns a Task instead), it disposes your controller instance, and (most-likely) along with it any locally-scoped fields.


While you're there, as you're in an async method anyway, you should prefer the async version of the EF call; i.e. await _db.MapItems.SingleOrDefaultAsync()

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.