Bmelca Bmelca - 2 months ago 23
ASP.NET (C#) Question

ASP.NET Core 2 - Identity - DI errors with custom Roles

I got this code in my Startup.cs:

services.AddDbContext<ApplicationDbContext>(options =>
options.UseSqlServer(Configuration.GetConnectionString("DefaultConnection")));

services.AddIdentity<ApplicationUser, ApplicationRole>()
.AddEntityFrameworkStores<ApplicationDbContext>()
.AddDefaultTokenProviders();


In that same file, I also replaced the
service.UseIdentity()
with
app.UseAuthentication();
as recommended by MS in the new version of ASP Core 2.

My Db Context:

public class ApplicationDbContext : IdentityDbContext<ApplicationUser, ApplicationRole, string>
{
public ApplicationDbContext(DbContextOptions<ApplicationDbContext> options)
: base(options)
{
}

protected override void OnModelCreating(ModelBuilder builder)
{
base.OnModelCreating(builder);
// Customize the ASP.NET Identity model and override the defaults if needed.
// For example, you can rename the ASP.NET Identity table names and more.
// Add your customizations after calling base.OnModelCreating(builder);
}


//public DbSet<ApplicationUser> ApplicationUser { get; set; }

//public DbSet<ApplicationRole> ApplicationRole { get; set; }
}


And my custom Role class:

public class ApplicationRole : IdentityRole
{
public ApplicationRole() : base() { }

public ApplicationRole(string roleName) : base(roleName) { }

public bool IsDefault { get; set; }
}


When running the application, I got a SeedDatabase helper method that runs:

var roleManager = serviceProvider.GetService<RoleManager<ApplicationRole>>();


This was all working fine, but since updating VS 2017 to the lastest version and installing .NET Core 2.0, this last line of code now throws the following exception:

System.AggregateException occurred
HResult=0x80131500
Message=One or more errors occurred. (Cannot resolve scoped service 'Microsoft.AspNetCore.Identity.RoleManager`1[CspLicensingPortal.Models.ApplicationRole]' from root provider.)
Source=<Cannot evaluate the exception source>
StackTrace:
at System.Threading.Tasks.Task.ThrowIfExceptional(Boolean includeTaskCanceledExceptions)
at System.Threading.Tasks.Task.Wait(Int32 millisecondsTimeout, CancellationToken cancellationToken)
at System.Threading.Tasks.Task.Wait()
at CspLicensingPortal.Startup.Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory) in D:\gsandorx\Documents\Visual Studio 2017\Projects\CspLicensingPortal\CspLicensingPortal\Startup.cs:line 275

Inner Exception 1:
InvalidOperationException: Cannot resolve scoped service 'Microsoft.AspNetCore.Identity.RoleManager`1[MyApplication.Models.ApplicationRole]' from root provider.


I'm not sure why the DI service manager is no longer able to find my ApplicationRole class. I have checked and all my references are using this class and not the default IdentityRole.

Any ideas?

Answer Source

You have to create the IServiceScope on your own.

To do this you have to replace

var roleManager = serviceProvider.GetService<RoleManager<ApplicationRole>>();

with

IServiceScopeFactory scopeFactory = app.ApplicationServices.GetRequiredService<IServiceScopeFactory>();

using (IServiceScope scope = scopeFactory.CreateScope()) {
    RoleManager<IdentityRole> roleManager = scope.ServiceProvider.GetRequiredService<RoleManager<IdentityRole>>();

    // Seed database code goes here
}