Unable to resolve service for type 'Microsoft.AspNetCore.Identity.UserManager` while attempting to activate 'AuthController'
Asked Answered
F

10

173

I'm getting this error in Login Controller.

InvalidOperationException: Unable to resolve service for type 'Microsoft.AspNetCore.Identity.UserManager`1[Automobile.Models.Account]' while attempting to activate 'Automobile.Server.Controllers.AuthController'.

here is Auth Controller constructor:

private SignInManager<Automobile.Models.Account> _signManager;
    private UserManager<Automobile.Models.Account> _userManager;

    public AuthController(UserManager<Models.Account> userManager,
                          SignInManager<Automobile.Models.Account> signManager)
    {
        this._userManager = userManager;
        this._signManager = signManager;
    }

and here is ConfigureServices in startup.cs:

public void ConfigureServices(IServiceCollection services)
    {
        // Add framework services.
        services.AddApplicationInsightsTelemetry(Configuration);
        services.Configure<AppConfig>(Configuration.GetSection("AppSettings"));

        //var provider = HttpContext.ApplicationServices;
        //var someService = provider.GetService(typeof(ISomeService));


        services.AddDbContext<Providers.Database.EFProvider.DataContext>(options => options
            .UseSqlServer(Configuration.GetConnectionString("DefaultConnection"),
                 b => b.MigrationsAssembly("Automobile.Server")
            ));


        services.AddIdentity<IdentityUser, IdentityRole>(options =>
        {
            options.User.RequireUniqueEmail = false;
        })
        .AddEntityFrameworkStores<Providers.Database.EFProvider.DataContext>()
        .AddDefaultTokenProviders(); 
        //services.AddScoped<SignInManager<Automobile.Models.Account>, SignInManager<Automobile.Models.Account>>();
        //services.AddScoped<UserManager<Automobile.Models.Account>, UserManager<Automobile.Models.Account>>();

        services.AddMvc();
        App.Service = services.BuildServiceProvider();

        // Adds a default in-memory implementation of IDistributedCache.
        services.AddDistributedMemoryCache();

        services.AddSession(options =>
        {
            // Set a short timeout for easy testing.
            options.IdleTimeout = TimeSpan.FromSeconds(10);
            options.CookieHttpOnly = true;
        });

    }
Florilegium answered 11/6, 2017 at 11:57 Comment(7)
It seems to me that you are registering IdentityUser as basic user class but then you are using Automobile.Models.Account, which, of course, is not registered anywhere by ASP.NET IdentityBarris
@FedericoDipuma Thank you so much :) Solved.Florilegium
How did you solved it.. ?Cilurzo
@Lobato in services.AddIdentity just replace IdentityUser with your Identity User classFlorilegium
@Florilegium why don't you post your comment as answer, this saved me but after some serious headache of RnD..Cookgeneral
Does this answer your question? Dependency Injection error: Unable to resolve service for type while attempting to activate, while class is registeredClinton
Add this - builder.Services.AddIdentity<ApplicationUser, IdentityRole>() .AddEntityFrameworkStores<CheersDbContext>() .AddDefaultTokenProviders();Vanvanadate
A
163

You need to use the same user data model in SignInManager, UserManager and services.AddIdentity. Same principal is true if you are using your own custom application role model class.

So, change

services.AddIdentity<IdentityUser, IdentityRole>(options =>
    {
        options.User.RequireUniqueEmail = false;
    })
    .AddEntityFrameworkStores<Providers.Database.EFProvider.DataContext>()
    .AddDefaultTokenProviders();

to

services.AddIdentity<Automobile.Models.Account, IdentityRole>(options =>
    {
        options.User.RequireUniqueEmail = false;
    })
    .AddEntityFrameworkStores<Providers.Database.EFProvider.DataContext>()
    .AddDefaultTokenProviders();
Assibilate answered 3/1, 2018 at 9:32 Comment(4)
I have the similar problem, I have my customer user and role defined in the AddIdentity method and I'm still getting the same error. Any idea why? I could post my code in a separate thread.Menchaca
Actually, I resolved that issue, but now facing a problem with creating the DB connection. I'll post the problem.Menchaca
#48161967Menchaca
seems your connection string has been not set correctly, check out my answer in your post.Assibilate
G
85

Just to be clear about the answer:

If you use the class ApplicationUser in startup.cs: services.AddIdentity<ApplicationUser, IdentityRole>()

then you must use the same class in your controller when injecting it:

public AccountController(UserManager<ApplicationUser> userManager)

If you use some other class such as:

public AccountController(UserManager<IdentityUser> userManager)

then you will get this error:

InvalidOperationException: Unable to resolve service for type 'Microsoft.AspNetCore.Identity.UserManager`1[IdentityUser]'

because you used ApplicationUser in startup, not IdentityUser so this type is not registered with the injection system.

