asp.net-coreblazorasp.net-identityroles.net-8.0

How to actually implement Roles in Blazor WebApp and Identity?


So, here's the thing: If you create a Blazor WebApp (.Net8) with individual accounts enabled, it will give you a working solution. For development, I'm using Sqlite. Here's what that looks like (in an otherwise completely functional app):

builder.Services.AddDbContext<ApplicationDbContext>(options =>
    options.UseSqlite("Data Source=Application.db"));
builder.Services.AddDatabaseDeveloperPageExceptionFilter();

builder.Services.AddIdentityCore<ApplicationUser>(options => options.SignIn.RequireConfirmedAccount = true)
    .AddEntityFrameworkStores<ApplicationDbContext>()
    .AddSignInManager()
    .AddDefaultTokenProviders();

Please take note of the Core in AddIdentityCore. Now, the helptext for this method states that you simply should use AddRole<IdentityRole> if you want roles. An inspection of the database also yields that there are automatically created tables for roles (and claims).

However, when you add the AddRoles<IdentityRole> it then bombs out because the RoleManager service is missing. Easy fix: Just do AddRoleManager<RoleManager<IdentityRole>>

Which in turn bombs out because the RoleStore service is missing. Okay. So I do AddRoleStore<IdentityRole> and everything is peachy, right?

Nope: Unable to resolve service for type 'Microsoft.EntityFrameworkCore.DbContext' while attempting to activate 'Microsoft.AspNetCore.Identity.EntityFrameworkCore.RoleStore'

Which is weird because every other service finds the DbContext just fine. So, where do I go from here?

Oh, and using other things like AddIdentity lets the app bomb out at other locations. I'm a bit irritated because all the documentation available makes no mention of AddIdentityCore and also makes no mention of the necessity to add the manager and the store, instead an AddRole suffices in those examples.


Solution

  • By inspecting the definition of Microsoft.AspNetCore.Identity.EntityFrameworkCore.RoleStore I found that it has several overloads, one of which takes a DbContext.

    For some reason the default project insists (for me) on adding everything (i.e. Roles, RoleManager and RoleStore) and throws an exception if I leave one of the three out. So the whole definition has to look like this for me:

    builder.Services.AddIdentityCore<ApplicationUser>(options => options.SignIn.RequireConfirmedAccount = true)
        .AddEntityFrameworkStores<ApplicationDbContext>()
        .AddSignInManager()
        .AddRoles<IdentityRole>()
        .AddRoleManager<RoleManager<IdentityRole>>()
        .AddRoleStore<RoleStore<IdentityRole, ApplicationDbContext>>()
        .AddDefaultTokenProviders();