At the moment I am trying to get Roles configured using the RoleManager<Identity>
, built into .NET Core 2.0, mvc-framework.
However I am getting the following error:
System.ObjectDisposedException
HResult=0x80131622
Message=Cannot access a disposed object. A common cause of this error is
disposing a context 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, or wrapping the
context in a using statement. If you are using dependency injection, you
should let the dependency injection container take care of disposing context
instances. The error occured in line 20 of UserRoleSeed-class.
Is this because of the async-character of the Seed()
method?
My Program.cs:
public class Program
{
public static void Main(string[] args)
{
var host = BuildWebHost(args);
using (var scope = host.Services.CreateScope())
{
var serviceProvider = scope.ServiceProvider;
try
{
var roleManager = serviceProvider.GetRequiredService<RoleManager<IdentityRole>>();
new UserRoleSeed(roleManager).Seed();
}
catch
{
throw new Exception();
}
}
host.Run();
}
public static IWebHost BuildWebHost(string[] args) =>
WebHost.CreateDefaultBuilder(args)
.UseStartup<Startup>()
.Build();
}
My UserRoleSeed.cs:
public class UserRoleSeed
{
private readonly RoleManager<IdentityRole> _roleManager;
public UserRoleSeed(RoleManager<IdentityRole> roleManager)
{
_roleManager = roleManager;
}
public async void Seed()
{
if ((await _roleManager.FindByNameAsync("Berijder")) == null)
{
await _roleManager.CreateAsync(new IdentityRole {Name =
"Berijder"});
}
}
}
This should create a new entry into the dbo.AspNetRoles table of my Context imo, but it doesn't. The problem could be something small, this is the first time I tried using roles in the Mvc-framework.
I tried to use the Startup.cs file at first, calling the Seed()
method in the Configure() method of this file, that didn't work (probably because this is CORE 2.0 and not 1.0).
An async void functions as a fire-and-forget method. The code will continue to run and dispose all objects before the async void is completed. Another way to handle this:
Make it an async Task
and call Wait()
;
public async Task SeedAsync()
{
...
}
call it like so:
// Calling Wait in EFCore is not so much of a problem, since there is not
// really a main blocking thread like UI program's have in .NET framework.
new UserRoleSeed(roleManager).SeedAsync().Wait();
Another solution is to use a task runner:
public static void Main(string[] args)
{
var host = BuildWebHost(args);
Task.Run(() => InitializeAsync(host));
host.Run();
}
private static async Task InitializeAsync(IWebHost host)
{
using (var scope = host.Services.CreateScope())
{
var serviceProvider = scope.ServiceProvider;
try
{
var roleManager = serviceProvider.GetRequiredService<RoleManager<IdentityRole>>();
await new UserRoleSeed(roleManager).SeedAsync();
}
catch
{
// TODO: log the exception
throw;
}
}
}
public static IWebHost BuildWebHost(string[] args) =>
WebHost.CreateDefaultBuilder(args)
.UseStartup<Startup>()
.Build();
User contributions licensed under CC BY-SA 3.0