简体   繁体   中英

User Manager for console app without Dependency Injection

I am trying to use the User Manager for a C# console app in .NET 6 without the help of dependency injection. I manage to construct an instance of the User Manager but when I get to using it (create an email with password reset for my users), I get this error:

No IUserTwoFactorTokenProvider named 'Default' is registered.

Here is where I initialize the User Manager in Program.cs :

IConfiguration config = new ConfigurationBuilder()
         .SetBasePath(Directory.GetCurrentDirectory())
         .AddJsonFile("appsettings.json", optional: true, reloadOnChange: true)
         .AddEnvironmentVariables()
         .Build();

IServiceCollection services = new ServiceCollection();
services.AddTransient<UserManager<ApplicationUser>>();

var connectionStrings = config.GetSection("ConnectionStrings");
var messagingConnectionString = connectionStrings.GetValue<string>("Messaging");

AgentConfigDTO appSettingsDTO = new AgentConfigDTO()
        {
           ....
        };

services.AddDbContext<ApplicationDbContext>(options =>
            options.UseSqlServer(connectionStrings.ToString(),
            sqlServerOptionsAction: sqlOptions =>
            {
                sqlOptions.EnableRetryOnFailure(
                            maxRetryCount: 5,
                            maxRetryDelay: TimeSpan.FromSeconds(30),
                            errorNumbersToAdd: null);
            }
            ));

// Register UserManager & RoleManager
services.AddIdentity<IdentityUser, IdentityRole>();
services.AddIdentity<ApplicationUser, IdentityRole>(
            options =>
            {
                options.Tokens.ProviderMap.Add("Default", new TokenProviderDescriptor(typeof(IUserTwoFactorTokenProvider<ApplicationUser>)));
            })
           .AddEntityFrameworkStores<ApplicationDbContext>()
           .AddDefaultTokenProviders();

services.AddTransient<IUserStore<IdentityUser>, UserStore<IdentityUser>>();
services.AddTransient<UserManager<IdentityUser>>();

IServiceProvider serviceProvider = services.BuildServiceProvider();

var optionsBuilderApplication = new DbContextOptionsBuilder<ApplicationDbContext>();
var _applicationContext = new ApplicationDbContext(optionsBuilderApplication.UseSqlServer(connectionStrings.ToString()).Options);
     
IUserStore<ApplicationUser> store = new UserStore<ApplicationUser>(_applicationContext);
UserManager<ApplicationUser> userManager = new UserManager<ApplicationUser>(store, null, new PasswordHasher<ApplicationUser>(), null, null, null, null, serviceProvider, null);

// UserManager & RoleManager require logging and HttpContext dependencies
services.AddLogging();
services.AddSingleton<IHttpContextAccessor, HttpContextAccessor>();

new ReportAgent(appSettingsDTO, messagingConnectionString, userManager).RunAsConsole(args);

And this is the method that runs the User Manager:

public void CheckingPasswords()
{
     try
     {               
         var date = DateTime.Now.AddMonths(-3);
         var userList = _applicationContext.Users.Where(t => t.PasswordExpiry != null && t.PasswordExpiry <= DateTime.Now.AddMonths(-3) && t.Deleted == false && t.PortalAccessEnabled == true).ToList();

         if (userList.Count > 0)
         {
             // Create email
             foreach (var user in userList)
             {
                 // Lock user out of the account
                 user.PortalAccessEnabled = false;
                 _applicationContext.Update(user);
                 _applicationContext.SaveChanges();

                 // Create email
                 // Exception is thrown on this line of code
                 var code = _userManager.GeneratePasswordResetTokenAsync(user).ToString(); 
                 var url = .
                 var callbackUrl = url.Replace("[[id]]", user.Id).Replace("[[code]]", code);

                 Email email = new()
                        {
                            ...
                        };
                 _dbContext.Add(email);
                 _dbContext.SaveChanges();
             }
         }
     }
}

I am now stuck with this and have no idea how to fix it.

I've also tried manually adding in the Token Provider but that didn't make any difference:

var identityBuilder = new IdentityBuilder(typeof(ApplicationUser), typeof(IdentityRole<string>), services);
identityBuilder.AddTokenProvider("Default", typeof(DataProtectorTokenProvider<ApplicationUser>));
services.AddTransient<UserManager<ApplicationUser>>();

The error message "No IUserTwoFactorTokenProvider named 'Default' is registered" is because you are missing the configuration for the default two-factor token provider. To resolve this, you need to register the default two-factor token provider for UserManager in the services collection.

public class Startup
{
    public Startup(IConfiguration configuration)
    {
        Configuration = configuration;
    }

    public IConfiguration Configuration { get; }

    public void ConfigureServices(IServiceCollection services)
    {
        services.AddDbContext<ApplicationDbContext>(options =>
            options.UseSqlServer(Configuration.GetConnectionString("DefaultConnection")));

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

        services.AddTransient<IUserStore<ApplicationUser>, UserStore<ApplicationUser>>();
        services.AddTransient<UserManager<ApplicationUser>>();

        services.AddLogging();
        services.AddHttpContextAccessor();
    }
}

public class ConsoleApp
{
    private readonly UserManager<ApplicationUser> _userManager;
    private readonly ApplicationDbContext _applicationContext;

    public ConsoleApp(UserManager<ApplicationUser> userManager, ApplicationDbContext applicationContext)
    {
        _userManager = userManager;
        _applicationContext = applicationContext;
    }

    public void CheckingPasswords()
    {
        try
        {               
            var date = DateTime.Now.AddMonths(-3);
            var userList = _applicationContext.Users.Where(t => t.PasswordExpiry != null && t.PasswordExpiry <= DateTime.Now.AddMonths(-3) && t.Deleted == false && t.PortalAccessEnabled == true).ToList();

            if (userList.Count > 0)
            {
                //Create email
                foreach (var user in userList)
                {
                    // Lock user out of the account
                    user.PortalAccessEnabled = false;
                    _applicationContext.Update(user);
                    _applicationContext.SaveChanges();

                    //Create email

                    var code = _userManager.GeneratePasswordResetTokenAsync(user).Result;
                    var url = .
                    var callbackUrl = url.Replace("[[id]]", user.Id).Replace("[[code]]", code);

                    Email email = new()
                    {
                        ...
                    };
                    _dbContext.Add(email);
                    _dbContext.SaveChanges();
                }
            }
        }
    }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM