1

I want to have a refreshed UserManager object after my DbContext changed with new connectionString inside the Controller, I have injected the UserManager in the Controller but it's obvious that it will always have the last DbContext reference from DI, not to the newly created dbcontext.

I have tried like below.

this.DbContext = new ApplicationDbContext(Configuration, optionsBuilder.Options);
this._userManager = new UserManager<ApplicationUser>(new UserStore<ApplicationUser>(DbContext), null, new PasswordHasher<ApplicationUser>(), null, null, null, null, null, null);

It works fine but it lacking most of the UserManager functionality like _userManager.CheckPasswordAsync(user, loginModel.Password) as I'm passing most of the parameter as null. What should I do to get a fully working UserManger with new DbContext in simplest way?

Sabir Hossain
  • 1,183
  • 1
  • 25
  • 46

2 Answers2

1

You can try to create a service and use the UserManger in the service, then, configure the service using the Transient operations in the Startup.ConfigureServices method. The Transient operations are always different, a new instance is created with every retrieval of the service. Then, you could use this service in the controller. Please check the following steps:

create a UserManagerRepository service (in this service you can create methods and use the UserManager methods):

public interface IUserManagerRepository
{
    void Write(string message);
}
public class UserManagerRepository : IUserManagerRepository, IDisposable
{
    private bool _disposed;
    private readonly UserManager<IdentityUser> _userManager;

    public UserManagerRepository(UserManager<IdentityUser> userManager)
    {
        _userManager = userManager;
    }

    public void Write(string message)
    {
        // _userManager.ChangePasswordAsync()
        Console.WriteLine($"UserManagerRepository: {message}");
    }

    public void Dispose()
    {
        if (_disposed)
            return;

        Console.WriteLine("UserManagerRepository.Dispose");
        _disposed = true;
    }
}

Confiture the service using the following code in the Startup.ConfigureServices method:

 services.AddTransient<IUserManagerRepository, UserManagerRepository>();

After that, call the services manually in the controller action method.

    public IActionResult Index()
    {
        var services = this.HttpContext.RequestServices;
        var log = (IUserManagerRepository)services.GetService(typeof(IUserManagerRepository));

        log.Write("Index method executing");
         
        var log2 = (IUserManagerRepository)services.GetService(typeof(IUserManagerRepository));

        log2.Write("Index method executing");
        var log3 = (IUserManagerRepository)services.GetService(typeof(IUserManagerRepository));

        log3.Write("Index method executing"); 
        return View();
    }

screenshot as below:

enter image description here

Reference:

Tutorial: Use dependency injection in .NET

Dependency injection guidelines

Dependency injection in ASP.NET Core

Zhi Lv
  • 18,845
  • 1
  • 19
  • 30
  • so after calling the service again the userManager will be initialized with the newly created AppDbContext? – Sabir Hossain Dec 29 '20 at 12:26
  • the _userManager still holds reference to the old dbContext, the new dbContext has a different connectionString – Sabir Hossain Dec 29 '20 at 12:46
  • @SabirHossain of course, because the code injects `UserManager` which is provided by the identity model, that still depends on the configured `DbContext` (in your app startup). This answer is definitely not what you want. – Hopeless Dec 29 '20 at 17:38
  • I knew that, @Hopeless what can I do to refresh the UserManger with the newly created DbContext, you can see how I'm doing that but I need a fully functional UserManager – Sabir Hossain Dec 30 '20 at 11:38
-1

Use Dependency Injection, that's how all of the mentioned tools are meant to be consumed.

private DbContext DbContext { get;}

private UserManager<IdentityUser> UserManager { get; } 

public MyController(DbContext dbContext, UserManager<IdentityUser> userManager)
{
    DbContext = dbContext;
    UserManager = userManager;
}

https://learn.microsoft.com/en-us/aspnet/core/fundamentals/dependency-injection?view=aspnetcore-5.0

And here's a page on how to setup Dependency Injection for EF Core:

https://learn.microsoft.com/en-us/ef/core/dbcontext-configuration/#dbcontext-in-dependency-injection-for-aspnet-core

Assuming you already have services.AddDefaultIdentity(...) and services.AddDbContext(...), injecting of UserManager and YourProjectDbContext should inherently just work in your Controllers.