Gibbeon answered 3/2, 2018 at 14:45 Comment(2)
This counts for all references, so if you implement the new Razor identity for asp.net core 2.1 to replace your old identitysystem, you need to replace their automatic implementation of stuff like SignInManager<IdentityUser> to SignInManager<ApplicationUser> wherever it is used. This can be annoying. Also you need to re-route from normal /Account/Login to /Identity/Account/Login etc. just some tips to help ;)Scutch
This should not be the accepted answer but it should be here and highlighted. I spent two hours trying to figure it out before I realized that the stupid ass me used default class for the user identity. Well, "realized" as in "read your answer". :)Balthazar
D
42

This is a bit unrelated to the original post but since Google brings you here... if you are getting this error and are using:

services.AddIdentityCore<YourAppUser>()

Then you will need to manually register the stuff that AddIdentity does, which can be found here: https://github.com/aspnet/Identity/blob/feedcb5c53444f716ef5121d3add56e11c7b71e5/src/Identity/IdentityServiceCollectionExtensions.cs#L79

        services.AddHttpContextAccessor();
        // Identity services
        services.TryAddScoped<IUserValidator<TUser>, UserValidator<TUser>>();
        services.TryAddScoped<IPasswordValidator<TUser>, PasswordValidator<TUser>>();
        services.TryAddScoped<IPasswordHasher<TUser>, PasswordHasher<TUser>>();
        services.TryAddScoped<ILookupNormalizer, UpperInvariantLookupNormalizer>();
        services.TryAddScoped<IRoleValidator<TRole>, RoleValidator<TRole>>();
        // No interface for the error describer so we can add errors without rev'ing the interface
        services.TryAddScoped<IdentityErrorDescriber>();
        services.TryAddScoped<ISecurityStampValidator, SecurityStampValidator<TUser>>();
        services.TryAddScoped<ITwoFactorSecurityStampValidator, TwoFactorSecurityStampValidator<TUser>>();
        services.TryAddScoped<IUserClaimsPrincipalFactory<TUser>, UserClaimsPrincipalFactory<TUser, TRole>>();
        services.TryAddScoped<UserManager<TUser>>();
        services.TryAddScoped<SignInManager<TUser>>();
        services.TryAddScoped<RoleManager<TRole>>();

You'll need to replace TUser and TRole with your implementations of those, or the default IdentityUser, IdentityRole

