0

I am trying to initialize roles for my Blazor app. This is my service that should create roles if they don't exist:

using Microsoft.AspNetCore.Identity;

namespace FoodApp.Services
{
    public class RoleInitializerService : IHostedService
    {
        private readonly RoleManager<IdentityRole> _roleManager;

        public RoleInitializerService(RoleManager<IdentityRole> roleManager)
        {
            _roleManager = roleManager;
        }

        public async Task StartAsync(CancellationToken cancellationToken)
        {
            string[] roles = { "Administrator", "User" };

            foreach (var role in roles)
            {
                if (!await _roleManager.RoleExistsAsync(role))
                {
                    await _roleManager.CreateAsync(new IdentityRole(role));
                }
            }
        }

        public Task StopAsync(CancellationToken cancellationToken) => Task.CompletedTask;
    }
}

And this is service registration in program.cs

builder.Services.AddScoped<RoleInitializerService>();

I put a breakpoint inside the StartAsync method of my service, and the method was never executed.

What am I doing wrong? Is the problem laying in lifetime mismatch or what else?

3
  • builder.Services.AddHostedService<RoleInitializerService>(); Commented Jul 2, 2024 at 13:05
  • @GHDevOps InvalidOperationException: Cannot consume scoped service 'Microsoft.AspNetCore.Identity.RoleManager`1[Microsoft.AspNetCore.Identity.IdentityRole]' from singleton 'Microsoft.Extensions.Hosting.IHostedService'. Commented Jul 2, 2024 at 15:19
  • It can't be scoped. Remove the registration and use the AddHostedService middleware only. Commented Jul 2, 2024 at 15:33

1 Answer 1

0

You could try this code:

 using Microsoft.AspNetCore.Identity;

namespace FoodApp.Services
{
    public class RoleInitializer
    {
        private readonly RoleManager<IdentityRole> _roleManager;

        public RoleInitializer(RoleManager<IdentityRole> roleManager)
        {
            _roleManager = roleManager;
        }

        public async Task InitializeRolesAsync()
        {
            string[] roles = { "Administrator", "User" };

            foreach (var role in roles)
            {
                if (!await _roleManager.RoleExistsAsync(role))
                {
                    await _roleManager.CreateAsync(new IdentityRole(role));
                }
            }
        }
    }
}

Program.cs:

var builder = WebApplication.CreateBuilder(args);

// Add services to the container.
builder.Services.AddControllersWithViews();

// Register RoleManager and Identity services
builder.Services.AddIdentity<IdentityUser, IdentityRole>()
    .AddEntityFrameworkStores<ApplicationDbContext>()
    .AddDefaultTokenProviders();

// Register the RoleInitializer service
builder.Services.AddScoped<RoleInitializer>();

var app = builder.Build();

// Configure the HTTP request pipeline.
if (!app.Environment.IsDevelopment())
{
    app.UseExceptionHandler("/Home/Error");
    app.UseHsts();
}

app.UseHttpsRedirection();
app.UseStaticFiles();

app.UseRouting();

app.UseAuthentication();
app.UseAuthorization();

app.MapControllerRoute(
    name: "default",
    pattern: "{controller=Home}/{action=Index}/{id?}");

// Call the RoleInitializer during application startup
using (var scope = app.Services.CreateScope())
{
    var roleInitializer = scope.ServiceProvider.GetRequiredService<RoleInitializer>();
    await roleInitializer.InitializeRolesAsync();
}

app.Run();
Sign up to request clarification or add additional context in comments.

2 Comments

InvalidOperationException: Cannot consume scoped service 'Microsoft.AspNetCore.Identity.RoleManager`1[Microsoft.AspNetCore.Identity.IdentityRole]' from singleton 'Microsoft.Extensions.Hosting.IHostedService'.
@Tomm could you try the updated code. you are getting this error because\ the RoleManager<IdentityRole> is registered with a scoped lifetime, but IHostedService has a singleton lifetime.

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.