I want my ApplicationContext
constructor to have the UserManager
as a parameter, but I am having trouble with dependency injection.
Code:
public class ApplicationContext : IdentityDbContext<ApplicationUser>
{
private IHttpContextAccessor _contextAccessor { get; set; }
public ApplicationUser ApplicationUser { get; set; }
private UserManager<ApplicationUser> _userManager;
public ApplicationContext(DbContextOptions<ApplicationContext> options, IHttpContextAccessor contextAccessor, UserManager<ApplicationUser> userManager)
: base(options)
{
_contextAccessor = contextAccessor;
var user = _contextAccessor.HttpContext.User;
_userManager = userManager;
ApplicationUser = _userManager.Users.FirstOrDefault(u => u.Id == _userManager.GetUserId(user));
}
}
And in startup.cs
:
public void ConfigureServices(IServiceCollection services)
{
// Add framework services.
services.AddDbContext<ApplicationContext>(options =>
options.UseSqlServer(Configuration.GetConnectionString("DefaultConnection"), b => b.MigrationsAssembly("RCI.App")));
services.AddIdentity<ApplicationUser, IdentityRole>()
.AddEntityFrameworkStores<ApplicationContext>()
.AddDefaultTokenProviders();
services.AddAuthentication();
services.AddMvc();
// Add application services.
services.AddTransient<IEmailSender, AuthMessageSender>();
services.AddTransient<ISmsSender, AuthMessageSender>();
services.AddTransient<IHttpContextAccessor, HttpContextAccessor>();
services.AddOptions();
}
Error message:
A circular dependency was detected for the service of type 'Microsoft.AspNetCore.Identity.UserManager`1[RCI.App.Models.ApplicationUser]'.
Could anyone point out what I'm doing wrong?
To resolve circular dependencies: Then there are three strategies you can use: Look for small pieces of code that can be moved from one project to the other. Look for code that both libraries depend on and move that code into a new shared library. Combine projectA and projectB into one library.
A circular or cyclic dependency is a situation where two or more independent modules or components rely on each other to function properly. This is referred to as mutual recursion. Circular dependency generally occurs in a modular framework while defining a dependency between modules or components.
A circular dependency was detected for the service of type 'UserService'. UserService -> PhoneService -> UserService. It even directly points out the exact services which depend on each other. Note that in some cases, the circle could be much larger.
ASP.NET Core supports the dependency injection (DI) software design pattern, which is a technique for achieving Inversion of Control (IoC) between classes and their dependencies. For more information specific to dependency injection within MVC controllers, see Dependency injection into controllers in ASP.NET Core.
If you don't actually need the UserManager
in the constructor, you can store a reference to the IServiceProvider
instead:
private IHttpContextAccessor _contextAccessor { get; set; }
public ApplicationUser ApplicationUser { get; set; }
private IServiceProvider _services;
public ApplicationContext(DbContextOptions<ApplicationContext> options,
IHttpContextAccessor contextAccessor, IServiceProvider services)
: base(options)
{
_contextAccessor = contextAccessor;
var user = _contextAccessor.HttpContext.User;
_services = services;
}
Then later, when you actually need the ApplicationUser
, call e.g. GetRequiredService<ApplicationUser>()
(defined in Microsoft.Extensions.DependencyInjection
):
var manager = _services.GetRequiredService<UserManager<ApplicationUser>>();
var user = manager.Users.FirstOrDefault(u => u.Id == _userManager.GetUserId(user));
Of course, you can use a Lazy<T>
to lazy-load the manager or user the first time and then store a reference to it.
In general, @poke is correct about re-architecting to avoid such circular dependencies, but leaving this answer here in case someone else has a similar problem and refactoring isn't an option.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With