Discuss answered 11/6, 2019 at 20:25 Comment(6)
Had to create a custom SignInManager and this fixed it, if you plan on doing so check github.com/dotnet/docs/issues/14828Epilate
I originally started down this route but found the solution here (https://mcmap.net/q/144749/-asp-net-core-3-1-1-jwt-redirects-instead-of-returning-http-status-401-after-migration-from-asp-net-core-2-2) more straight forward; The only change I had to make (after re-ordering AddIdentity and AddJwtBearer was to set all three options shown in the example; I'd only been using DefaultAuthenticationScheme. I still get the cookie back on login, but [Authorize] now works for the JWT tokens without specifying an AuthenticationSchema.Arbour
This is exactly what I was missing. Adding TryAddScoped<UserManager<TUser>>(); and services.TryAddScoped<SignInManager<TUser>>(); to my Startup.cs fixed my issue.Shipboard
Note that some of these are already registered - IdentityCore skips e.g. SignInManager / RoleManagerPennywise
I think solution I added below is simpler in this scenario and worked for me.Laflamme
I'm using .net 6 and had to add IUserStore, IRoleStore, and ISystemClock as well. Full code in my answer below.Idiopathy
E
11

You can set IdentityUser and IdentityRole in ConfigureServices inside Startup class individually as shown below:

services.AddDefaultIdentity<IdentityUser>()
    .AddRoles<IdentityRole>()
    .AddEntityFrameworkStores<ApplicationDbContext>();

OR

you can configure directly into AddIdentity:

services.AddIdentity<IdentityUser, IdentityRole>()
        .AddEntityFrameworkStores<ApplicationDbContext>();
Egad answered 7/4, 2020 at 14:28 Comment(1)
With a code only answer, OP and others will hardly learn about the problem, consider editing your answer and adding an explanationHeadland
O
6

don't forget to add role manager in ConfigureServices

services.AddDefaultIdentity<IdentityUser>()
    .AddRoles<IdentityRole>() // <--------
    .AddDefaultUI(UIFramework.Bootstrap4)
    .AddEntityFrameworkStores<ApplicationDbContext>();
Opprobrious answered 2/7, 2019 at 9:27 Comment(0)
S
1

For me, the order of the services being added was important in Dot.Net Core 7.

This code in program.cs resulted in the error:

builder.Services.AddDefaultIdentity<IdentityUser>(options => options.SignIn.RequireConfirmedAccount = true)
    .AddEntityFrameworkStores<ApplicationDbContext>()
    .AddRoles<IdentityRole>();

Here the same statements are flipped. This code works fine:

builder.Services.AddDefaultIdentity<IdentityUser>(options => options.SignIn.RequireConfirmedAccount = true)
    .AddRoles<IdentityRole>()
    .AddEntityFrameworkStores<ApplicationDbContext>();
Subbase answered 10/4, 2023 at 14:30 Comment(0)
Q
0

If you're using "IdentityServer" so IdentityServer authenticates the user and authorizes the client.By default, IdentityServer is actually not about user management. But there is some support for asp.net Identity

So you need add :

services.AddIdentityServer()
    .AddAspNetIdentity<ApplicationUser>();
Quickstep answered 21/3, 2020 at 22:55 Comment(0)
W
0

You need to update your Statup.cs class with below

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

Here : ApplicationUser is my custom model class.

Woodall answered 13/9, 2020 at 23:46 Comment(0)
L
0

This is a bit unrelated to the original post as the answer above but since Google brings you here... and this is a simpler solution, if you are getting this error and are using:

services.AddIdentityCore()

There is an easier solution than the answer listed above like this one.

Lets say you have a custom IdentityUser named ApplicationUser and a custom role named ApplicationRole you can simply use below to work.

builder
    .Services
    .AddIdentityCore<ApplicationUser>(identityOptions =>
                                      {
                                          identityOptions.Lockout = new LockoutOptions
                                          {
                                              DefaultLockoutTimeSpan = TimeSpan.FromMinutes(30)
                                              , MaxFailedAccessAttempts = 20
                                          };

                                          identityOptions.Password = new PasswordOptions
                                          {
                                              RequireDigit = true
                                              , RequireLowercase = true
                                              , RequireNonAlphanumeric = true
                                              , RequireUppercase = true
                                              , RequiredLength = 8
                                          };

                                          identityOptions.SignIn = new SignInOptions
                                          {
                                              RequireConfirmedAccount = true
                                              , RequireConfirmedEmail = true
                                          };

                                          identityOptions.User = new UserOptions
                                          {
                                              AllowedUserNameCharacters = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ.@1234567890!#$%&'*+-/=?^_`{|}~"
                                              , RequireUniqueEmail = true
                                          };
                                      })
    .AddRoles<ApplicationRole>()
    .AddClaimsPrincipalFactory<UserClaimsPrincipalFactory<ApplicationUser, ApplicationRole>>()
    .AddEntityFrameworkStores<ApplicationDbContext>()
    .AddDefaultTokenProviders();

This is much simpler.

Also it appears from microsoft documentation you have to declare your DbContext like so for it to infer.

public class ApplicationDbContext
    : IdentityDbContext<ApplicationUser
        , ApplicationRole
        , long
        , ApplicationUserClaim
        , ApplicationUserRole
        , ApplicationUserLogin
        , ApplicationRoleClaim
        , ApplicationUserToken>
{
}

Of course don't have to use custom types I am using here and can use defaults etc.

Laflamme answered 8/12, 2022 at 20:55 Comment(1)
oh, this is a good answer for everyone to use services.AddIdentityCore()Monocotyledon
I
-1

Similar to the above answer, but I had to add IUserStore and IRoleStore. Additionally, the security stamp validator complains that ISystemClock (available from Microsoft.AspNetCore.Authentication) is not registered, so that is here too.

The types below are named after the standard Identity database tables (dbo.AspNetUsers, dbo.AspNetRoles, etc). The Guid type below is the primary key type for these tables. By default this is string so adjust to your model accordingly.

/* begin services to support app custom identity */

// Add the system clock service
services.AddSingleton<ISystemClock, SystemClock>();

services.TryAddScoped<
    IUserStore<AspNetUser>,
    UserStore<AspNetUser, AspNetRole, ApplicationDbContext, Guid, AspNetUserClaim, AspNetUserRole, AspNetUserLogin, AspNetUserToken, AspNetRoleClaim>>();

services.TryAddScoped<
    IRoleStore<AspNetRole>,
    RoleStore<AspNetRole, ApplicationDbContext, Guid, AspNetUserRole, AspNetRoleClaim>>();

// Identity services
services.TryAddScoped<IUserValidator<AspNetUser>, UserValidator<AspNetUser>>();
services.TryAddScoped<IPasswordValidator<AspNetUser>, PasswordValidator<AspNetUser>>();
services.TryAddScoped<IPasswordHasher<AspNetUser>, PasswordHasher<AspNetUser>>();
services.TryAddScoped<ILookupNormalizer, UpperInvariantLookupNormalizer>();
services.TryAddScoped<IRoleValidator<AspNetRole>, RoleValidator<AspNetRole>>();
// No interface for the error describer so we can add errors without rev'ing the interface
services.TryAddScoped<IdentityErrorDescriber>();
services.TryAddScoped<ISecurityStampValidator, SecurityStampValidator<AspNetUser>>();
services.TryAddScoped<ITwoFactorSecurityStampValidator, TwoFactorSecurityStampValidator<AspNetUser>>();
services.TryAddScoped<IUserClaimsPrincipalFactory<AspNetUser>, UserClaimsPrincipalFactory<AspNetUser, AspNetRole>>();
services.TryAddScoped<IUserConfirmation<AspNetUser>, DefaultUserConfirmation<AspNetUser>>();
services.TryAddScoped<UserManager<AspNetUser>>();
services.TryAddScoped<SignInManager<AspNetUser>>();
services.TryAddScoped<RoleManager<AspNetRole>>();

/* end services to support app custom identity */
Idiopathy answered 23/12, 2022 at 17:50 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.